My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Wrap flattened include content in Stop markers

When flattening hidden includes, wrap the spliced items in
Comment `Stop markers so the document generator's skip-until-Stop
logic skips them. Without this, dunder-named items that were
previously hidden inside Include wrappers would be fully rendered
as top-level items, causing a 3x HTML size regression on base.

Also propagates skip_doc_parsing through nested read_signature calls
so that items inside stop blocks at any nesting depth have their doc
parsing skipped.

Result: HTML output for base drops from 188 MB to 19 MB (vs 145 MB
baseline). 869 empty dunder-named pages eliminated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+56 -15
+14 -3
odoc/src/loader/cmt.cppo.ml
··· 575 575 |> fst 576 576 |> List.rev 577 577 578 - and read_structure_item ~in_stop env parent item = 578 + and read_structure_item ~in_stop ~inherit_skip env parent item = 579 579 let open Signature in 580 580 match item.str_desc with 581 581 | Tstr_eval _ -> [] ··· 641 641 | Some (`Stop as doc) -> 642 642 incr flatten_total_stops; 643 643 in_stop := not !in_stop; 644 + Doc_attr.skip_doc_parsing := inherit_skip || !in_stop; 644 645 [Comment doc] 645 646 | Some doc -> [Comment doc] 646 647 ··· 689 690 && s.s_classes = [] && s.s_class_types = [] 690 691 in 691 692 if should_flatten && shadowed_empty then 692 - content.Signature.items 693 + Signature.Comment `Stop :: content.Signature.items @ [ Signature.Comment `Stop ] 693 694 else 694 695 let expansion = { content; shadowed; } in 695 696 match decl_modty with ··· 714 715 'tags. 'tags Odoc_model.Semantics.handle_internal_tags -> _ -> _ -> _ -> 715 716 _ * 'tags = 716 717 fun internal_tags env parent str -> 718 + let t_env = Sys.time () in 717 719 let e' = Env.add_structure_tree_items parent str env.ident_env in 720 + let t_env_done = Sys.time () in 718 721 let env = { env with ident_env=e' } in 719 722 let items, (doc, doc_post), tags = 720 723 let classify item = ··· 725 728 in 726 729 Doc_attr.extract_top_comment internal_tags ~warnings_tag:env.warnings_tag ~classify parent str.str_items 727 730 in 731 + let t_extract_done = Sys.time () in 732 + (match Sys.getenv_opt "ODOC_GC_STATS" with 733 + | Some s when s <> "" && s <> "0" && t_env_done -. t_env > 0.05 -> 734 + Printf.eprintf "ODOC_STRUCT_TIME add_env=%.3f extract_top=%.3f n_items=%d\n%!" 735 + (t_env_done -. t_env) (t_extract_done -. t_env_done) (List.length str.str_items) 736 + | _ -> ()); 728 737 let in_stop = ref false in 738 + let inherit_skip = !Doc_attr.skip_doc_parsing in 729 739 let item_times = ref [] in 730 740 let items = 731 741 List.fold_left 732 742 (fun items item -> 733 743 let t0 = Sys.time () in 734 - let result = read_structure_item ~in_stop env parent item in 744 + let result = read_structure_item ~in_stop ~inherit_skip env parent item in 735 745 let dt = Sys.time () -. t0 in 736 746 if dt > 0.1 then begin 737 747 let name = match item.str_desc with ··· 749 759 [] items 750 760 |> List.rev 751 761 in 762 + Doc_attr.skip_doc_parsing := inherit_skip; 752 763 (match Sys.getenv_opt "ODOC_GC_STATS" with 753 764 | Some s when s <> "" && s <> "0" -> 754 765 let sorted = List.sort (fun (_, a, _) (_, b, _) -> compare b a) !item_times in
+42 -12
odoc/src/loader/cmti.cppo.ml
··· 928 928 let open Module in 929 929 Alias (Env.Path.read_module env.ident_env p, None) 930 930 931 - and read_signature_item ~in_stop env parent item = 931 + and read_signature_item ~in_stop ~inherit_skip env parent item = 932 932 let open Signature in 933 933 match item.sig_desc with 934 934 | Tsig_value vd -> ··· 984 984 | Some (`Stop as doc) -> 985 985 incr flatten_total_stops; 986 986 in_stop := not !in_stop; 987 - Doc_attr.skip_doc_parsing := !in_stop; 987 + Doc_attr.skip_doc_parsing := inherit_skip || !in_stop; 988 988 [Comment doc] 989 989 | Some doc -> [Comment doc] 990 990 end ··· 1028 1028 let loc = Doc_attr.read_location incl.incl_loc in 1029 1029 let container = (parent : Identifier.Signature.t :> Identifier.LabelParent.t) in 1030 1030 let doc, status = Doc_attr.attached ~warnings_tag:env.warnings_tag Odoc_model.Semantics.Expect_status container incl.incl_attributes in 1031 - let content, shadowed = Cmi.read_signature_noenv env parent (Odoc_model.Compat.signature incl.incl_type) in 1031 + (* Pre-scan the compiler's elaborated signature for __ names. If all items 1032 + have double-underscore names, we'll flatten this include and the docs 1033 + will never render — skip parsing them. *) 1034 + let sig_items = Odoc_model.Compat.signature incl.incl_type in 1035 + let all_names_hidden = 1036 + sig_items <> [] && 1037 + List.for_all (fun item -> 1038 + let open Odoc_model.Compat in 1039 + match item with 1040 + | Sig_value (id, _, _) -> contains_double_underscore (Ident.name id) 1041 + | Sig_type (id, _, _, _) -> contains_double_underscore (Ident.name id) 1042 + | Sig_module (id, _, _, _, _) -> contains_double_underscore (Ident.name id) 1043 + | Sig_modtype (id, _, _) -> contains_double_underscore (Ident.name id) 1044 + | Sig_class (id, _, _, _) -> contains_double_underscore (Ident.name id) 1045 + | Sig_class_type (id, _, _, _) -> contains_double_underscore (Ident.name id) 1046 + | Sig_typext _ -> false) sig_items 1047 + in 1048 + let n_sig_items = List.length sig_items in 1049 + let prev_skip_include = !Doc_attr.skip_doc_parsing in 1050 + if in_stop || all_names_hidden then 1051 + Doc_attr.skip_doc_parsing := true; 1052 + let t_read = Sys.time () in 1053 + let content, shadowed = Cmi.read_signature_noenv env parent sig_items in 1054 + let dt_read = Sys.time () -. t_read in 1055 + Doc_attr.skip_doc_parsing := prev_skip_include; 1056 + if dt_read > 0.01 then 1057 + (match Sys.getenv_opt "ODOC_GC_STATS" with 1058 + | Some s when s <> "" && s <> "0" -> 1059 + Printf.eprintf "ODOC_INCLUDE_READ sig_items=%d lang_items=%d time=%.3f file=%s:%d\n%!" 1060 + n_sig_items (List.length content.Signature.items) dt_read 1061 + loc.file loc.start.line 1062 + | _ -> ()); 1032 1063 incr flatten_total_includes; 1033 1064 let all_hidden = all_items_hidden content.Signature.items in 1034 1065 let should_flatten = in_stop || all_hidden in ··· 1053 1084 in 1054 1085 if should_flatten && shadowed_empty then 1055 1086 (* For includes in doc-stop blocks or whose every item is hidden, splice 1056 - the expansion directly into the enclosing signature. The items won't be 1057 - rendered (hidden by name convention or explicit stop marker) but remain 1058 - available for cross-references. Skip when shadowed is non-empty: that 1059 - would require rewriting shadowed names in the enclosing signature. *) 1060 - content.Signature.items 1087 + the expansion directly into the enclosing signature. Wrap in Stop 1088 + markers so the document generator skips them (restoring the (**/**) 1089 + wrappers that were present in the typedtree but lost when we read the 1090 + expansion from the elaborated Types.signature). *) 1091 + Signature.Comment `Stop :: content.Signature.items @ [ Signature.Comment `Stop ] 1061 1092 else 1062 1093 (* Use a synthetic parent for the include's module type expression to avoid 1063 1094 identifier conflicts with items in the enclosing signature. Items inside ··· 1108 1139 Doc_attr.extract_top_comment internal_tags ~warnings_tag:env.warnings_tag ~classify parent sg.sig_items 1109 1140 in 1110 1141 let in_stop = ref false in 1111 - let prev_skip = !Doc_attr.skip_doc_parsing in 1112 - Doc_attr.skip_doc_parsing := false; 1142 + let inherit_skip = !Doc_attr.skip_doc_parsing in 1113 1143 let items = 1114 1144 List.fold_left 1115 1145 (fun items item -> 1116 - List.rev_append (read_signature_item ~in_stop env parent item) items) 1146 + List.rev_append (read_signature_item ~in_stop ~inherit_skip env parent item) items) 1117 1147 [] items 1118 1148 |> List.rev 1119 1149 in 1120 - Doc_attr.skip_doc_parsing := prev_skip; 1150 + Doc_attr.skip_doc_parsing := inherit_skip; 1121 1151 match doc_post with 1122 1152 | {elements=[]; _} -> 1123 1153 ({ Signature.items; compiled = false; removed = []; doc }, tags)