diff --git a/check/classic/classic.exp b/check/classic/classic.exp index 7d7dce5b..1804311c 100644 --- a/check/classic/classic.exp +++ b/check/classic/classic.exp @@ -1,5 +1,30 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:3: internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:38: internally_used_f @@ -518,6 +543,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -563,3 +614,5 @@ Nothing else to report in this section Nothing else to report in this section -------------------------------------------------------------------------------- + + diff --git a/check/classic/classic.ref b/check/classic/classic.ref index 1a7e8a02..bf4b80b1 100644 --- a/check/classic/classic.ref +++ b/check/classic/classic.ref @@ -1,5 +1,31 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Reexport.unused: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:3: internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:38: internally_used_f @@ -518,6 +544,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -565,7 +617,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 491 -Success: 491 -Failed: 0 -Ratio: 100.% +Total: 531 +Success: 530 +Failed: 1 +Ratio: 99.8116760829% diff --git a/check/internal/internal.exp b/check/internal/internal.exp index 266dd6e9..7a7042c8 100644 --- a/check/internal/internal.exp +++ b/check/internal/internal.exp @@ -1,5 +1,20 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -483,6 +498,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -528,3 +569,5 @@ Nothing else to report in this section Nothing else to report in this section -------------------------------------------------------------------------------- + + diff --git a/check/internal/internal.ref b/check/internal/internal.ref index 61168480..f028200a 100644 --- a/check/internal/internal.ref +++ b/check/internal/internal.ref @@ -1,5 +1,21 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Reexport.unused: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -483,6 +499,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -530,7 +572,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 458 -Success: 458 -Failed: 0 -Ratio: 100.% +Total: 489 +Success: 488 +Failed: 1 +Ratio: 99.7955010225% diff --git a/check/src/path.ml b/check/src/path.ml index 3684991a..b6a00a70 100644 --- a/check/src/path.ml +++ b/check/src/path.ml @@ -37,22 +37,23 @@ let normalize path = (* Relocate a `path` found in a `.got` file as a relative path from the project's root. - - For files in 'using_make': there is no 'using_make' file or directory in - '/examples/using_'. Therefore, taking everything in the - path from the last 'using_make' filename provides the common part for the - relocation. Then, adding an extra './' completes the path as found in the - expected reports + - For files in 'docs' and 'using_make': there is no 'using_make' file or + directory in '/examples/*'. Therefore, taking everything in the + path from the last 'docs' or 'using_make' filename provides the common part + for the relocation. Then, adding an extra './iexamples' completes the path as + found in the expected reports - For files in 'using_dune': the same startegy as for files in 'using_make' can be applied with the removal of '_build/default' on the way. Because those directory names are unique, we can actually share the same logic for both 'using_make' and 'using_dune'. *) let relocate path = (* retrieve the subpath starting from the last occurence of - "using_" if it exists, and remove "_build" and "default" + a valid basename if it exists, and remove "_build" and "default" directories from the path *) + let valid_basenames = ["docs"; "using_make"; "using_dune"] in let rec extract_subpath acc dirpath = let basename = Filename.basename dirpath in - if basename = "using_make" || basename = "using_dune" then + if List.mem basename valid_basenames then basename::acc else if basename = dirpath (* fixpoint *) then path::[] (* TODO: error handling *) @@ -64,7 +65,7 @@ let relocate path = in extract_subpath acc (Filename.dirname dirpath) in - let relative_path = (* ["using"; ...] *) + let relative_path = (* [valid_basename; ...] *) extract_subpath [] path in String.concat Filename.dir_sep ("."::"examples"::relative_path) diff --git a/check/threshold-1/threshold-1.exp b/check/threshold-1/threshold-1.exp index 3ee1152d..b1c62f3c 100644 --- a/check/threshold-1/threshold-1.exp +++ b/check/threshold-1/threshold-1.exp @@ -1,5 +1,20 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -84,6 +99,38 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/function/function_lib.mli:3: memoize +./examples/docs/exported_values/code_constructs/function/function_lib.mli:5: heavy_computation +./examples/docs/exported_values/code_constructs/function/function_lib.mli:9: do_nothing + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:8: F.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:24: Internal_app.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: Redefine.used_directly + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: Original.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:17: M_redef.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:4: M.externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:2: hello +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_lib.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_no_intf.mli:1: mark_used @@ -826,6 +873,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... diff --git a/check/threshold-1/threshold-1.ref b/check/threshold-1/threshold-1.ref index b1d8443f..13e7d268 100644 --- a/check/threshold-1/threshold-1.ref +++ b/check/threshold-1/threshold-1.ref @@ -1,5 +1,21 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Reexport.unused: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -84,6 +100,41 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/function/function_lib.mli:3: memoize +./examples/docs/exported_values/code_constructs/function/function_lib.mli:5: heavy_computation +./examples/docs/exported_values/code_constructs/function/function_lib.mli:9: do_nothing + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:8: F.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:24: Internal_app.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Reexport.used_directly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Redefine.used_indirectly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Reexport.used_indirectly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: Redefine.used_directly + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: Original.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:17: M_redef.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:4: M.externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:2: hello +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_lib.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_no_intf.mli:1: mark_used @@ -826,6 +877,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -873,7 +950,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 762 -Success: 762 -Failed: 0 -Ratio: 100.% +Total: 821 +Success: 817 +Failed: 4 +Ratio: 99.5127892814% diff --git a/check/threshold-3-0.5/threshold-3-0.5.exp b/check/threshold-3-0.5/threshold-3-0.5.exp index 9a443ecb..a587ebad 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.exp +++ b/check/threshold-3-0.5/threshold-3-0.5.exp @@ -1,5 +1,20 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -84,6 +99,38 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/function/function_lib.mli:3: memoize +./examples/docs/exported_values/code_constructs/function/function_lib.mli:5: heavy_computation +./examples/docs/exported_values/code_constructs/function/function_lib.mli:9: do_nothing + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:8: F.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:24: Internal_app.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: Redefine.used_directly + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: Original.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:17: M_redef.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:4: M.externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:2: hello +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_lib.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_no_intf.mli:1: mark_used @@ -287,6 +334,17 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 2 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:19: External_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:20: External_param.unused_required + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.unused + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:4: world +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:4: world + ./examples/using_dune/preprocessed_lib/preprocessed.mli:2: used ./examples/using_dune/preprocessed_lib/preprocessed.mli:31: exported_f ./examples/using_dune/preprocessed_lib/preprocessed.mli:38: internally_used_f @@ -993,7 +1051,9 @@ Nothing else to report in this section ./examples/using_make/dir/anonFn2.mli:2: ?a (2/3 calls) ./examples/using_make/dir/anonFn2.mli:2: ?b (2/3 calls) ./examples/using_make/dir/match_opt.ml:1: ?b (2/3 calls) + ./examples/using_make/dir/matchopt.ml:1: ?x (3/4 calls) + ./examples/using_make/dir/ref_fn.ml:1: ?a (2/3 calls) ./examples/using_make/dir/ref_fn.ml:1: ?b (2/3 calls) @@ -1192,9 +1252,9 @@ Nothing else to report in this section ./examples/using_make/dir/anonFn.mli:3: ?a (1/2 calls) ./examples/using_make/dir/anonFn.mli:3: ?b (1/2 calls) ./examples/using_make/dir/anonFn2.mli:1: ?b (2/3 calls) + ./examples/using_make/dir/matchopt.ml:1: ?y (3/4 calls) ./examples/using_make/dir/matchopt.ml:1: ?z (3/4 calls) - ./examples/using_make/let_in.ml:1: ?b (2/3 calls) ./examples/using_make/matchopt.ml:1: ?y (3/4 calls) ./examples/using_make/matchopt.ml:1: ?z (3/4 calls) @@ -1209,6 +1269,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... diff --git a/check/threshold-3-0.5/threshold-3-0.5.ref b/check/threshold-3-0.5/threshold-3-0.5.ref index 1b6277b2..faf280c6 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.ref +++ b/check/threshold-3-0.5/threshold-3-0.5.ref @@ -1,5 +1,21 @@ .> UNUSED EXPORTED VALUES: ========================= +./examples/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: Reexport.unused: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -84,6 +100,41 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/function/function_lib.mli:3: memoize +./examples/docs/exported_values/code_constructs/function/function_lib.mli:5: heavy_computation +./examples/docs/exported_values/code_constructs/function/function_lib.mli:9: do_nothing + +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:8: F.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:24: Internal_app.externally_used +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: Reexport.used_directly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Redefine.used_indirectly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: Reexport.used_indirectly: Should not be detected +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: Redefine.used_directly + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: Original.used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: Original.used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: Original.used_by_requirement + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:17: M_redef.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used + +./examples/docs/exported_values/code_constructs/module/module_lib.mli:4: M.externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:2: hello +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_lib.mli:1: mark_used ./examples/using_dune/bin/use_preprocessed_lib/use_preprocessed_no_intf.mli:1: mark_used @@ -287,6 +338,17 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 2 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:19: External_param.used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.mli:20: External_param.unused_required + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:13: M_subst.unused + +./examples/docs/exported_values/hello_world/hello_world_lib.mli:4: world +./examples/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world +./examples/docs/exported_values/hello_world/hello_world_without_intf.ml:4: world + ./examples/using_dune/preprocessed_lib/preprocessed.mli:2: used ./examples/using_dune/preprocessed_lib/preprocessed.mli:31: exported_f ./examples/using_dune/preprocessed_lib/preprocessed.mli:38: internally_used_f @@ -993,7 +1055,9 @@ Nothing else to report in this section ./examples/using_make/dir/anonFn2.mli:2: ?a (2/3 calls) ./examples/using_make/dir/anonFn2.mli:2: ?b (2/3 calls) ./examples/using_make/dir/match_opt.ml:1: ?b (2/3 calls) + ./examples/using_make/dir/matchopt.ml:1: ?x (3/4 calls) + ./examples/using_make/dir/ref_fn.ml:1: ?a (2/3 calls) ./examples/using_make/dir/ref_fn.ml:1: ?b (2/3 calls) @@ -1192,6 +1256,7 @@ Nothing else to report in this section ./examples/using_make/dir/anonFn.mli:3: ?a (1/2 calls) ./examples/using_make/dir/anonFn.mli:3: ?b (1/2 calls) ./examples/using_make/dir/anonFn2.mli:1: ?b (2/3 calls) + ./examples/using_make/dir/matchopt.ml:1: ?y (3/4 calls) ./examples/using_make/dir/matchopt.ml:1: ?z (3/4 calls) ./examples/using_make/let_in.ml:1: ?b (2/3 calls) @@ -1208,6 +1273,32 @@ Nothing else to report in this section .> CODING STYLE: =============== +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:16: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:17: unit pattern unused_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:21: unit pattern used_required +./examples/docs/exported_values/code_constructs/functor/functor_lib.ml:22: unit pattern unused_required + +./examples/docs/exported_values/code_constructs/include/include_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:5: unit pattern unused +./examples/docs/exported_values/code_constructs/include/include_lib.ml:14: unit pattern used_directly +./examples/docs/exported_values/code_constructs/include/include_lib.ml:15: unit pattern unused + +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:3: unit pattern used_directly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:4: unit pattern used_indirectly +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: unit pattern used_by_requirement +./examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: unit pattern unused + +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:11: unit pattern externally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:12: unit pattern internally_used +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:13: unit pattern unused +./examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml:14: unit pattern unused_unexported + +./examples/docs/exported_values/code_constructs/module/module_lib.ml:4: unit pattern externally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:5: unit pattern internally_used +./examples/docs/exported_values/code_constructs/module/module_lib.ml:6: unit pattern unused +./examples/docs/exported_values/code_constructs/module/module_lib.ml:7: unit pattern unused_unexported + ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: let () = ... in ... (=> use sequence) ./examples/using_dune/preprocessed_lib/preprocessed.ml:83: unit pattern unit_binding ./examples/using_dune/preprocessed_lib/preprocessed.ml:84: val f: ... -> (... -> ?_:_ -> ...) -> ... @@ -1255,7 +1346,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 1071 -Success: 1071 -Failed: 0 -Ratio: 100.% +Total: 1138 +Success: 1134 +Failed: 4 +Ratio: 99.6485061511% diff --git a/docs/USER_DOC.md b/docs/USER_DOC.md index 48c03ae0..0fff3c01 100644 --- a/docs/USER_DOC.md +++ b/docs/USER_DOC.md @@ -53,6 +53,7 @@ not related to the _use_ of elements of code. This documentation is split accross different topics: - [Usage](USAGE.md) describes the usage of the `dead_code_analyzer` and its options. +- [Exported Values](exported_values/EXPORTED_VALUES.md) describes the semantics and usage of the "unused exported values" report section, and provides examples. ## Footnotes diff --git a/docs/exported_values/EXPORTED_VALUES.md b/docs/exported_values/EXPORTED_VALUES.md new file mode 100644 index 00000000..715bf97f --- /dev/null +++ b/docs/exported_values/EXPORTED_VALUES.md @@ -0,0 +1,214 @@ +# Table of contents + ++ [Exported Values](#exported-values) + + [Definitions](#definitions) + + [Compiler warnings](#compiler-warnings) + + [Warning 26: unused-var](#warning-26-unused-var) + + [Warning 27: unused-var-strict](#warning-27-unused-var-strict) + + [Warning 32: unused-value-declaration](#warning-32-unused-value-declaration) + + [Usage](#usage) ++ [Examples](#examples) + +# Exported Values + +## Definitions + +A **value** is the result of an expression. For the analyzer, we'll restrict +this definition to a _named_ value, i.e. a name bound to an expression. +In general, this is the `lhs` of `let lhs = ...` or `val lhs : ...`. + +An **exported** value is one that is accessible outside its compilation unit. +I.e. a value that can be referenced in other `.ml` and/or `.mli` files than +the ones that declare it. + +A **use** is either : +- An explicit reference. + E.g. + ```OCaml + let answer = 42 + let () = print_int answer + ``` + The value `answer` is explicitly referenced in `print_int answer`. +- A requirement for that value to exist. + E.g. + ```OCaml + module M = struct + let answer = 42 + end + + module M2 : sig val answer : int end = M + ``` + There are 2 values here : `M.answer`, and `M2.answer`. + Neither of them is explictly referenced. However, `M.answer` is used by + requirement in `M2 : ... = M`. I.e. it needs to be provided by `M` to fulfill + `M2`'s signature. Without it the compilation would fail with an error like : + ``` + File "requirement.ml", line 4, characters 39-40: + 4 | module M2 : sig val answer : int end = M + ^ + Error: Signature mismatch: + Modules do not match: + sig end + is not included in + sig val answer : int end + The value answer is required but not provided + File "requirement.ml", line 4, characters 16-32: Expected declaration + ``` + +## Compiler warnings + +The analyzer reports unused _exported_ values while the compiler reports other +kinds of unused values. They complement each other. + +> [!TIP] +> To obtain a list of available compiler warnings, use +> `ocamlopt -warn-help` + +The compiler warnings related to unused values are the 26, 27, and 32. +The two firsts warn about unused local values. The third warns about unused +unexported toplevel values. + +### Warning 26: unused-var + +This warning is enabled by default. +I can be disabled by passing the `-w -26` to the compiler. + +Description: +``` +26 [unused-var] Suspicious unused variable: unused variable that is bound + with "let" or "as", and doesn't start with an underscore ("_") + character. +``` + +Example: +```OCaml +(* warning26.ml *) +let () = + let x = () in + () +``` +``` +$ ocamlopt warning26.ml +File "warning26.ml", line 3, characters 6-7: +3 | let x = () in + ^ +Warning 26 [unused-var]: unused variable x. +``` + +### Warning 27: unused-var-strict + +This warning is disabled by default. +I can be enabled by passing the `-w +27` to the compiler. + +Description: +``` +27 [unused-var-strict] Innocuous unused variable: unused variable that is not bound with + "let" nor "as", and doesn't start with an underscore ("_") + character. +``` + +Example: +```OCaml +(* warning27.ml *) +let f = function + | x -> () +``` +``` +$ ocamlopt -w +27 warning27.ml +File "warning27.ml", line 2, characters 4-5: +2 | | x -> () + ^ +Warning 27 [unused-var-strict]: unused variable x. +``` + +### Warning 32: unused-value-declaration + +This warning is disabled by default. +I can be enabled by passing the `-w +32` to the compiler. + +Description: +``` +32 [unused-value-declaration] Unused value declaration. (since 4.00) +``` + +Example: +```OCaml +(* warning32.mli *) +``` +```OCaml +(* warning32.ml *) +let x = () +``` +``` +$ ocamlopt -w +32 warning32.mli warning32.ml +File "warning32.ml", line 2, characters 4-5: +2 | let x = () + ^ +Warning 32 [unused-value-declaration]: unused value x. +``` + +## Usage + +Unused exported values are reported by default. +Their reports can be deactivated by using the `--nothing` or `-E nothing` +command line arguments. +They can be reactivated by using the `--all` or `-E all` command line arguments. +For more details about the command line arguments see [the more general Usage +documentation](../USAGE.md). + +The report section looks like: + +The expected resolution for an unused exported value is to remove it from the +`.mli` if there is one, or the `.ml` otherwise. + +> [!IMPORTANT] +> Removing unused values from the codebase (reported by either the compiler or +> the analyzer) may trigger the detection of new unused values for both the +> compiler and the analyzer. Consequently, it is expected that a user might need +> to compile and analyze their code multiple times when cleaning up their +> codebase. + +In order to provide actionable reports, the analyzer does not track the same +uses depending on whether a `.mli` exists or not : +- If a value is declared in a `.mli`, then only uses outside its compilation +unit are tracked (by default). +- If there is no `.mli`, then uses inside the compilation unit are also tracked. + +With that same goal in mind, the analyzer does not report _transitively_ unused +exported values. I.e. if a value is only used by unused values, then it will +not be reported as unused. It would be reported unused only after all the code +using it has been removed. +This is also the compiler's behavior for its warnings about unused values. + +E.g. +```OCaml +(* not_transitive.ml *) +let () = + let x = () in + let y = x in + () +``` +``` +$ ocamlopt not_transitive.ml +File "not_transitive.ml", line 4, characters 6-7: +4 | let y = x in + ^ +Warning 26 [unused-var]: unused variable y. +``` +`y` is reported by the warning 26 but not `x`, because `x` is used by `y`. + +# Examples + +- [Hello world](./HELLO_WORLD.md) is a collection of small examples relying on the + same code, but organized differently (with/without `.mli`, single/multiple + compilation units). This aims at providing a first walk-through of the + analyzer's usage. + +- The [code constructs](./code_constructs) directory contains a collection of + examples dedicated to specific code constructs : + - [Function](./code_constructs/FUNCTION.md) + - [Module](./code_constructs/MODULE.md) + - [Functor](./code_constructs/FUNCTOR.md) + - [Module type](./code_constructs/MODTYP.md) + - [Module signature](./code_constructs/MODSIG.md) + - [Include](./code_constructs/INCLUDE.md) diff --git a/docs/exported_values/HELLO_WORLD.md b/docs/exported_values/HELLO_WORLD.md new file mode 100644 index 00000000..22935a56 --- /dev/null +++ b/docs/exported_values/HELLO_WORLD.md @@ -0,0 +1,575 @@ +# Table of contents + ++ [Single compilation unit without interface](#single-compilation-unit-without-interface) ++ [Single compilation unit with interface](#single-compilation-unit-with-interface) ++ [Multiple compilation units](#multiple-compilation-units) ++ [All Together](#all-together) + +All of the following examples can be found in the [hello\_world](../../examples/docs/exported_values/hello_world) +directory. + +The reference takes place in `/tmp/docs/exported_values/hello_world`, which +contains copies of the examples. Reported locations may differ depending on the +location of the source files. + +# Single compilation unit without interface + +This example illustrates a simple case of a compilation unit without `.mli` and +without any external use. + +The reference file for this example is +[`hello_world_without_intf.ml`](../../examples/docs/exported_values/hello_world/hello_world_without_intf.ml). + +The compilation command to produce `hello_world_without_intf.cmi` and +`hello_world_without_intf.cmt` is : +``` +ocamlopt -bin-annot hello_world_without_intf.ml +``` + +The analysis command is : +``` +dead_code_analyzer --nothing -E all hello_world_without_intf.cmi hello_world_without_intf.cmt +``` + +## First run + +Code : +```OCaml +(* hello_world_without_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world +``` + +Compile : +``` +$ ocamlopt -bin-annot hello_world_without_intf.ml +File "hello_world_without_intf.ml", line 8, characters 6-19: +8 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. +``` + +The compiler reports a warning 26 on `goodbye_world`: +`Warning 26 [unused-var]: unused variable goodbye_world.` +This tells us that the _local_ value is unused, and, thus, can be removed at the +reported location: `File "hello_world_without_intf.ml", line 8` + +Analyze : +``` +$ dead_code_analyzer --nothing -E all hello_world_without_intf.cmi hello_world_without_intf.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The analyzer does not report any unused _exported_ value. There are 3 exported +in the `Hello_world_without_intf` compilation unit : `hello`, `goodbye` and `world`. +These are the top level values of `hello_world_without_intf.ml`. +They are all referenced internally. Because there is no `hello_world_without_intf.mli`, +the internal uses are accounted for. Consequently, none of the exported values +are considered unused by the analyzer. + +## Fixing the warning 26 + +Let's remove the unused `goodbye_world`. + +Code : +```OCaml +(* hello_world_without_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_without_intf.ml + +$ dead_code_analyzer --nothing -E all hello_world_without_intf.cmi hello_world_without_intf.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The compiler does not report any unused value. + +The analyzer reports that `goodbye` declared at line 3 is unused : +`/tmp/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye` +Like the warning 26 above, this report tells us that `goodbye` can be removed +at the reported location. + +## Removing the unused `goodbye` + +Code : +```OCaml +(* hello_world_without_intf.ml *) +let hello = "Hello" +let world = "World" + +let () = + let hello_world = hello ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_without_intf.ml + +$ dead_code_analyzer --nothing -E all hello_world_without_intf.cmi hello_world_without_intf.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +Now, neither the compiler nor the analyzer report any unused value. +Our work here is done. + +# Single compilation unit with interface + +This example is the same as the previous example, with an explicit `.mli`. +Although an interface is provided, all the uses remain inside the same +compilation unit. + +The reference files for this example are +[`hello_world_with_intf.mli`](../../examples/docs/exported_values/hello_world/hello_world_with_intf.mli) and +[`hello_world_with_intf.ml`](../../examples/docs/exported_values/hello_world/hello_world_with_intf.ml) + +The compilation command to produce `hello_world.cmi` and `hello_world.cmt` is : +``` +ocamlopt -bin-annot hello_world_with_intf.mli hello_world_with_intf.ml +``` + +The analysis command is : +``` +dead_code_analyzer --nothing -E all hello_world.cmi hello_world.cmt +``` + +## First run + +Code : +```OCaml +(* hello_world_with_intf.mli *) +val hello : string +val goodbye : string +val world : string +``` +```OCaml +(* hello_world_with_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_with_intf.ml +File "hello_world_with_intf.ml", line 8, characters 6-19: +8 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. + +$ dead_code_analyzer --nothing -E all hello_world.cmi hello_world.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The compiler reports the same warning 26 on `goodbye_world` as in the previous +example. + +The analyzer reports that there are 3 unused _exported_ value in +`hello_world_with_intf.mli`: `hello` at line 2, `goodbye` line 3, and `world` line 4. +These are the only exported values in the `Hello_world_with_intf` compilation +unit because they are the only ones listed in the `.mli`. They are all used in +`hello_world_with_intf.ml`, but not outside of their compilation unit. Because there is an +interface file available, only external uses are accounted for. Thus, they are +considered unused and can be dropped from the `.mli` + +## Removing the unused values + +Let's remove the unused `goodbye_world` from `hello_world_with_intf.ml`, reported unused +by the compiler, and the values in `hello_world_with_intf.mli` reported by the analyzer. + +Code : +```OCaml +(* hello_world_with_intf.mli *) +``` +```OCaml +(* hello_world_with_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + print_endline hello_world +``` +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_with_intf.ml +$ dead_code_analyzer --nothing -E all hello_world.cmi hello_world.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +Now, neither the compiler nor the analyzer report any unused value. + +We learned from the previous example that the `goodbye` value is unused after +we remove `goodbye_world`. This is on the compiler to report it in this example +because it is an _unexported_ value here (while it was an _exported_ value in +the previous example). The corresponding warning is actually off by default and +can be activated by passing the `-w +32` argument to the compiler : +``` +$ ocamlopt -w +32 hello_world_with_intf.ml +File "hello_world_with_intf.ml", line 3, characters 4-11: +3 | let goodbye = "Goodbye" + ^^^^^^^ +Warning 32 [unused-value-declaration]: unused value goodbye. +``` +The `goodbye` value can be safely removed and neither the compiler nor the +analyzer will report unused values anymore. Our work here is done. + +# Multiple compilation units + +This example is the same as the previous example, split in 2 separate +compilation units. All the exported values are now used externally. + +The reference files for this example are +[`hello_world_lib.mli`](../../examples/docs/exported_values/hello_world/hello_world_lib.mli), +[`hello_world_lib.ml`](../../examples/docs/exported_values/hello_world/hello_world_lib.ml), and +[`hello_world_bin.ml`](../../examples/docs/exported_values/hello_world/hello_world_bin.ml) + +The compilation command to produce the necessary `.cmi` and `.cmt` files is : +``` +ocamlopt -bin-annot hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +``` + +The analysis command is : +``` +dead_code_analyzer --nothing -E all hello_world_lib.cmi hello_world_lib.cmt hello_world_bin.cmi hello_world_bin.cmt +``` + +> [!NOTE] +> It is left as an exercise to the reader to explore this example without +> `hello_world_lib.mli`. + +## First run + +Code : +```OCaml +(* hello_world_lib.mli *) +val hello : string +val goodbye : string +val world : string +``` +```OCaml +(* hello_world_lib.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" +``` +```OCaml +(* hello_world_bin.ml *) +let () = + let open Hello_world_lib in + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +File "hello_world_bin.ml", line 5, characters 6-19: +5 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. + +$ dead_code_analyzer --nothing -E all hello_world_lib.cmi hello_world_lib.cmt hello_world_bin.cmi hello_world_bin.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The compiler reports the same warning 26 on `goodbye_world` as in the previous +example. + +The analyzer does not report any unused _exported_ value. The 3 exported +values are `hello`, `goodbye` and `world` in `hello_world_lib.mli`. They are all +referenced externally, in `hello_world_bin.ml`. + +> [!NOTE] +> All the different flavors of explicit reference are taken into account the +> same way. Here, the values are referenced after a local `open`. They could +> have been referenced after a global `open` or using their full paths (e.g. +> `Hello_world_lib.hello`) without making any difference on the reports. + +## Fixing the warning 26 + +Let's remove the unused `goodbye_world`. + +Code : +```OCaml +(* hello_world_lib.mli *) +val hello : string +val goodbye : string +val world : string +``` +```OCaml +(* hello_world_lib.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" +``` +```OCaml +(* hello_world_bin.ml *) +let () = + let open Hello_world_lib in + let hello_world = hello ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml + +$ dead_code_analyzer --nothing -E all hello_world_lib.cmi hello_world_lib.cmt hello_world_bin.cmi hello_world_bin.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The compiler does not report any unused value. + +The analyzer reports `goodbye` as unused, as in the previous example. + +## Unexporting `goodbye` + +Code : +```OCaml +(* hello_world_lib.mli *) +val hello : string +val world : string +``` +```OCaml +(* hello_world_lib.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" +``` +```OCaml +(* hello_world_bin.ml *) +let () = + let open Hello_world_lib in + let hello_world = hello ^ world in + print_endline hello_world +``` + +Compile and analyze : +``` +$ ocamlopt -bin-annot hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml + +$ dead_code_analyzer --nothing -E all hello_world_lib.cmi hello_world_lib.cmt hello_world_bin.cmi hello_world_bin.cmt +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +Now, neither the compiler nor the analyzer report any unused value. + +Like in the previous example, we need to pass `-w +32` to the compiler to +trigger the `unused-value-declaration` warning : +``` +$ ocamlopt -bin-annot hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +File "hello_world_lib.ml", line 3, characters 4-11: +3 | let goodbye = "Goodbye" + ^^^^^^^ +Warning 32 [unused-value-declaration]: unused value goodbye. +``` +The `goodbye` value can be safely removed and neither the compiler nor the +analyzer will report unused values anymore. Our work here is done. + +# All Together + +This example is the grouping of all the previous [*Hello World*](#hello-world) +examples. Analyzing all the files at once reduces the number of iterations to +reach a satisfying codebase. + +The reference files for this example are all those listed previously. + +The compilation command to produce the necessary `.cmi` and `.cmt` files, +and the desired warnings is the combination of all the previous ones : +``` +ocamlopt -w +32 -bin-annot hello_world_without_intf.ml hello_world_with_intf.mli hello_world_with_intf.ml hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +``` + +> [!NOTE] +> For our usage, this has the same effect has running each of the previous +> compliation commands, with the extra `-w +32` argument, one after the other. +> The benefit is that all the warnings will be printed at once. + +The analysis command is : +``` +dead_code_analyzer --nothing -E all . +``` + +> [!TIP] +> As we can see in the compilation command, there is a large number of files to +> list. Instead of listing all the `.cmi` and `.cmt` files in the command line, +> the analyzer accepts directories as arguments and will analyze all the +> relevant files it can find in them. + +The code is not re-exposed at each iteration here. It is the same as in the +previous examples. + +## First Run + +Compile : +``` +$ ocamlopt -w +32 -bin-annot hello_world_without_intf.ml hello_world_with_intf.mli hello_world_with_intf.ml hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +File "hello_world_without_intf.ml", line 8, characters 6-19: +8 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. + +File "hello_world_with_intf.ml", line 8, characters 6-19: +8 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. + +File "hello_world_bin.ml", line 5, characters 6-19: +5 | let goodbye_world = goodbye ^ world in + ^^^^^^^^^^^^^ +Warning 26 [unused-var]: unused variable goodbye_world. +``` + +Without any surprise, the compiler reports the warnings 26 explored +in the previous examples. +Let's fix them and **recompile**, before running the analyzer. + +Analyze : +``` +$ dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:2: hello +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:3: goodbye +/tmp/docs/exported_values/hello_world/hello_world_with_intf.mli:4: world +/tmp/docs/exported_values/hello_world/hello_world_lib.mli:3: goodbye +/tmp/docs/exported_values/hello_world/hello_world_without_intf.ml:3: goodbye + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +The analyzer correctly reports the unused exported values it reported in +the previous examples, all in one run. Note that the reports are in the +lexicographical order. +Unlike the compiler which listed its warnings in the order of the files in +the command line, the analyzer always sorts its reports in this order. + +## Removing the unused exported values + +Like we did, in the previous examples, we can remove the exported values at the +locations reported by the analyzer. + +Compile : +``` +$ ocamlopt -w +32 -bin-annot hello_world_without_intf.ml hello_world_with_intf.mli hello_world_with_intf.ml hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +File "hello_world_with_intf.ml", line 3, characters 4-11: +3 | let goodbye = "Goodbye" + ^^^^^^^ +Warning 32 [unused-value-declaration]: unused value goodbye. + +File "hello_world_lib.ml", line 3, characters 4-11: +3 | let goodbye = "Goodbye" + ^^^^^^^ +Warning 32 [unused-value-declaration]: unused value goodbye. +``` + +Once again, the warnings are the same as for the previous examples. After +`goodbye_world` is removed and `goodbye` is unexported, the compiler warning 32 +indicates that `goodbye` is unused. +Let's fix the warnings. + +Compile and analyze : +``` +$ ocamlopt -w +32 -bin-annot hello_world_without_intf.ml hello_world_with_intf.mli hello_world_with_intf.ml hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml + +$ dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` + +Now, neither the compiler nor the analyzer report any unused value. +Our work here is done. diff --git a/docs/exported_values/code_constructs/FUNCTION.md b/docs/exported_values/code_constructs/FUNCTION.md new file mode 100644 index 00000000..bc2ee6db --- /dev/null +++ b/docs/exported_values/code_constructs/FUNCTION.md @@ -0,0 +1,173 @@ +The reference files for this example are in the +[function](../../../examples/docs/exported_values/code_constructs/function) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C function build +``` + +The analysis command is : +``` +make -C function analyze +``` + +The compile + analyze command is : +``` +make -C function +``` + +## First run + +Code: +```OCaml +(* function_lib.mli *) + +val memoize : f:('a -> 'b) -> 'a -> 'b + +val heavy_computation : 'a -> 'a + +val unused : 'a -> 'a + +val do_nothing : 'a -> unit +``` +```OCaml +(* function_lib.ml *) + +let memoize ~f = + let mem = Hashtbl.create 8 in + function x -> + match Hashtbl.find_opt mem x with + | Some y -> y + | None -> + let y = f x in + Hashtbl.add mem x y; + y + +let heavy_computation x = x + +let unused x = x + +let do_nothing x = () +``` +```OCaml +(* function_bin.ml *) + +let () = + let my_memoized = Function_lib.(memoize ~f:heavy_computation) in + Function_lib.do_nothing (); + assert (my_memoized 42 = my_memoized 42) +``` + +Function values are analyzed like any other value. Hence, passing them as +arguments to a function or applying them (even partially) count as uses just +like any other explicit reference. Therefore, `Function_lib`'s `memoize`, +`heavy_computation`, and `do_nothing` are used in `Function_bin`. This leaves +`Function_lib.unused` as the only unused exported value. + + +Compile and analyze : +``` +$ make -C function +make: Entering directory '/tmp/docs/exported_values/code_constructs/function' +ocamlopt -w +27+32 -bin-annot function_lib.mli function_lib.ml function_bin.ml +File "function_lib.ml", line 17, characters 15-16: +17 | let do_nothing x = () + ^ +Warning 27 [unused-var-strict]: unused variable x. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/function/function_lib.mli:7: unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/function' +``` + +The compiler reports that `do_nothing`'s parameter `x` is unused via a +warning 27. This can be easily fixed by prefixing the name with an underscore +`_` or even replacing the name by an underscore. Depending on the context, other +solutions may be considered, such as removing the parameter, or fixing the +argument's type to `unit`. + +As expected, the analyzer only reports `unused`, declared in `function_lib.mli`. + +## Removing the unused values + +The warning 27 is fixed by updating `do_nothing`'s type to `unit -> unit` and +its parameter `x` to `()`. + +Code: +```OCaml +(* function_lib.mli *) + +val memoize : f:('a -> 'b) -> 'a -> 'b + +val heavy_computation : 'a -> 'a + +val do_nothing : unit -> unit +``` +```OCaml +(* function_lib.ml *) + +let memoize ~f = + let mem = Hashtbl.create 8 in + function x -> + match Hashtbl.find_opt mem x with + | Some y -> y + | None -> + let y = f x in + Hashtbl.add mem x y; + y + +let heavy_computation x = x + +let unused x = x + +let do_nothing () = () +``` +```OCaml +(* function_bin.ml *) + +let () = + let my_memoized = Function_lib.(memoize ~f:heavy_computation) in + Function_lib.do_nothing (); + assert (my_memoized 42 = my_memoized 42) +``` + +Compile and analyze : +``` +$ make -C function +make: Entering directory '/tmp/docs/exported_values/code_constructs/function' +ocamlopt -w +27+32 -bin-annot function_lib.mli function_lib.ml function_bin.ml +File "function_lib.ml", line 15, characters 4-10: +15 | let unused x = x + ^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/function' +``` + +Now that `unused` is unexported, the compiler reports it as unused via the +warning 32, and the analyzer does not report anything. Removing that value +fixes all the warnings. Our work here is done. diff --git a/docs/exported_values/code_constructs/FUNCTOR.md b/docs/exported_values/code_constructs/FUNCTOR.md new file mode 100644 index 00000000..514a40d5 --- /dev/null +++ b/docs/exported_values/code_constructs/FUNCTOR.md @@ -0,0 +1,329 @@ +The reference files for this example are in the +[functor](../../../examples/docs/exported_values/code_constructs/functor) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C functor build +``` + +The analysis command is : +``` +make -C functor analyze +``` + +The compile + analyze command is : +``` +make -C functor +``` + +## First run + +Code: +```OCaml +(* functor_lib.mli *) +type t + +module F (P : sig + val used_required : t + val unused_required : t +end) : sig + val externally_used : t + val internally_used : t + val unused : t +end + +module Internal_param : sig + val used_required : t + val unused_required : t +end + +module External_param : sig + val used_required : t + val unused_required : t +end + +module Internal_app : sig + val externally_used : t + val internally_used : t + val unused : t +end +``` +```OCaml +(* functor_lib.ml *) +type t = unit + +module F (P : sig + val used_required : t + val unused_required : t +end) = struct + let externally_used = P.used_required + let internally_used = P.used_required + let unused = P.used_required + let unused_unexported = P.used_required + let () = internally_used +end + +module Internal_param = struct + let used_required = () + let unused_required = () +end + +module External_param = struct + let used_required = () + let unused_required = () +end + +module Internal_app = F(Internal_param) +``` +```OCaml +(* functor_bin.ml *) +open Functor_lib + +module External_app = F(External_param) + +let () = + ignore Internal_app.externally_used; + ignore External_app.externally_used +``` + +Before looking at the analysis results, let's look at the code. + +The `Functor_lib` compilation unit exports 1 functor and 3 modules : +- `F` takes a module containing the values `used_required` and `unused_required`, + and returns a module with 3 values whose names are explicit. +- `Internal_param` and `External_param` fit the signature of `F`'s parameter `P`. + The first one is used for a functor application inside `Functor_lib`. + The second one is used for a functor application outside of it. +- `Internal_app` fits the signature of the result of `F`, and is impemented as + the result of applying `F` inside its compilation unit. + +The `Functor_bin` compilation unit exports 1 module : `External_app`, which is +the result of applying `Functor_lib.F` outside its compilation unit. + +Among all the exported values, the only explicit references accounted for are +`Internal_app.externally_used` and `External_app.externally_used` in +`Functor_bin`. + +Additionally, some values are used by requirement. Because `Internal_param` and +`External_param` are passed as arguments to `F`, their values `used_required` and +`unused_required` are used by requirement to fulfill the signature of `F`'s +parameter `P`. + +With those observations in mind, let's see what the compiler and the analyzer +report. + +Compile and analyze: +``` +$ make -C functor +make: Entering directory '/tmp/docs/exported_values/code_constructs/functor' +ocamlopt -w +32 -bin-annot functor_lib.mli functor_lib.ml functor_bin.ml +File "functor_lib.ml", line 6, characters 2-25: +6 | val unused_required : t + ^^^^^^^^^^^^^^^^^^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused_required. + +File "functor_lib.ml", line 11, characters 6-23: +11 | let unused_unexported = P.used_required + ^^^^^^^^^^^^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused_unexported. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:9: F.internally_used +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:10: F.unused +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:14: Internal_param.used_required +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:15: Internal_param.unused_required +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:25: Internal_app.internally_used +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:26: Internal_app.unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/functor' +``` + +> The compiler reports 2 unused values, that can be removed at the reported locations : +> - `unused_required`, defined by `P`, the parameter of `F`; +> - `unexported_unused`, defined by `F`, like it did in the [module](MODULE.md) example. + +The analyzer reports 6 unused exported values, all in `functor_lib.mli` : +2 in `F`, 2 in `Internal_param`, and 2 in `Internal_app`. Let's observe them by +module (in reverse order) : + +- The reports for `Internal_app` are identical to the [module](MODULE.md) example. +Although, `Internal_app` is implemented as the result of applying `F` in +`functor_lib.ml`, its signature is independent of `F` in `functor_lib.mli`. +I.e. it exposes its own values and the link between them and those of +`F` is absent from the signature. Consequently, they are tracked independently. + +- As we observed before runnning the analyzer, the values in `Internal_param` are +used by requirement. However, this use is internal to `Functor_lib`, and there +is an interface available : `functor_lib.mli`. Consequently, the internal uses +are ignored, and `Internal_param`'s values become unused. + +- `F` is a functor but is tracked like a regular module. The reported values are +those of its result module. Reporting on those may feel like duplicates, but, +as explained for the reports of `Internal_app`, the values of the result +module are declared independently of those of `Internal_app`, hence they are +tracked and reported independently. + +All the values reported by the analyzer can be safely removed. + +Before moving on, there is another observation that we can make : +the values `unused` and `internally_used` of `External_app` are not reported. +Because they are reported for `Internal_app` and `F`, one could +expect them to be reported for `External_app` as well. In reality, they are not +tracked individually for `External_app` because it does not expose them +explicitly. Unlike `Internal_app` which has an explicit module signature, +`External_app` does not. Consequently, its values are directly linked to those of +`F`. This situation is explored in the +[module signature](MODSIG.md) example. + +> [!TIP] +> If we activated the compiler warning 67 `unused-functor-parameter` (by +> passing the argument `-w +67`), then the compiler would have reported : +> ``` +> File "functor_lib.mli", line 4, characters 10-11: +> 4 | module F (P : sig +> ^ +> Warning 67 [unused-functor-parameter]: unused functor parameter P. +> ``` +> This can be fixed by either replacing `P` with `_`, or by rewriting the +> declaration of `F` as : +> ```OCaml +> module F : sig +> val used_required : t +> val unused_required : t +> end +> -> sig +> val externally_used : t +> val internally_used : t +> val unused : t +> end +> ``` + +## Removing the unused values + +In addition to removing everything that was reported by the compiler and the +analyzer, we also commented out `P.used_required` and `Internal_param` in +`functor_lib.mli`. It is up to the user to decide whether they would like to +keep them or remove them from their specifications. Neither would be reported +by the compiler or the analyzer. + +> [!NOTE] +> It is allowed to give a larger module as argument than what the parameter +> specifies. Similarly it is allowed to declare the parameter larger in the +> interface than it is in the implementation. Consequently, the compiler would +> not complain if `P` expected `unused_required` in the `.mli` but not in the +> `.ml`. + +Code: +```OCaml +(* functor_lib.mli *) +type t + +module F (P : sig + val used_required : t + (* val unused_required : t *) +end) : sig + val externally_used : t +end + +(* +module Internal_param : sig +end +*) + +module External_param : sig + val used_required : t + val unused_required : t +end + +module Internal_app : sig + val externally_used : t +end +``` +```OCaml +(* functor_lib.ml *) +type t = unit + +module F (P : sig + val used_required : t +end) = struct + let externally_used = P.used_required + let internally_used = P.used_required + let unused = P.used_required + let () = internally_used +end + +module Internal_param = struct + let used_required = () + let unused_required = () +end + +module External_param = struct + let used_required = () + let unused_required = () +end + +module Internal_app = F(Internal_param) +``` +```OCaml +(* functor_bin.ml *) +open Functor_lib + +module External_app = F(External_param) + +let () = + ignore Internal_app.externally_used; + ignore External_app.externally_used +``` + +Compile and analyze : +``` +$ make -C functor +make: Entering directory '/tmp/docs/exported_values/code_constructs/functor' +ocamlopt -w +32 -bin-annot functor_lib.mli functor_lib.ml functor_bin.ml +File "functor_lib.ml", line 9, characters 6-12: +9 | let unused = P.used_required + ^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused. + +File "functor_lib.ml", line 15, characters 6-21: +15 | let unused_required = () + ^^^^^^^^^^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused_required. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/functor/functor_lib.mli:18: External_param.unused_required + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/functor' +``` + +Now that `F.unused` and `Internal_param.unused_required` are not exported, they +are reported as unused by the compiler, and can be removed safely. + +`External_param.unused_required` was used by requirement. Now that it is not +required by `P` (because it is commented out), it is unused and the analyzer +correctly reports it. It can be removed safely. Removing it will trigger the +same compiler warning as for `Internal_param.unused_required`, so it can be +removed from both the interface and the implementation. + +The unused values can be removed as explained. Our work here is done. diff --git a/docs/exported_values/code_constructs/INCLUDE.md b/docs/exported_values/code_constructs/INCLUDE.md new file mode 100644 index 00000000..32afa596 --- /dev/null +++ b/docs/exported_values/code_constructs/INCLUDE.md @@ -0,0 +1,163 @@ +The reference files for this example are in the +[include](../../../examples/docs/exported_values/code_constructs/include) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C include build +``` + +The analysis command is : +``` +make -C include analyze +``` + +The compile + analyze command is : +``` +make -C include +``` + +## First run + +Code: +```OCaml +(* include_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () + let unused = () +end + +module Reexport = struct + include Original +end + +module Redefine = struct + include Original + let used_directly = () + let unused = () +end +``` +```OCaml +(* include_bin.ml *) +let () = + let open Include_lib in + ignore Original.used_directly; + ignore Reexport.used_indirectly; + ignore Redefine.used_directly; +``` + +Before looking at the analysis results, let's look at the code. + +The `Include_lib` compilation unit does not have a `.mli`, so all the internal +uses are accounted for. It exposes 3 modules : +- `Original`, which explicitly defines all its values; +- `Reexport`, which only includes `Original`; +- `Redefine`, which includes `Original` and redefines 2 values : + `used_directly`, and `unused`. + +By the explanation in the [module signature](MODSIG.md) and +[module type](MODTYP.md) examples, although there are 9 exported values +(`used_directly`, `used_indirectly`, and `unused` for each module), only 5 are +expected to be tracked by the analyzer : those in `Original` and the 2 redefined +in `Redefine`. These are the only values a developer can trivially remove if +they are reported unused. + +Thus, the only values used are `Original.used_directly`, +`Original.used_indirectly` (by an explicit reference to +`Reexport.used_indirectly`), and `Redefine.used_directly`. This means that the +unused exported values tracked by the analyzer are `Original.unused` and +`Redefine.unused`. + +Compile and analyze: +``` +$ make -C include +make: Entering directory '/tmp/docs/exported_values/code_constructs/include' +ocamlopt -bin-annot include_lib.ml include_bin.ml +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/include/include_lib.ml:5: Original.unused +/tmp/docs/exported_values/code_constructs/include/include_lib.ml:5: Reexport.unused +/tmp/docs/exported_values/code_constructs/include/include_lib.ml:15: Redefine.unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/include' +``` + +The compiler does not report any unused value. + +As expected, the analyzer reports `Original.unused` and `Redefine.unused`. +However, it also reports `Reexport.unused`, which is unexpected. + +> [!WARNING] +> The extra report on `Reexport.unused` is a known bug, tracked by +> [issue #57](https://github.com/LexiFi/dead_code_analyzer/issues/57). +> This duplicated report only exists because the modules `Original` and +> `Reexport` belong to the same compilation unit (`Include_lib`). This can +> easily be verified by moving `Reexport` in `Include_bin` instead. + +Because the report of `Reexport.unused` is actually a duplicate of the report +of `Original.unused`, we can simply ignore it. + +## Removing the unused values + +The reported values can be removed from the implementation. + +Code: +```OCaml +(* include_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () +end + +module Reexport = struct + include Original +end + +module Redefine = struct + include Original + let used_directly = () +end +``` +```OCaml +(* include_bin.ml *) +let () = + let open Include_lib in + ignore Original.used_directly; + ignore Reexport.used_indirectly; + ignore Redefine.used_directly; +``` + +Compile and analyze: +``` +$ make -C include +make: Entering directory '/tmp/docs/exported_values/code_constructs/include' +ocamlopt -bin-annot include_lib.ml include_bin.ml +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/include' +``` + +Now, neither the compiler nor the analyzer report any unused value. +Our work here is done. diff --git a/docs/exported_values/code_constructs/MODSIG.md b/docs/exported_values/code_constructs/MODSIG.md new file mode 100644 index 00000000..f49af91e --- /dev/null +++ b/docs/exported_values/code_constructs/MODSIG.md @@ -0,0 +1,165 @@ +The reference files for this example are in the +[modsig](../../../examples/docs/exported_values/code_constructs/modsig) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C modsig build +``` + +The analysis command is : +``` +make -C modsig analyze +``` + +The compile + analyze command is : +``` +make -C modsig +``` + +## First run + +Code: +```OCaml +(* modsig_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () + let used_by_requirement = () + let unused = () +end + +module Alias_without_sig = Original + +module Alias_with_sig : sig + val used_by_requirement : unit +end = Original +``` +```OCaml +(* modsig_bin.ml *) +let () = + let open Modsig_lib in + Original.used_directly; + Alias_without_sig.used_indirectly +``` + +Before looking at the analysis results, let's look at the code. + +The `Modsig_lib` compilation unit does not have a `.mli`, so all the internal +uses are accounted for. It exposes 3 modules : `Original`, `Alias_without_sig`, +and `Alias_with_sig`. Only the first module actually defines values. The second +one is an trivial alias, and the third is an alias with an explicit signature. +Because the 2 latter modules are aliases of the `Original` module, one could +expect that the values they expose are unified with the ones of `Original`. +This would imply that only the values in `Original` could be reported as unused. +This reasoning is partially true. + +As explained in the [module type](MODTYP.md) example, reporting a value in +`Alias_without_sig` would not be trivially solved. Thus, +its values are unified with those of `Original`, and, consequently, they +cannot be reported by the analyzer. Only the values in `Original` can be +reported in this case. + +However, `Alias_with_sig` has an explicit signature, which means 2 things: +1. it controls what it exports, thus a reporting values in that module is + trivially actionable by removing the reported values from the signature +2. it has requirements, thus all the values in `Original` that are expected in + the signature of `Alias_with_sig` are considered used. + +Now that we have explained the nuances introduced by the existence of an +explicit module signature, let's look at the results. + +Compile and analyze: +``` +$ make -C modsig +make: Entering directory '/tmp/docs/exported_values/code_constructs/modsig' +ocamlopt -bin-annot modsig_lib.ml modsig_bin.ml +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/modsig/modsig_lib.ml:6: Original.unused +/tmp/docs/exported_values/code_constructs/modsig/modsig_lib.ml:12: Alias_with_sig.used_by_requirement + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/modsig' +``` + +The compiler does not report any unused value. + +The analyzer reports that `Original.unused` and +`Alias_with_sig.used_by_requirement` are unused. As expected, it does not report +any unused value in `Alias_without_sig`. +Let's look more closely at the values and their uses. +- `Original.used_directly` is explicitly referenced in `Modsig_bin` +- `Original.used_indirectly` is used by an explicit reference to + `Alias_without_sig.used_indirectly` in `Modsig_bin` +- `Original.used_by_requirement` is used by requirement to fulfill + `Alias_with_sig`'s signature +- `Original.unused` is not referenced nor required anywhere +- `Alias_without_sig` does not "own" any value +- `Alias_with_sig.used_by_requirement` is not referenced nor required anywhere + +## Removing the unused values + +The reported values can be removed : `Original.unused` is removed from the +module's strucutre because it does not have an explicit signature, and +`Alias_with_sig.used_by_requirement` is removed from the module's signature. + +Code: +```OCaml +(* modsig_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () + let used_by_requirement = () +end + +module Alias_without_sig = Original + +module Alias_with_sig : sig end = Original +``` +```OCaml +(* modsig_bin.ml *) +let () = + let open Modsig_lib in + Original.used_directly; + Alias_without_sig.used_indirectly +``` + +Compile and analyze: +``` +$ make -C modsig +make: Entering directory '/tmp/docs/exported_values/code_constructs/modsig' +ocamlopt -bin-annot modsig_lib.ml modsig_bin.ml +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/modsig/modsig_lib.ml:5: Original.used_by_requirement + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/modsig' +``` + +The compiler does not report any unused value. + +The analyzer reports `Original.used_by_requirement` as unused. Indeed, +by removing `used_by_requirement` from the signature of `Alias_with_sig` we +removed the requirement for `Original` to provide it. This value can be removed +from `Orignal`, and neither the compiler nor the analyzer will report unused +values anymore. Our work here is done. diff --git a/docs/exported_values/code_constructs/MODTYP.md b/docs/exported_values/code_constructs/MODTYP.md new file mode 100644 index 00000000..aa06c0f7 --- /dev/null +++ b/docs/exported_values/code_constructs/MODTYP.md @@ -0,0 +1,154 @@ +The reference files for this example are in the +[modtyp](../../../examples/docs/exported_values/code_constructs/modtyp) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C modtyp build +``` + +The analysis command is : +``` +make -C modtyp analyze +``` + +The compile + analyze command is : +``` +make -C modtyp +``` + +> [!IMPORTANT] +> **LIMITATION** +> +> In order to reduce noise (false positives and duplication) in the results, +> the analyzer currently ignores values exported by module types +> (see [issue #50](https://github.com/LexiFi/dead_code_analyzer/issues/50)). + +## First run + +Code: +```OCaml +(* modtyp_lib.mli *) +module type T = sig + type t + val externally_used : t + val internally_used : t + val unused : t +end + +module M_reuse : T + +module M_constr : T with type t = unit + +module M_subst : T with type t := unit + +module M_redef : sig + type t + val externally_used : t + val internally_used : t + val unused : t +end +``` +```OCaml +(* modtyp_lib.ml *) +module type T = sig + type t + val externally_used : t + val internally_used : t + val unused : t +end + +module M = struct + type t = unit + let externally_used = () + let internally_used = () + let unused = () + let unused_unexported = () +end + +let () = M.internally_used + +module M_reuse = M + +module M_constr = M + +module M_subst = M + +module M_redef = M +``` +```OCaml +(* modtyp_bin.ml *) +let () = + ignore Modtyp_lib.M_reuse.externally_used; + ignore Modtyp_lib.M_constr.externally_used; + ignore Modtyp_lib.M_subst.externally_used; + ignore Modtyp_lib.M_redef.externally_used +``` + +Before looking at the analysis results, let's look at the code. + +The `Modtyp_lib` exports 1 module type `T` and 4 modules : +`M_reuse`, `M_constr`, `M_subst`, and `M_redef`. Of these 4 modules, the first +3 have `T` as signature (with minor twists), while the last one has its own +explicit signature, which is a copy of `T`. In this way, `M_redef` is equivalent +to `Module_lib.M` in the [module](MODULE.md) example : it exposes exactly +the same information. +Each of the modules exposed by `Modtyp_lib` are used exactly in the same way : +their `externally_used` values are explicitly referenced in `Modtyp_bin`. + +One could expect that all the exported values are reported except for the +`externally_used`. However, reporting e.g. `M_subst.internally_used` as unused +would not be immediately actionable. In reality, this value is explicitly +declared by `T`. +Fixing an unused value reported in a module using a module type as signature +would require either removing the value from the module type (if possible), +or explicilty describing the signature of the module, effectively losing the +benefits of using the module type. Thus, reporting unused values for the module +itself would be counterproductive. + +An actionable report would be of the value in the module type itself, +if it is unused by all the modules of that module type (as it is the case here +for `T.unused`). Currently, and as described in the introduction of this example, +the values exported by module types are ignored by the analyzer, and, +consequently, are not reported. + +Now that we have explained what the expected behavior of the analyzer should be, +let's look at its results on the code above. + +Compile and analyze : +``` +$ make -C modtyp +make: Entering directory '/tmp/docs/exported_values/code_constructs/modtyp' +ocamlopt -w +32 -bin-annot modtyp_lib.mli modtyp_lib.ml modtyp_bin.ml +File "modtyp_lib.ml", line 14, characters 6-23: +14 | let unused_unexported = () + ^^^^^^^^^^^^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused_unexported. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:18: M_redef.internally_used +/tmp/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli:19: M_redef.unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/modtyp' +``` + +As in the module example, the compiler reports that `unused_unexported` is unused. + +As in the module example, the analyzer reports `M_redef.internally_used` and +`M_redef.unused` as unused exported values. + +All the reports are similar to those of the [module](MODULE.md) example. +Its exploration and resolution can be applied. +Our work here is done. diff --git a/docs/exported_values/code_constructs/MODULE.md b/docs/exported_values/code_constructs/MODULE.md new file mode 100644 index 00000000..23ada048 --- /dev/null +++ b/docs/exported_values/code_constructs/MODULE.md @@ -0,0 +1,153 @@ +The reference files for this example are in the +[module](../../../examples/docs/exported_values/code_constructs/module) directory. + +The reference takes place in `/tmp/docs/exported_values/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/exported_values/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C module build +``` + +The analysis command is : +``` +make -C module analyze +``` + +The compile + analyze command is : +``` +make -C module +``` + +## First run + +Code: +```OCaml +(* module_lib.mli *) +module M : sig + type t + val externally_used : t + val internally_used : t + val unused : t +end +``` +```OCaml +(* module_lib.ml *) +module M = struct + type t = unit + let externally_used = () + let internally_used = () + let unused = () + let unused_unexported = () +end + +let () = M.internally_used +``` +```OCaml +(* module_bin.ml *) +let () = + ignore Module_lib.M.externally_used +``` + +Before looking at the analysis results, let's look at the code. + +All the values of `Module_lib.M` are exported except for +`unused_unexported`. Among the exported values, `unused` is not referenced +anywhere, `internally_used` is only referenced within its compilation unit +(`Module_lib`), and `externally_used` is only referenced outside of it. + +> [!IMPORTANT] +> Using `internally_used` inside of `M` rather than outside would provide the +> same results. The only scope of interest is the compilation unit. + +Compile and analyze : +``` +$ make -C module +make: Entering directory '/tmp/docs/exported_values/code_constructs/module' +ocamlopt -w +32 -bin-annot module_lib.mli module_lib.ml module_bin.ml +File "module_lib.ml", line 7, characters 6-23: +7 | let unused_unexported = () + ^^^^^^^^^^^^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused_unexported. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/exported_values/code_constructs/module/module_lib.mli:5: M.internally_used +/tmp/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/module' +``` + +The compiler reports that `unused_unexported` is unused. + +The analyzer reports `M.internally_used` and `M.unused` as unused. Notice how +it did not only report the name of the value but its full path within its +compilation unit. + +> [!NOTE] +> `M.internally_used` is only used within its compilation unit. Because it is +> declared in a `.mli`, only external uses are accounted for. +> It is left as an exercise to the reader to explore this example without +> `module_lib.mli` + +## Removing the unused values + +Code: +```OCaml +(* module_lib.mli *) +module M : sig + type t + val externally_used : t +end +``` +```OCaml +(* module_lib.ml *) +module M = struct + type t = unit + let externally_used = () + let internally_used = () + let unused = () +end + +let () = M.internally_used +``` +```OCaml +(* module_bin.ml *) +let () = + ignore Module_lib.M.externally_used +``` + +Compile and analyze : +``` +$ make -C module +make: Entering directory '/tmp/docs/exported_values/code_constructs/module' +ocamlopt -w +32 -bin-annot module_lib.mli module_lib.ml module_bin.ml +File "module_lib.ml", line 6, characters 6-12: +6 | let unused = () + ^^^^^^ +Warning 32 [unused-value-declaration]: unused value unused. +dead_code_analyzer --nothing -E all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/exported_values/code_constructs/module' +``` + +The compiler reports `unused` as unused and the analyzer does not report +anything. Removing that value fixes all the warnings. Our work here is done. diff --git a/examples/Makefile b/examples/Makefile index 5f43d246..0100a940 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,19 +1,26 @@ -.PHONY: clean run_dca build_dca build_dune build_make build dune_only make_only +.PHONY: clean run_dca build_dca build_dune build_make build_docs build dune_only make_only docs_only +CMTI_ROOT_DOCS=docs CMTI_ROOT_MAKE=using_make CMTI_ROOT_DUNE=using_dune/_build/default/ -CMTI_ROOT?=$(CMTI_ROOT_MAKE) $(CMTI_ROOT_DUNE) +CMTI_ROOT?=$(CMTI_ROOT_DOCS) $(CMTI_ROOT_MAKE) $(CMTI_ROOT_DUNE) REDIRECT?="" # Used by ../check/Makefile all: build build_dca run_dca +docs_only: build_make build_dca + make run_dca CMTI_ROOT=$(CMTI_ROOT_DOCS) + make_only: build_make build_dca make run_dca CMTI_ROOT=$(CMTI_ROOT_MAKE) dune_only: build_dune build_dca make run_dca CMTI_ROOT=$(CMTI_ROOT_DUNE) -build: build_make build_dune +build: build_docs build_make build_dune + +build_docs: + make -C docs build_make: make -C using_make @@ -29,5 +36,6 @@ run_dca: clean: rm -f *~ *.cm* *.o *.obj + make -C docs clean make -C using_make clean dune clean --root=using_dune diff --git a/examples/docs/Makefile b/examples/docs/Makefile new file mode 100644 index 00000000..ae38a077 --- /dev/null +++ b/examples/docs/Makefile @@ -0,0 +1,11 @@ +.PHONY: clean build + +all: build + +build: + make -C exported_values + +clean: + rm -f *~ *.cm* *.o *.obj + make -C exported_values clean + diff --git a/examples/docs/exported_values/Makefile b/examples/docs/exported_values/Makefile new file mode 100644 index 00000000..c452f3e9 --- /dev/null +++ b/examples/docs/exported_values/Makefile @@ -0,0 +1,13 @@ +.PHONY: clean build + +all: build + +build: + make -C hello_world + make -C code_constructs + +clean: + rm -f *~ *.cm* *.o *.obj + make -C hello_world clean + make -C code_constructs clean + diff --git a/examples/docs/exported_values/code_constructs/Makefile b/examples/docs/exported_values/code_constructs/Makefile new file mode 100644 index 00000000..ff3799a2 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/Makefile @@ -0,0 +1,21 @@ +.PHONY: clean build + +all: build + +build: + make -C function build + make -C module build + make -C functor build + make -C modtyp build + make -C modsig build + make -C include build + +clean: + rm -f *~ *.cm* *.o *.obj + make -C function clean + make -C module clean + make -C functor clean + make -C modtyp clean + make -C modsig clean + make -C include clean + diff --git a/examples/docs/exported_values/code_constructs/function/Makefile b/examples/docs/exported_values/code_constructs/function/Makefile new file mode 100644 index 00000000..1487fe4c --- /dev/null +++ b/examples/docs/exported_values/code_constructs/function/Makefile @@ -0,0 +1,12 @@ +SRC:=function_lib.mli function_lib.ml function_bin.ml + +all: build analyze + +build: + ocamlopt -w +27+32 -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/function/function_bin.ml b/examples/docs/exported_values/code_constructs/function/function_bin.ml new file mode 100644 index 00000000..7aa027dc --- /dev/null +++ b/examples/docs/exported_values/code_constructs/function/function_bin.ml @@ -0,0 +1,6 @@ +(* function_bin.ml *) + +let () = + let my_memoized = Function_lib.(memoize ~f:heavy_computation) in + Function_lib.do_nothing (); + assert (my_memoized 42 = my_memoized 42) diff --git a/examples/docs/exported_values/code_constructs/function/function_lib.ml b/examples/docs/exported_values/code_constructs/function/function_lib.ml new file mode 100644 index 00000000..89be8141 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/function/function_lib.ml @@ -0,0 +1,17 @@ +(* function_lib.ml *) + +let memoize ~f = + let mem = Hashtbl.create 8 in + function x -> + match Hashtbl.find_opt mem x with + | Some y -> y + | None -> + let y = f x in + Hashtbl.add mem x y; + y + +let heavy_computation x = x + +let unused x = x + +let do_nothing x = () diff --git a/examples/docs/exported_values/code_constructs/function/function_lib.mli b/examples/docs/exported_values/code_constructs/function/function_lib.mli new file mode 100644 index 00000000..7792b0fe --- /dev/null +++ b/examples/docs/exported_values/code_constructs/function/function_lib.mli @@ -0,0 +1,9 @@ +(* function_lib.mli *) + +val memoize : f:('a -> 'b) -> 'a -> 'b + +val heavy_computation : 'a -> 'a + +val unused : 'a -> 'a + +val do_nothing : 'a -> unit diff --git a/examples/docs/exported_values/code_constructs/functor/Makefile b/examples/docs/exported_values/code_constructs/functor/Makefile new file mode 100644 index 00000000..c91b18eb --- /dev/null +++ b/examples/docs/exported_values/code_constructs/functor/Makefile @@ -0,0 +1,12 @@ +SRC:=functor_lib.mli functor_lib.ml functor_bin.ml + +all: build analyze + +build: + ocamlopt -w +32 -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/functor/functor_bin.ml b/examples/docs/exported_values/code_constructs/functor/functor_bin.ml new file mode 100644 index 00000000..18ff81c2 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/functor/functor_bin.ml @@ -0,0 +1,8 @@ +(* functor_bin.ml *) +open Functor_lib + +module External_app = F(External_param) + +let () = + ignore Internal_app.externally_used; + ignore External_app.externally_used diff --git a/examples/docs/exported_values/code_constructs/functor/functor_lib.ml b/examples/docs/exported_values/code_constructs/functor/functor_lib.ml new file mode 100644 index 00000000..102a8973 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/functor/functor_lib.ml @@ -0,0 +1,25 @@ +(* functor_lib.ml *) +type t = unit + +module F (P : sig + val used_required : t + val unused_required : t +end) = struct + let externally_used = P.used_required + let internally_used = P.used_required + let unused = P.used_required + let unused_unexported = P.used_required + let () = internally_used +end + +module Internal_param = struct + let used_required = () + let unused_required = () +end + +module External_param = struct + let used_required = () + let unused_required = () +end + +module Internal_app = F(Internal_param) diff --git a/examples/docs/exported_values/code_constructs/functor/functor_lib.mli b/examples/docs/exported_values/code_constructs/functor/functor_lib.mli new file mode 100644 index 00000000..f2cdfd8a --- /dev/null +++ b/examples/docs/exported_values/code_constructs/functor/functor_lib.mli @@ -0,0 +1,27 @@ +(* functor_lib.mli *) +type t + +module F (P : sig + val used_required : t + val unused_required : t +end) : sig + val externally_used : t + val internally_used : t + val unused : t +end + +module Internal_param : sig + val used_required : t + val unused_required : t +end + +module External_param : sig + val used_required : t + val unused_required : t +end + +module Internal_app : sig + val externally_used : t + val internally_used : t + val unused : t +end diff --git a/examples/docs/exported_values/code_constructs/include/Makefile b/examples/docs/exported_values/code_constructs/include/Makefile new file mode 100644 index 00000000..44b93352 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/include/Makefile @@ -0,0 +1,12 @@ +SRC:=include_lib.ml include_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/include/include_bin.ml b/examples/docs/exported_values/code_constructs/include/include_bin.ml new file mode 100644 index 00000000..563106cc --- /dev/null +++ b/examples/docs/exported_values/code_constructs/include/include_bin.ml @@ -0,0 +1,6 @@ +(* include_bin.ml *) +let () = + let open Include_lib in + ignore Original.used_directly; + ignore Reexport.used_indirectly; + ignore Redefine.used_directly; diff --git a/examples/docs/exported_values/code_constructs/include/include_lib.ml b/examples/docs/exported_values/code_constructs/include/include_lib.ml new file mode 100644 index 00000000..8e41947c --- /dev/null +++ b/examples/docs/exported_values/code_constructs/include/include_lib.ml @@ -0,0 +1,16 @@ +(* include_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () + let unused = () +end + +module Reexport = struct + include Original +end + +module Redefine = struct + include Original + let used_directly = () + let unused = () +end diff --git a/examples/docs/exported_values/code_constructs/modsig/Makefile b/examples/docs/exported_values/code_constructs/modsig/Makefile new file mode 100644 index 00000000..109a96da --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modsig/Makefile @@ -0,0 +1,12 @@ +SRC:=modsig_lib.ml modsig_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/modsig/modsig_bin.ml b/examples/docs/exported_values/code_constructs/modsig/modsig_bin.ml new file mode 100644 index 00000000..971d3e6c --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modsig/modsig_bin.ml @@ -0,0 +1,5 @@ +(* modsig_bin.ml *) +let () = + let open Modsig_lib in + Original.used_directly; + Alias_without_sig.used_indirectly diff --git a/examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml b/examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml new file mode 100644 index 00000000..31329a04 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modsig/modsig_lib.ml @@ -0,0 +1,13 @@ +(* modsig_lib.ml *) +module Original = struct + let used_directly = () + let used_indirectly = () + let used_by_requirement = () + let unused = () +end + +module Alias_without_sig = Original + +module Alias_with_sig : sig + val used_by_requirement : unit +end = Original diff --git a/examples/docs/exported_values/code_constructs/modtyp/Makefile b/examples/docs/exported_values/code_constructs/modtyp/Makefile new file mode 100644 index 00000000..5b9b6dd0 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modtyp/Makefile @@ -0,0 +1,12 @@ +SRC:=modtyp_lib.mli modtyp_lib.ml modtyp_bin.ml + +all: build analyze + +build: + ocamlopt -w +32 -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/modtyp/modtyp_bin.ml b/examples/docs/exported_values/code_constructs/modtyp/modtyp_bin.ml new file mode 100644 index 00000000..61a25ead --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modtyp/modtyp_bin.ml @@ -0,0 +1,6 @@ +(* modtyp_bin.ml *) +let () = + ignore Modtyp_lib.M_reuse.externally_used; + ignore Modtyp_lib.M_constr.externally_used; + ignore Modtyp_lib.M_subst.externally_used; + ignore Modtyp_lib.M_redef.externally_used diff --git a/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml b/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml new file mode 100644 index 00000000..c0bec72e --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.ml @@ -0,0 +1,25 @@ +(* modtyp_lib.ml *) +module type T = sig + type t + val externally_used : t + val internally_used : t + val unused : t +end + +module M = struct + type t = unit + let externally_used = () + let internally_used = () + let unused = () + let unused_unexported = () +end + +let () = M.internally_used + +module M_reuse = M + +module M_constr = M + +module M_subst = M + +module M_redef = M diff --git a/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli b/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli new file mode 100644 index 00000000..4027f7e1 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/modtyp/modtyp_lib.mli @@ -0,0 +1,20 @@ +(* modtyp_lib.mli *) +module type T = sig + type t + val externally_used : t + val internally_used : t + val unused : t +end + +module M_reuse : T + +module M_constr : T with type t = unit + +module M_subst : T with type t := unit + +module M_redef : sig + type t + val externally_used : t + val internally_used : t + val unused : t +end diff --git a/examples/docs/exported_values/code_constructs/module/Makefile b/examples/docs/exported_values/code_constructs/module/Makefile new file mode 100644 index 00000000..4917174f --- /dev/null +++ b/examples/docs/exported_values/code_constructs/module/Makefile @@ -0,0 +1,12 @@ +SRC:=module_lib.mli module_lib.ml module_bin.ml + +all: build analyze + +build: + ocamlopt -w +32 -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/exported_values/code_constructs/module/module_bin.ml b/examples/docs/exported_values/code_constructs/module/module_bin.ml new file mode 100644 index 00000000..19c25d77 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/module/module_bin.ml @@ -0,0 +1,3 @@ +(* module_bin.ml *) +let () = + ignore Module_lib.M.externally_used diff --git a/examples/docs/exported_values/code_constructs/module/module_lib.ml b/examples/docs/exported_values/code_constructs/module/module_lib.ml new file mode 100644 index 00000000..1d50dbc1 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/module/module_lib.ml @@ -0,0 +1,10 @@ +(* module_lib.ml *) +module M = struct + type t = unit + let externally_used = () + let internally_used = () + let unused = () + let unused_unexported = () +end + +let () = M.internally_used diff --git a/examples/docs/exported_values/code_constructs/module/module_lib.mli b/examples/docs/exported_values/code_constructs/module/module_lib.mli new file mode 100644 index 00000000..7eccf6f3 --- /dev/null +++ b/examples/docs/exported_values/code_constructs/module/module_lib.mli @@ -0,0 +1,7 @@ +(* module_lib.mli *) +module M : sig + type t + val externally_used : t + val internally_used : t + val unused : t +end diff --git a/examples/docs/exported_values/hello_world/Makefile b/examples/docs/exported_values/hello_world/Makefile new file mode 100644 index 00000000..45da992c --- /dev/null +++ b/examples/docs/exported_values/hello_world/Makefile @@ -0,0 +1,19 @@ +.PHONY: clean build + +COMPFLAGS=-w +32 -bin-annot -keep-locs +OCAMLC=ocamlc $(COMPFLAGS) +SRC=hello_world_without_intf.ml\ + hello_world_with_intf.mli hello_world_with_intf.ml\ + hello_world_lib.mli hello_world_lib.ml hello_world_bin.ml +CMTI=$(filter %.cmi,$(SRC:.ml=.cmi)) $(filter %.cmt,$(SRC:.ml=.cmt)) + +all: build + +build: $(CMTI) + +$(CMTI): $(SRC) + $(OCAMLC) -c $(SRC) + +clean: + rm -f *~ *.cm* *.o *.obj + diff --git a/examples/docs/exported_values/hello_world/hello_world_bin.ml b/examples/docs/exported_values/hello_world/hello_world_bin.ml new file mode 100644 index 00000000..a6293a4e --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_bin.ml @@ -0,0 +1,6 @@ +(* hello_world_bin.ml *) +let () = + let open Hello_world_lib in + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world diff --git a/examples/docs/exported_values/hello_world/hello_world_lib.ml b/examples/docs/exported_values/hello_world/hello_world_lib.ml new file mode 100644 index 00000000..93fb93bd --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_lib.ml @@ -0,0 +1,4 @@ +(* hello_world_lib.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" diff --git a/examples/docs/exported_values/hello_world/hello_world_lib.mli b/examples/docs/exported_values/hello_world/hello_world_lib.mli new file mode 100644 index 00000000..77fe3cf0 --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_lib.mli @@ -0,0 +1,4 @@ +(* hello_world_lib.mli *) +val hello : string +val goodbye : string +val world : string diff --git a/examples/docs/exported_values/hello_world/hello_world_with_intf.ml b/examples/docs/exported_values/hello_world/hello_world_with_intf.ml new file mode 100644 index 00000000..a31aab06 --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_with_intf.ml @@ -0,0 +1,9 @@ +(* hello_world_with_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world diff --git a/examples/docs/exported_values/hello_world/hello_world_with_intf.mli b/examples/docs/exported_values/hello_world/hello_world_with_intf.mli new file mode 100644 index 00000000..1dfb73c6 --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_with_intf.mli @@ -0,0 +1,4 @@ +(* hello_world_with_intf.mli *) +val hello : string +val goodbye : string +val world : string diff --git a/examples/docs/exported_values/hello_world/hello_world_without_intf.ml b/examples/docs/exported_values/hello_world/hello_world_without_intf.ml new file mode 100644 index 00000000..842cc316 --- /dev/null +++ b/examples/docs/exported_values/hello_world/hello_world_without_intf.ml @@ -0,0 +1,9 @@ +(* hello_world_without_intf.ml *) +let hello = "Hello" +let goodbye = "Goodbye" +let world = "World" + +let () = + let hello_world = hello ^ world in + let goodbye_world = goodbye ^ world in + print_endline hello_world