···2424 in
2525 match names with [] -> check_language () | _ :: _ -> check_name ()
26262727-let print oc line_directives location value =
2727+let print line_directives oc location value =
2828 if line_directives then (
2929- Printf.fprintf oc "#%d \"%s\"\n" (location.Loc.start.line + 1) location.file;
2929+ Printf.fprintf oc "#%d \"%s\"\n" location.Loc.start.line location.file;
3030 Printf.fprintf oc "%s%s\n"
3131- (String.v ~len:(location.start.column + 1) (fun _ -> ' '))
3131+ (String.v ~len:location.start.column (fun _ -> ' '))
3232 value)
3333 else Printf.fprintf oc "%s" value
3434···3737 | `Verbatim _ | `Modules _ | `Math_block _ | `Media _ | `Paragraph _ -> ()
3838 | `Code_block { Ast.content = { value; location }; meta; _ }
3939 when needs_extraction names meta ->
4040- print oc line_directives location value
4040+ print line_directives oc location value
4141 | `Code_block _ -> ()
4242 | `List (_, _, l) ->
4343 List.iter (List.iter (nestable_block_element line_directives oc names)) l
···4747 List.iter (nestable_block_element line_directives oc names) x))
4848 table
49495050-and block_element line_directives oc names v =
5050+let block_element line_directives oc names v =
5151 match v.Loc.value with
5252 | `Tag
5353 ( `Deprecated l
···6666 | #Ast.nestable_block_element as value ->
6767 nestable_block_element line_directives oc names { v with value }
68686969-let extract ~dst ~input ~names ~line_directives =
6969+let pad_loc loc =
7070+ { loc.Location.loc_start with pos_cnum = loc.loc_start.pos_cnum + 3 }
7171+7272+let iterator line_directives oc names =
7373+ let attribute _ attr =
7474+ match Odoc_loader.parse_attribute attr with
7575+ | None | Some (`Stop _ | `Alert _) -> ()
7676+ | Some (`Text (doc, loc) | `Doc (doc, loc)) ->
7777+ let ast_docs =
7878+ Odoc_parser.parse_comment ~location:(pad_loc loc) ~text:doc
7979+ in
8080+ let ast = Odoc_parser.ast ast_docs in
8181+ List.iter (block_element line_directives oc names) ast
8282+ in
8383+ (* For some reason, Tast_iterator.default_iterator does not recurse on
8484+ Tsig_attribute and on attributes... *)
8585+ let signature_item sub sig_ =
8686+ match sig_.Typedtree.sig_desc with
8787+ | Tsig_attribute attr -> attribute sub attr
8888+ | _ -> Tast_iterator.default_iterator.signature_item sub sig_
8989+ in
9090+ let attributes sub attrs = List.iter (attribute sub) attrs in
9191+ { Tast_iterator.default_iterator with attribute; attributes; signature_item }
9292+9393+let load_cmti line_directives oc names input =
9494+ let cmt_info = Cmt_format.read_cmt input in
9595+ match cmt_info.cmt_annots with
9696+ | Interface intf ->
9797+ let iterator = iterator line_directives oc names in
9898+ iterator.signature iterator intf
9999+ | _ -> failwith "TODO"
100100+101101+let load_mld line_directives oc names input =
70102 let location =
7171- { Lexing.pos_fname = input; pos_lnum = 0; pos_bol = 0; pos_cnum = 0 }
103103+ { Lexing.pos_fname = input; pos_lnum = 1; pos_bol = 0; pos_cnum = 0 }
72104 in
73105 let c = Io_utils.read_lines input |> String.concat ~sep:"\n" in
74106 let parsed = parse_comment ~location ~text:c in
75107 let ast = ast parsed in
7676- let go oc = List.iter (block_element line_directives oc names) ast in
7777- match dst with None -> go stdout | Some dst -> Io_utils.with_open_out dst go
108108+ List.iter (block_element line_directives oc names) ast
109109+110110+let extract ~dst ~input ~names ~line_directives =
111111+ let loader =
112112+ match input |> Fpath.v |> Fpath.get_ext with
113113+ | ".mld" -> load_mld
114114+ | ".cmti" -> load_cmti
115115+ | _ -> failwith "TODO"
116116+ in
117117+ match dst with
118118+ | None -> loader line_directives stdout names input
119119+ | Some dst ->
120120+ Io_utils.with_open_out dst @@ fun oc ->
121121+ loader line_directives oc names input
+25
test/extract_code/cmti_extraction.t/main.mli
···11+(** {[
22+ let x = 1
33+ ]} *)
44+55+val x : int
66+[@@deriving none]
77+(** {[
88+ let () =
99+ print_int x;
1010+ print_newline ()
1111+ ]} *)
1212+1313+module A : sig
1414+ val x : int
1515+ (** {[
1616+ let hello = 2
1717+ ]} *)
1818+end
1919+2020+type t =
2121+ | A of int
2222+ (** {[
2323+ let _ = hello +. hello
2424+ ]} *)
2525+ | B of int
+29
test/extract_code/cmti_extraction.t/run.t
···11+ $ ocamlc -bin-annot main.mli
22+ $ odoc extract-code -o output.ml --line-directives main.cmti
33+44+ $ cat output.ml
55+ #1 "main.mli"
66+77+ let x = 1
88+99+ #7 "main.mli"
1010+1111+ let () =
1212+ print_int x;
1313+ print_newline ()
1414+1515+ #15 "main.mli"
1616+1717+ let hello = 2
1818+1919+ #22 "main.mli"
2020+2121+ let _ = hello +. hello
2222+2323+2424+ $ ocaml output.ml
2525+ 1
2626+ File "main.mli", line 23, characters 20-25:
2727+ Error: This expression has type "int" but an expression was expected of type
2828+ "float"
2929+ [2]
+11-11
test/extract_code/mld_extraction.t/run.t
···26262727 $ odoc extract-code --line-directives --name error.ml --name printing main.mld
2828 #18 "main.mld"
2929- let five = 5
2929+ let five = 5
3030 #20 "main.mld"
3131-3131+3232 let () = print_int five
33333434 #25 "main.mld"
3535-3535+3636 let y = five +. five (* This is a typing error *)
37373838···42424343 $ odoc extract-code --line-directives main.mld
4444 #5 "main.mld"
4545-4545+4646 (** By default, an odoc code block is assumed to contain OCaml code *)
4747 let () = ()
48484949 #18 "main.mld"
5050- let five = 5
5050+ let five = 5
5151 #20 "main.mld"
5252-5252+5353 let () = print_int five
54545555 #25 "main.mld"
5656-5656+5757 let y = five +. five (* This is a typing error *)
58585959···61616262 $ odoc extract-code --line-directives --name error.ml main.mld
6363 #18 "main.mld"
6464- let five = 5
6464+ let five = 5
6565 #25 "main.mld"
6666-6666+6767 let y = five +. five (* This is a typing error *)
68686969···7272 $ odoc extract-code --line-directives --name error.ml -o error.ml main.mld
7373 $ cat error.ml
7474 #18 "main.mld"
7575- let five = 5
7575+ let five = 5
7676 #25 "main.mld"
7777-7777+7878 let y = five +. five (* This is a typing error *)
79798080