(** Markup examples. *)

(** The OCaml manual gives a
    {{:https://ocaml.org/manual/ocamldoc.html#ss:ocamldoc-placement}comprehensive
     example} of comment placement. This has been replicated in the module Foo
    below to show how this is rendered by [odoc]. *)

module type Foo = sig
  (** The first special comment of the file is the comment associated with the
      whole module.*)

  (** Special comments can be placed between elements and are kept by the
      OCamldoc tool, but are not associated to any element. [@]-tags in these
      comments are ignored.*)

  (*******************************************************************)
  (** Comments like the one above, with more than two asterisks, are ignored. *)

  (** The comment for function f. *)
  val f : int -> int -> int
  (** The continuation of the comment for function f. *)

  (* Hello, I'm a simple comment :-) *)
  exception My_exception of (int -> int) * int
  (** Comment for exception My_exception, even with a simple comment between the
      special comment and the exception.*)

  (** Comment for type weather *)
  type weather =
    | Rain of int  (** The comment for constructor Rain *)
    | Sun  (** The comment for constructor Sun *)

  (** Comment for type weather2 *)
  type weather2 =
    | Rain of int  (** The comment for constructor Rain *)
    | Sun  (** The comment for constructor Sun *)
  (** I can continue the comment for type weather2 here because there is already
      a comment associated to the last constructor.*)

  (** The comment for type my_record *)
  type my_record = {
    foo : int;  (** Comment for field foo *)
    bar : string;  (** Comment for field bar *)
  }
  (** Continuation of comment for type my_record *)

  (** Comment for foo *)
  val foo : string
  (** This comment is associated to foo and not to bar. *)

  val bar : string
  (** This comment is associated to bar. *)

  class cl : object
    (** Interesting information about cl *)
  end

  (** The comment for class my_class *)
  class my_class : object
    inherit cl
    (** A comment to describe inheritance from cl *)

    val mutable tutu : string
    (** The comment for attribute tutu *)

    val toto : int
    (** The comment for attribute toto. *)

    (** This comment is not attached to titi since there is a blank line before
        titi, but is kept as a comment in the class. *)

    val titi : string

    method toto : string
    (** Comment for method toto *)

    method m : float -> int
    (** Comment for method m *)
  end

  (** The comment for the class type my_class_type *)
  class type my_class_type = object
    val mutable x : int
    (** The comment for variable x. *)

    method m : int -> int
    (** The comment for method m. *)
  end

  (** The comment for module Foo *)
  module Foo : sig
    val x : int
    (** The comment for x *)

    (** A special comment that is kept but not associated to any element *)
  end

  (** The comment for module type my_module_type. *)
  module type my_module_type = sig
    val x : int
    (** The comment for value x. *)

    (** The comment for module M. *)
    module M : sig
      val y : int
      (** The comment for value y. *)

      (* ... *)
    end
  end
end

module Stop : sig
  (** This module demonstrates the use of stop comments ([(**/**)]) *)

  class type foo = object
    method m : string
    (** comment for method m *)

    (**/**)

    method bar : int
    (** This method won't appear in the documentation *)
  end

  val foo : string
  (** This value appears in the documentation, since the Stop special comment in
      the class does not affect the parent module of the class.*)

  (**/**)

  val bar : string
  (** The value bar does not appear in the documentation.*)

  (**/**)

  type t = string
  (** The type t appears since in the documentation since the previous stop
      comment toggled off the "no documentation mode". *)
end

(** {2 Scoping rules} *)
module Scope : sig
  (** In this floating comment I can refer to type {!t} and value {!v} declared
      later in the signature *)

  type t

  val v : t

  val x : int

  val y : int

  module A : sig
    (** In this module I can refer to val {!x} declared above as well as type
        {!u} declared later in the parent module. Elements declared in this
        signature take priority, so {!y} refers to {!A.y} as opposed to the [y]
        declared in the parent signature.

        @see 'markup.mli' for a good time *)

    val y : string
  end

  type u
end

module Preamble_examples : sig
  (** This module demonstrates the various ways that preambles are calculated *)

  (** This is the comment attached to the declaration of Hidden__Module *)
  module Hidden__Module : sig
    (** This is the top comment declared in the module Hidden__module.

        This is the second paragraph in the module Hidden__module.

        @canonical Odoc_examples.Markup.Module *)

    type t
    (** This is a comment on type t *)
  end

  module Module = Hidden__Module
  (** This comment is on the declaration of Module as an alias of Hidden__Module
  *)

  (** This is the comment attached to the declaration of module Hidden__Module2
  *)
  module Hidden__Module2 : sig
    (** This is the top comment declared in the module Hidden__module2.

        This is the second paragraph in the module Hidden__module2.

        @canonical Odoc_examples.Markup.Module2 *)

    type t
    (** This is a comment on type t *)
  end

  module Module2 = Hidden__Module2

  module Nonhidden_module : sig
    (** This is the top comment declared in the module Hidden__module2.

        This is the second paragraph in the module Hidden__module2. *)
  end

  module Module3 = Nonhidden_module
  (** This comment is on the declaration of Module3 as an alias of
      Nonhidden_module *)

  module Nonhidden_module2 : sig
    (** This is the top comment declared in the module Hidden__module2.

        This is the second paragraph in the module Hidden__module2. *)
  end

  module Module4 = Nonhidden_module2

  (** The [modules] special reference can be used to refer to a list of modules.
      It uses the synopsis from the modules *)
end
