diff --git a/check/classic/classic.exp b/check/classic/classic.exp index efc07a67..dd991654 100644 --- a/check/classic/classic.exp +++ b/check/classic/classic.exp @@ -25,6 +25,13 @@ ./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/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./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 @@ -146,6 +153,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -571,6 +601,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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/classic/classic.ref b/check/classic/classic.ref index ba7997bf..093c0b1d 100644 --- a/check/classic/classic.ref +++ b/check/classic/classic.ref @@ -30,6 +30,13 @@ ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:40: new_method: Should not be detected ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:41: public_method_label: Should not be detected ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.mli:10: I.x: Should not be detected +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./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 @@ -151,6 +158,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Should not be detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m: Not detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -576,6 +606,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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: ... -> (... -> ?_:_ -> ...) -> ... @@ -623,7 +656,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 536 -Success: 531 -Failed: 5 -Ratio: 99.0671641791% +Total: 557 +Success: 550 +Failed: 7 +Ratio: 98.7432675045% diff --git a/check/internal/internal.exp b/check/internal/internal.exp index 0b9dfad1..e6137438 100644 --- a/check/internal/internal.exp +++ b/check/internal/internal.exp @@ -15,6 +15,13 @@ ./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -101,6 +108,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -526,6 +556,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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/internal/internal.ref b/check/internal/internal.ref index 9c869823..5ba89818 100644 --- a/check/internal/internal.ref +++ b/check/internal/internal.ref @@ -20,6 +20,13 @@ ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:40: new_method: Should not be detected ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:41: public_method_label: Should not be detected ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.mli:10: I.x: Should not be detected +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -106,6 +113,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Should not be detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m: Not detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -531,6 +561,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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: ... -> (... -> ?_:_ -> ...) -> ... @@ -578,7 +611,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 494 -Success: 489 -Failed: 5 -Ratio: 98.987854251% +Total: 515 +Success: 508 +Failed: 7 +Ratio: 98.640776699% diff --git a/check/threshold-1/threshold-1.exp b/check/threshold-1/threshold-1.exp index 7f8b44f8..a330fc91 100644 --- a/check/threshold-1/threshold-1.exp +++ b/check/threshold-1/threshold-1.exp @@ -15,6 +15,13 @@ ./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -133,6 +140,24 @@ ./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/docs/methods/code_constructs/class/class_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/class_type/class_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/object_type/object_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml:2: push_n_times + +./examples/docs/methods/limitations/alias/alias_lib.mli:8: alias + ./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 @@ -338,6 +363,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -398,6 +446,34 @@ Nothing else to report in this section .>-> ALMOST UNUSED METHODS: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#used_by_requirement + +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#peek +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#pop +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#push + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used_by_child + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#peek +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#pop +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#push + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#internally_used ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#externally_used @@ -903,6 +979,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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 0f3a3f17..ce484c1c 100644 --- a/check/threshold-1/threshold-1.ref +++ b/check/threshold-1/threshold-1.ref @@ -20,6 +20,13 @@ ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:40: new_method: Should not be detected ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:41: public_method_label: Should not be detected ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.mli:10: I.x: Should not be detected +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -138,6 +145,24 @@ ./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/docs/methods/code_constructs/class/class_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/class_type/class_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/object_type/object_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml:2: push_n_times + +./examples/docs/methods/limitations/alias/alias_lib.mli:8: alias + ./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 @@ -343,6 +368,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Should not be detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m: Not detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -403,6 +451,33 @@ Nothing else to report in this section .>-> ALMOST UNUSED METHODS: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#used_by_requirement + +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#peek +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#pop +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#push + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used_by_child + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#peek +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#pop +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#push + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Not detected ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#internally_used ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#externally_used @@ -908,6 +983,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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: ... -> (... -> ?_:_ -> ...) -> ... @@ -955,7 +1033,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 825 -Success: 820 -Failed: 5 -Ratio: 99.3939393939% +Total: 875 +Success: 867 +Failed: 8 +Ratio: 99.0857142857% 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 13143ef3..8992101b 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.exp +++ b/check/threshold-3-0.5/threshold-3-0.5.exp @@ -15,6 +15,13 @@ ./examples/docs/exported_values/code_constructs/module/module_lib.mli:6: M.unused +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -133,6 +140,24 @@ ./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/docs/methods/code_constructs/class/class_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/class_type/class_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/object_type/object_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml:2: push_n_times + +./examples/docs/methods/limitations/alias/alias_lib.mli:8: alias + ./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 @@ -340,6 +365,8 @@ ./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/docs/methods/limitations/alias/alias_lib.mli:2: original + ./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 @@ -445,6 +472,14 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 3 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class_type/class_type_lib.mli:10: int_stack + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack + +./examples/docs/methods/code_constructs/object_type/object_type_lib.mli:9: int_stack + ./examples/using_dune/unwrapped_lib/values/values_no_intf.ml:19: aliased_fun ./examples/using_dune/wrapped_lib/values/values_no_intf.ml:19: aliased_fun @@ -466,6 +501,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -526,6 +584,34 @@ Nothing else to report in this section .>-> ALMOST UNUSED METHODS: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#used_by_requirement + +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#peek +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#pop +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#push + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used_by_child + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#peek +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#pop +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#push + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#internally_used ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#externally_used @@ -1292,6 +1378,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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 518f3410..ffdf5ab0 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.ref +++ b/check/threshold-3-0.5/threshold-3-0.5.ref @@ -20,6 +20,13 @@ ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:40: new_method: Should not be detected ./examples/docs/exported_values/limitations/incl_same_name/oo.mli:41: public_method_label: Should not be detected ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.mli:10: I.x: Should not be detected +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory + ./examples/using_dune/preprocessed_lib/preprocessed.mli:1: unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:2: unused @@ -138,6 +145,24 @@ ./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/docs/methods/code_constructs/class/class_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/class_type/class_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/object_type/object_type_bin.ml:4: push_n_times + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml:2: push_n_times + +./examples/docs/methods/limitations/alias/alias_lib.mli:8: alias + ./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 @@ -345,6 +370,8 @@ ./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/docs/methods/limitations/alias/alias_lib.mli:2: original + ./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 @@ -450,6 +477,14 @@ .>-> ALMOST UNUSED EXPORTED VALUES: Called 3 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class_type/class_type_lib.mli:10: int_stack + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack + +./examples/docs/methods/code_constructs/object_type/object_type_lib.mli:9: int_stack + ./examples/using_dune/unwrapped_lib/values/values_no_intf.ml:19: aliased_fun ./examples/using_dune/wrapped_lib/values/values_no_intf.ml:19: aliased_fun @@ -471,6 +506,29 @@ Nothing else to report in this section .> UNUSED METHODS: ================= +./examples/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +./examples/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#unused +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Should not be detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:2: factory_with_intermediate_binding#m: Not detected +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#unused ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#unused @@ -531,6 +589,33 @@ Nothing else to report in this section .>-> ALMOST UNUSED METHODS: Called 1 time(s): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#used_by_requirement + +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#peek +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#pop +./examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#push + +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#peek +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#pop +./examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#push + +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used +./examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#used_by_child + +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#peek +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#pop +./examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#push + +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used +./examples/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias: Not detected ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:6: immediate#internally_used ./examples/using_dune/preprocessed_lib/preprocessed_no_intf.ml:12: immediate#externally_used @@ -1297,6 +1382,9 @@ Nothing else to report in this section ./examples/docs/exported_values/limitations/sigincl/sigincl_lib.ml:9: unit pattern x +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:3: let x = ... in x (=> useless binding) +./examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:12: let x = ... in x (=> useless binding) + ./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: ... -> (... -> ?_:_ -> ...) -> ... @@ -1344,7 +1432,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 1137 -Success: 1132 -Failed: 5 -Ratio: 99.5602462621% +Total: 1192 +Success: 1184 +Failed: 8 +Ratio: 99.3288590604% diff --git a/docs/USER_DOC.md b/docs/USER_DOC.md index 0fff3c01..f1d813ff 100644 --- a/docs/USER_DOC.md +++ b/docs/USER_DOC.md @@ -54,6 +54,7 @@ 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. +- [Methods](methods/METHODS.md) describes the semantics and usage of the "unused methods" report section, and provides examples. ## Footnotes diff --git a/docs/methods/METHODS.md b/docs/methods/METHODS.md new file mode 100644 index 00000000..1ad372f9 --- /dev/null +++ b/docs/methods/METHODS.md @@ -0,0 +1,343 @@ +# Table of contents + ++ [Methods](#methods) + + [Definitions](#definitions) + + [Compiler warnings](#compiler-warnings) + + [Warning 26: unused-ancestor](#warning-36-unused-ancestor) + + [Usage](#usage) ++ [Examples](#examples) ++ [Limitations](#limitations) + +[Class type](#class-type) + +[Object type](#object-type) + +[Alias](#alias) + +[Factory function](#factory-function) + +# Methods + +## Definitions + +A **method** is declared using the `method` keyword in the definition of a class +or an immediate object, or as a field of an object type. + +An **instance variable** is declared using the `val` keyword in the definition +of a class or an immediate object. It does not appear in object types. + +A **public** method is not a private method. +A **private** method is one declared with the `private` keyword. + +An **exported** method is one that exists in its compilation unit's signature + +A **use** is either : +- An explicit reference. + E.g. + ```OCaml + let o = object method answer = 42 end + let () = print_int o#answer + ``` + The method `answer` is explicitly referenced in `o#answer`. +- A requirement for that method to exist. + E.g. + ```OCaml + let print_answer param = print_int param#answer + let o = object method answer = 42 end + let () = print_answer o + ``` + The type of `print_answer` is `< answer : int; .. > -> unit`, meaning that its + arguments are required to at least provide a method named `answer`. Therefore, + `o#answer` is used by requirement in `print_answer o`. If `o` did not provide + method `answer`, then the compilation would fail with an error like : + ``` + File "requirement.ml", line 4, characters 22-23: + 4 | let () = print_answer o + ^ + Error: This expression has type < > but an expression was expected of type + < answer : int; .. > + The first object type has no method answer + ``` + +## Compiler warnings + +The analyzer reports unused exported public methods. The compiler does not +report unused methods (private or public, exported or not, from a class, an +immediate, or an object type), not instance vraiables. Thus, the 2 tools do not +complement each other. + +> [!WARNING] +> Only a portion of the unused object-related code can be reported using the +> compiler and the analyzer : unused exported public methods. Unused private or +> unexported methods, as well as unused instance variables will remain +> undetected. + +> [!IMPORTANT] +> Exported values of object or class types belong to the +> [Exported values](../exported_values/EXPORTED_VALUES.md) section. + +Although the compiler does not report unused methods or instance variables, it +still has a few object-related warnings, of which one is related to unused code +constructs : warning 36. + +### Warning 36: unused-ancestor + +This warning is disabled by default. +I can be enabled by passing the `-w +36` to the compiler. + +Description: +``` +36 [unused-ancestor] Unused ancestor variable. (since 4.00) +``` + +Example: +```OCaml +(* warning36.ml *) +class c1 = object end +class c2 = object + inherit c1 as super +end +``` +``` +$ ocamlopt -w +36 warning36.ml +File "warning36.ml", line 4, characters 3-22: +4 | inherit c1 as super + ^^^^^^^^^^^^^^^^^^^ +Warning 36 [unused-ancestor]: unused ancestor variable super. +``` + +## Usage + +Unused exported public methods are reported by default. +Their reports can be deactivated by using the `--nothing` or `-M nothing` +command line arguments. +They can be reactivated by using the `--all` or `-M 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: + +``` +.> UNUSED METHODS: +================= +filepath:line: source#method + +Nothing else to report in this section +-------------------------------------------------------------------------------- +``` +The report line format is `filepath:line: value` with `filepath` the absolute +path to the file (`.mli` if available, `.ml` otherwise) where `source` is +declared, `line` the line index in `filepath` at which `source` is declared, +`source` the path of the object/class within its compilation unit (e.g. `M.c`) +which declares `method`, and `method` the unused method. +There can be any number of such lines. + +The expected resolution for an unused exported public method is to remove it +from the `.mli` if there is one and the `.ml`. + +> [!IMPORTANT] +> Removing unused methods or values from the codebase may trigger the detection +> of new unused methods, or remove some for values of object types. +> Consequently, it is expected that a user might need to compile and analyze +> their code multiple times when cleaning up their codebase. + +# Examples + +- The [code constructs](./code_constructs) directory contains a collection of + examples dedicated to specific code constructs : + - [Class](./code_constructs/CLASS.md) + - [Polymorphic class](./code_constructs/CLASS.md) + - [Constructor](./code_constructs/CONSTRUCTOR.md) + - [Class type](./code_constructs/CLASS_TYPE.md) + - [Inheritance](./code_constructs/INHERITANCE.md) + - [Immediate object](./code_constructs/IMMEDIATE_OBJECT.md) + - [Factory function](./code_constructs/FACTORY_FUN.md) + - [Object type](./code_constructs/OBJECT_TYPE.md) + - [Coercion](./code_constructs/COERCION.md) + +# Limitations + +## Class type + +As explained in the [Class type](./code_constructs/CLASS_TYPE.md) example, the +analyzer is currently restricted to not reporting methods declared in class +type definitions. + +## Object type + +As explained in the [Object type](./code_constructs/OBJECT_TYPE.md) example, the +analyzer is currently restricted to not reporting methods declared in object +types. + +## Alias + +Related issue : +[issue #66](https://github.com/LexiFi/dead_code_analyzer/issues/66). + +In the presence of multiple bindings to the same object, the analyzer corrctly +avoids tracking their methods individually. However, it fails at unifying them +and only keeps track of the methods used through the original binding, where the +methods are defined. This leads to **false positives**. + +### Example + +The reference files for this example are in the +[alias](../../examples/docs/methods/limitations/alias) directory. + +The reference takes place in `/tmp/docs/methods/limitations`, which +is a copy of the [limitations](../../../examples/docs/methods/limitations) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C alias build +``` + +The analysis command is : +``` +make -C alias analyze +``` + +The compile + analyze command is : +``` +make -C alias +``` + +Code: +```OCaml +(* alias_lib.mli *) +val original : + < used : unit + ; used_by_alias : unit + ; unused : unit + > + +val alias : + < used : unit + ; used_by_alias : unit + ; unused : unit + > +``` +```OCaml +(* alias_lib.ml *) +let original = + object + method used = () + method used_by_alias = () + method unused = () + end + +let alias = original +``` +```OCaml +(* alias_bin.ml *) +open Alias_lib + +let () = + original#used; + alias#used_by_alias +``` + +Compile and analyze: +``` +$ make -C alias +make: Entering directory '/tmp/docs/methods/limitations/alias' +ocamlopt -bin-annot alias_lib.mli alias_lib.ml alias_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/limitations/alias/alias_lib.mli:2: original#unused +/tmp/docs/methods/limitations/alias/alias_lib.mli:2: original#used_by_alias + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/limitations/alias' +``` + +The analyzer reports `original#used_by_alias` although it is used by +`alias#used_by_alias`. + +## Factory function + +Related issue : +[issue #67](https://github.com/LexiFi/dead_code_analyzer/issues/67). + +Factory functions' methods analysis is currently very limited to situations like +the one in the [Factory function](./code_constructs/FACTORY_FUN.md) example : +functions without intermediate binding to the returned object in at least one +branch. I.e. if in all the branches, the result object is bound to a name, then +the analyzer fails to track its methods. This leads to **false negatives**. + +### Example + +The reference files for this example are in the +[factory\_fun\_indir](../../examples/docs/methods/limitations/factory_fun_indir) directory. + +The reference takes place in `/tmp/docs/methods/limitations`, which +is a copy of the [limitations](../../../examples/docs/methods/limitations) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C factory_fun_indir build +``` + +The analysis command is : +``` +make -C factory_fun_indir analyze +``` + +The compile + analyze command is : +``` +make -C factory_fun_indir +``` + +Code: +```OCaml +(* factoy_fun_indir.ml *) +let factory_with_intermediate_binding () = + let res = + object method m = () end + in + res + +let random_factory () = + if Random.bool () then + object method m = () end + else + let res = object method m = () end in + res +``` + +Compile and analyze: +``` +$ make -C factory_fun_indir +make: Entering directory '/tmp/docs/methods/limitations/factory_fun_indir' +ocamlopt -bin-annot factory_fun_indir.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml:8: random_factory#m + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/limitations/factory_fun_indir' +``` + +The analyzer correctly reports `random_factory#m` because its last expression in +the `if` branch is the object's definition. It does not report +`factory_with_intermediate_binding#m` because the returned object is bound +inside the function. + +> [!NOTE] +> The analyzer does not distinguish which object is actually returned when there +> are alternatives like in `random_factory`. Only uses outside of the function +> are accounted for. E.g. using `res#m` in the `else` branch does not count. diff --git a/docs/methods/code_constructs/CLASS.md b/docs/methods/code_constructs/CLASS.md new file mode 100644 index 00000000..f2586903 --- /dev/null +++ b/docs/methods/code_constructs/CLASS.md @@ -0,0 +1,218 @@ +The reference files for this example are in the +[class](../../../examples/docs/methods/code_constructs/class) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C class build +``` + +The analysis command is : +``` +make -C class analyze +``` + +The compile + analyze command is : +``` +make -C class +``` + +## First run + +Code: +```OCaml +(* class_lib.mli *) +class int_stack : + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end +``` +```OCaml +(* class_lib.ml *) +class int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* class_bin.ml *) +class unused_class = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Class_lib.int_stack in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +Before looking at the analysis results, let's look at the code. + +The `Class_lib` declares and exports 1 class : `int_stack`. An instance of this +class is used in `Class_bin`. +`Class_bin` declares and exports 1 class : `unused_class`, which is unused. +All of the methods are public, so they are tracked by the analyzer. + +2 methods are explicitly referenced : `int_stack#peek`, and `int_stack#pop`. +1 method is used by requirement : `int_stack#push`, required by the call +`push_n_times n int_stack`. + +This leaves only 2 unused methods : `int_stack#reset` and +`unused_obj#unused_method`. + +Compile and analyze: +``` +$ make -C class +make: Entering directory '/tmp/docs/methods/code_constructs/class' +ocamlopt -bin-annot class_lib.mli class_lib.ml class_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/class/class_bin.ml:2: unused_class#unused_method +/tmp/docs/methods/code_constructs/class/class_lib.mli:2: int_stack#reset + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/class' +``` + +As expected, 2 methods are reported unused : `unused_class#unused_method`, and +`int_stack#reset`. These can be removed from the class definitions at the +reported locations. + +> [!IMPORTANT] +> The reported locations are those of the classes to which the methods belong. + +> [!NOTE] +> The objects manipulated in this example are instances of classes. Thus, their +> methods are those of their classes. +> If the analyzer reported unused methods for each instance, a user would need +> to explicit the signature of each object rather than simply rely on the +> (possibly inferred) defined class type. This is a non-trivial resolution +> of unused methods, effectively losing the benefits of using class types. +> Consequently, the analyzer does not report unused methods of instances but +> only of the classes they belong to. + +In addition to these unused methods, there is the unused exported class +`unused_class` which is currently not reportable by the analyzer. + +## Removing the unused methods + +> [!TIP] +> Do not forget to remove `int_stack#reset` from both the `.mli` **and** the `.ml`. +> Otherwise, the compiler will reject the code with a message like : +> ``` +> File "class_lib.ml", line 1: +> Error: The implementation class_lib.ml +> does not match the interface class_lib.mli: +> Class declarations do not match: +> class int_stack : +> object +> val mutable l : int list +> method peek : int option +> method pop : unit +> method push : int -> unit +> method reset : unit +> end +> does not match +> class int_stack : +> object +> method peek : int option +> method pop : unit +> method push : int -> unit +> end +> The public method reset cannot be hidden +> ``` + +Code: +```OCaml +(* class_lib.mli *) +class int_stack : + object + method push : int -> unit + method pop : unit + method peek : int option + end +``` +```OCaml +(* class_lib.ml *) +class int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + end +``` +```OCaml +(* class_bin.ml *) +class unused_class = object end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Class_lib.int_stack in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +Compile and analyze: +``` +$ make -C class +make: Entering directory '/tmp/docs/methods/code_constructs/class' +ocamlopt -bin-annot class_lib.mli class_lib.ml class_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/class' +``` + +There is no more unused method. Our work here is done. diff --git a/docs/methods/code_constructs/CLASS_TYPE.md b/docs/methods/code_constructs/CLASS_TYPE.md new file mode 100644 index 00000000..263cb84a --- /dev/null +++ b/docs/methods/code_constructs/CLASS_TYPE.md @@ -0,0 +1,113 @@ +The reference files for this example are in the +[class\_type](../../../examples/docs/methods/code_constructs/class_type) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C class_type build +``` + +The analysis command is : +``` +make -C class_type analyze +``` + +The compile + analyze command is : +``` +make -C class_type +``` + +> [!IMPORTANT] +> **LIMITATION** +> +> Methods declared in class types definition (different from class signatures) +> are currently ignored by the analyzer. + +## First run + +Code: +```OCaml +(* class_type_lib.mli *) +class type int_stack = + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end + +val int_stack : int_stack +``` +```OCaml +(* class_type_lib.ml *) +class type int_stack = + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end + +let int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* class_type_bin.ml *) +class type unused_class_type = object method unused_method : unit end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Class_type_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +By looking at the code, we could make the same observation as in the +[Class](./CLASS.md) example. + +However, because of the current limitation on class types, nothing is expected +to reported. + +Code and analyze: +``` +$ make -C class_type +make: Entering directory '/tmp/docs/methods/code_construct/class_type' +ocamlopt -bin-annot class_type_lib.mli class_type_lib.ml class_type_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_construct/class_type' +``` + +Nothing is reported. Our work here is done. diff --git a/docs/methods/code_constructs/COERCION.md b/docs/methods/code_constructs/COERCION.md new file mode 100644 index 00000000..6b05bffd --- /dev/null +++ b/docs/methods/code_constructs/COERCION.md @@ -0,0 +1,82 @@ +The reference files for this example are in the +[coercion](../../../examples/docs/methods/code_constructs/coercion) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C coercion build +``` + +The analysis command is : +``` +make -C coercion analyze +``` + +The compile + analyze command is : +``` +make -C coercion +``` + +## First run + +Code: +```OCaml +(* coercion_lib.mli *) +val obj : + < used_by_requirement : unit + ; unused : unit + > +``` +```OCaml +(* coercion_lib.ml *) +let obj = + object + method used_by_requirement = () + method unused = () + end +``` +```OCaml +(* coercion_bin.ml *) +open Coercion_lib + +let () = + let _coerce = (obj :> < used_by_requirement : unit >) in + () +``` + +Before looking at the analysis results, let's look at the code. + +There is 1 object : `Coercion_lib.obj`, which defined 2 zmthods : +`used_by_requirement`, and `unused`. Neither of them is explicitly referenced, +and the object is only manipulated through a coercion. The coercion produces an +alias to `obj` named `_coerce`, which only exposes the method +`used_by_requirement`. Because the method is required to exists in `obj` for the +coercion, then the analyzer effectively considers it as used by requirement. + +Compile and analyze: +``` +$ make -C coercion +make: Entering directory '/tmp/docs/methods/code_constructs/coercion' +ocamlopt -bin-annot coercion_lib.mli coercion_lib.ml coercion_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/coercion/coercion_lib.mli:2: obj#unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/coercion' +``` + +As expected, the anlyzer reports `obj#unsed` as unused and not +`obj#used_by_requirement`. The unused method can be removed from the `.mli` and +the `.ml`. Our work here is done. diff --git a/docs/methods/code_constructs/CONSTRUCTOR.md b/docs/methods/code_constructs/CONSTRUCTOR.md new file mode 100644 index 00000000..a604d81c --- /dev/null +++ b/docs/methods/code_constructs/CONSTRUCTOR.md @@ -0,0 +1,101 @@ +The reference files for this example are in the +[constructor](../../../examples/docs/methods/code_constructs/constructor) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C constructor build +``` + +The analysis command is : +``` +make -C constructor analyze +``` + +The compile + analyze command is : +``` +make -C constructor +``` + +## First run + +Code: +```OCaml +(* constructor_lib.mli *) +class int_stack : + int list -> + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end +``` +```OCaml +(* constructor_lib.ml *) +class int_stack init = + object + val mutable l : int list = init + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* constructor_bin.ml *) +class unused_class _ = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Constructor_lib.int_stack [] in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +The code is very similar to the one of the [Class](./CLASS.md) example, with a +small twist : the classes have initialisers. Because the analyzer does not track +each instance' methods uses individually but unified whith the defining class, +the presence of initialisers should not make a difference and the expected +results are the same as in the [Class](./CLASS.md) example. + +Compile and analyze: +``` +$ make -C constructor +make: Entering directory '/tmp/docs/methods/code_constructs/constructor' +ocamlopt -bin-annot constructor_lib.mli constructor_lib.ml constructor_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/constructor/constructor_bin.ml:2: unused_class#unused_method +/tmp/docs/methods/code_constructs/constructor/constructor_lib.mli:2: int_stack#reset + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/constructor' +``` + +The results are the same as expected. The resolution is already detailed in the +[Class](./CLASS.md) example. Our work here is done. diff --git a/docs/methods/code_constructs/FACTORY_FUN.md b/docs/methods/code_constructs/FACTORY_FUN.md new file mode 100644 index 00000000..bffaf5ac --- /dev/null +++ b/docs/methods/code_constructs/FACTORY_FUN.md @@ -0,0 +1,128 @@ +The reference files for this example are in the +[factory_fun](../../../examples/docs/methods/code_constructs/factory_fun) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C factory_fun build +``` + +The analysis command is : +``` +make -C factory_fun analyze +``` + +The compile + analyze command is : +``` +make -C factory_fun +``` + +> [!IMPORTANT] +> **LIMITATION** +> +> Only factory functions that return the object without intermediate binding +> in at least one branch are understood by the analyzer. This may lead to +> **false negatives**. +> See [Factory function | Limitations](../METHODS.md#factory-function). +> +> Storing the result of a factory function in a new binding breaks the analysis. +> Although 2 calls to the same factory function may produce different objects, +> they are considered to be the same by the analyzer. Hence, storing the result +> in a new binding is similar to an alias, which may lead to **false positives**. +> See [Alias | Limitations](../METHODS.md#alias) + +## First run + +Code: +```OCaml +(* factoy_fun_lib.mli *) +val get_stack : + unit -> + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > +``` +```OCaml +(* factoy_fun_lib.ml *) +let stack = ref [] + +let get_stack () = + object + method push x = stack := x::!stack + method pop = + match !stack with + | [] -> () + | _::tl -> stack := tl + method peek = + match !stack with + | [] -> None + | hd::_ -> Some hd + method reset = stack := [] + end +``` +```OCaml +(* factoy_fun_bin.ml *) +let unused_factory () = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Factory_fun_lib in + let n = 42 in + push_n_times n (get_stack ()); + while (get_stack ())#peek <> None do + (get_stack ())#pop; + done +``` + +Before looking at the analysis results, let's look at the code. + +The `Factory_fun_lib` declares and exports 1 factory function `get_stack` which +takes `unit` as parameter and returns a fresh object. The return object has +4 methods, manipulating the unexported value `stack`. +1 of these methods is used by requirement : `push`. +2 of these methods are explicitly referenced : `peek`, and `pop`. +This leaves `reset` as unused. + +The `Factory_fun_bin` declares and exports 1 factory function `unused_factory` +which takes `unit` as parameter and returns a fresh object with one method +`unused_method`. This function is unused, leaving its method unused too. + +Compile and analyze: +``` +$ make -C factory_fun +make: Entering directory '/tmp/docs/methods/code_constructs/factory_fun' +ocamlopt -bin-annot factory_fun_lib.mli factory_fun_lib.ml factory_fun_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml:2: unused_factory#unused_method +/tmp/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli:2: get_stack#reset + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/factory_fun' +``` + +As expected, the analyzer reports `unused_factory#unused_method` and +`get_stack#reset` as unused. Following the report line format +`filepath:line: source#method`, here the sources are the functions themselves. +Indeed, the returned objects are defined as the immediate results of the +functions, making the functions behave similarly to class constructors. + +The reported methods can be removed from the `.mli` and `.ml`. +Our work here is done. diff --git a/docs/methods/code_constructs/IMMEDIATE_OBJECT.md b/docs/methods/code_constructs/IMMEDIATE_OBJECT.md new file mode 100644 index 00000000..b7185e0c --- /dev/null +++ b/docs/methods/code_constructs/IMMEDIATE_OBJECT.md @@ -0,0 +1,232 @@ +The reference files for this example are in the +[immediate\_object](../../../examples/docs/methods/code_constructs/immediate_object) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C immediate_object build +``` + +The analysis command is : +``` +make -C immediate_object analyze +``` + +The compile + analyze command is : +``` +make -C immediate_object +``` + +## First run + +Code: +```OCaml +(* immediate_object_lib.mli *) +val int_stack : + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > +``` +```OCaml +(* immediate_object_lib.ml *) +let int_stack = + object + val mutable l = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* immediate_object_bin.ml *) +let unused_obj = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Immediate_object_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +Before looking at the analysis results, let's look at the code. + +The `Imm_obj_lib` declares and exports 1 object : `int_stack`, which is used by +`Imm_obj_bin`. `Imm_obj_bin` declares and exports 1 object : `unused_obj`, which +is unused. All of the methods are public, so they are tracked by the analyzer. + +2 methods are explicitly referenced : `int_stack#peek`, and `int_stack#pop`. +1 method is used by requirement : `int_stack#push`, required by the call +`push_n_times n int_stack`. + +This leaves only 2 unused methods : `int_stack#reset` and +`unused_obj#unused_method`. + +Compile and analyze: +``` +$ make -C immediate_object +make: Entering directory '/tmp/docs/methods/code_constructs/immediate_object' +ocamlopt -bin-annot immediate_object_lib.mli immediate_object_lib.ml immediate_object_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj#unused_method +/tmp/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli:2: int_stack#reset + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/immediate_object' +``` + +As expected, 2 methods are reported unused : `unused_obj#unused_method`, and +`int_stack#reset`. These can be removed from the object definitions at the +reported locations. + +> [!IMPORTANT] +> The reported locations are those of the objects to which the methods belong. + +In addition to these unused methods, there is the unused exported value +`unused_obj` which is not reported because we disabled the analysis of unused +values when passing `--nothing` to the analyzer. Let's update the Makefile and +pass `-E all` to the analyzer to enable that analysis. + +``` +SRC:=immediate_object_lib.mli immediate_object_lib.ml immediate_object_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -E all -M all . + +clean: + rm -f *.cm* *.o a.out +``` + +## Removing the unused methods + +> [!TIP] +> Do not forget to remove `int_stack#reset` from both the `.mli` **and** the `.ml`. +> Otherwise, the compiler will reject the code with a message like : +> ``` +> File "immediate_object_lib.ml", line 1: +> Error: The implementation immediate_object_lib.ml +> does not match the interface immediate_object_lib.mli: +> Values do not match: +> val int_stack : +> < peek : '_weak1 option; pop : unit; push : '_weak1 -> unit; +> reset : unit > +> is not included in +> val int_stack : +> < peek : int option; pop : unit; push : int -> unit > +> The type +> < peek : '_weak1 option; pop : unit; push : '_weak1 -> unit; +> reset : unit > +> is not compatible with the type +> < peek : int option; pop : unit; push : int -> unit > +> The second object type has no method reset +> File "immediate_object_lib.mli", lines 2-6, characters 0-3: +> Expected declaration +> File "immediate_object_lib.ml", line 2, characters 4-13: +> Actual declaration +> ``` + +Code: +```OCaml +(* immediate_object_lib.mli *) +val int_stack : + < push : int -> unit + ; pop : unit + ; peek : int option + > +``` +```OCaml +(* immediate_object_lib.ml *) +let int_stack = + object + val mutable l = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + end +``` +```OCaml +(* immediate_object_bin.ml *) +let unused_obj = object end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Immediate_object_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +Compile and analyze: +``` +$ make -C immediate_object +make: Entering directory '/tmp/docs/methods/code_constructs/immediate_object' +ocamlopt -bin-annot immediate_object_lib.mli immediate_object_lib.ml immediate_object_bin.ml +dead_code_analyzer --nothing -E all -M all . +Scanning files... + [DONE] + +.> UNUSED EXPORTED VALUES: +========================= +/tmp/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml:2: unused_obj + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +.> UNUSED METHODS: +================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/immediate_object' +``` + +There is no more unused method. The unused exported value can be removed as +explained in the [Exported values](../../exported_values/EXPORTED_VALUES.md) documentation. +Our work here is done diff --git a/docs/methods/code_constructs/INHERITANCE.md b/docs/methods/code_constructs/INHERITANCE.md new file mode 100644 index 00000000..5e3eb7ab --- /dev/null +++ b/docs/methods/code_constructs/INHERITANCE.md @@ -0,0 +1,105 @@ +The reference files for this example are in the +[inheritance](../../../examples/docs/methods/code_constructs/inheritance) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C inheritance build +``` + +The analysis command is : +``` +make -C inheritance analyze +``` + +The compile + analyze command is : +``` +make -C inheritance +``` + +## First run + +Code: +```OCaml +(* inheritance_lib.mli *) +class parent : + object + method unused : unit + method used : unit + method used_by_child : unit + end + +class child : + object + inherit parent + end +``` +```OCaml +(* inheritance_lib.ml *) +class parent = + object + method unused = () + method used = () + method used_by_child = () + end + +class child = + object + inherit parent + end +``` +```OCaml +(* inheritance_bin.ml *) +let () = + let p = new Inheritance_lib.parent in + let c = new Inheritance_lib.child in + p#used; + c#used_by_child +``` + +The code is pretty straightforward. `Inheritance_lib` defines 2 classes : +- `parent`, which defines 3 methods; +- `child`, which only inherits `parent`. + +CLass inheritance is semantically equivalent to module inclusion from the +analyzer's point of view : the `parent` class is the actual "owner" of the +methods, and `child` only re-exposes them. This, has 2 consequences : +- inherited methods in `child` are not analyzed individually; +- using a method from `child` that is inherited from `parent` is the same as + using the method from `parent`. + +Now if we look at the uses, 2 methods are referenced explicitly : +- `p#used`, which is `parent#used` +- `c#used_by_child`, which is `child#used_by_child`, which is + `parent#used_by_child` + +This leaves `parent#unused` as the only unused method. + +Compile and analyze: +``` +$ make -C inheritance +make: Entering directory '/tmp/docs/methods/code_constructs/inheritance' +ocamlopt -bin-annot inheritance_lib.mli inheritance_lib.ml inheritance_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/inheritance/inheritance_lib.mli:2: parent#unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/inheritance' +``` + +As expected, the analyzer reports `parent#unused` as unused. It can be removed +from `inheritance_lib.mli` and `inheritance_lib.ml`. +Neither the compiler nor the analyzer will report unused methods anymore. +Our work here is done. diff --git a/docs/methods/code_constructs/OBJECT_TYPE.md b/docs/methods/code_constructs/OBJECT_TYPE.md new file mode 100644 index 00000000..8bcd8b66 --- /dev/null +++ b/docs/methods/code_constructs/OBJECT_TYPE.md @@ -0,0 +1,108 @@ +The reference files for this example are in the +[object\_type](../../../examples/docs/methods/code_constructs/object_type) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C object_type build +``` + +The analysis command is : +``` +make -C object_type analyze +``` + +The compile + analyze command is : +``` +make -C object_type +``` + +> [!IMPORTANT] +> **LIMITATION** +> +> Methods declared in object types are currently ignored by the analyzer. + +## First run + +Code: +```OCaml +(* object_type_lib.mli *) +type int_stack = + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > + +val int_stack : int_stack +``` +```OCaml +(* object_type_lib.ml *) +type int_stack = + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > + +let int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* object_type_bin.ml *) +type unused_t = < unused_method : unit > + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Object_type_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +By looking at the code, we could make the same observation as in the +[Class type](./CLASS_TYPE.md) example. The analyzer's semantics are equivalent +so the results are the same as well. + +Code and analyze: +``` +$ make -C object_type +make: Entering directory '/tmp/docs/methods/code_construct/object_type' +ocamlopt -bin-annot object_type_lib.mli object_type_lib.ml object_type_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_construct/object_type' +``` + +Nothing is reported. Our work here is done. diff --git a/docs/methods/code_constructs/POLYMORPHIC_CLASS.md b/docs/methods/code_constructs/POLYMORPHIC_CLASS.md new file mode 100644 index 00000000..a59b2eb1 --- /dev/null +++ b/docs/methods/code_constructs/POLYMORPHIC_CLASS.md @@ -0,0 +1,106 @@ +The reference files for this example are in the +[polymorphic\_class](../../../examples/docs/methods/code_constructs/polymorphic_class) directory. + +The reference takes place in `/tmp/docs/methods/code_constructs`, which +is a copy of the [code\_constructs](../../../examples/docs/methods/code_constructs) +directory. Reported locations may differ depending on the location of the source +files. + +The compilation command is : +``` +make -C polymorphic_class build +``` + +The analysis command is : +``` +make -C polymorphic_class analyze +``` + +The compile + analyze command is : +``` +make -C polymorphic_class +``` + +## First run + +Code: +```OCaml +(* polymorphic_class_lib.mli *) +class ['a] stack : + object + method push : 'a -> unit + method pop : unit + method peek : 'a option + method reset : unit + end +``` +```OCaml +(* polymorphic_class_lib.ml *) +class ['a] stack = + object + val mutable l : 'a list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end +``` +```OCaml +(* polymorphic_class_bin.ml *) +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Polymorphic_class_lib.stack in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done +``` + +Before looking at the analysis results, let's look at the code. + +This example is very similar to the [Class](./CLASS.md) example, without the +`unused_class` class. Instead of using an definitive `int_stack` class, the +`Polymorphic_class_lib` defines a polymorphic `['a] stack` class. + +Methods `push`, `peek`, and `pop` are used, leaving `reset` as the only unused method. + +Compile and analyze: +``` +$ make -C polymorphic_class/ +make: Entering directory '/tmp/docs/methods/code_constructs/polymorphic_class' +ocamlopt -bin-annot polymorphic_class_lib.mli polymorphic_class_lib.ml polymorphic_class_bin.ml +dead_code_analyzer --nothing -M all . +Scanning files... + [DONE] + +.> UNUSED METHODS: +================= +/tmp/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli:2: stack#reset + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/methods/code_constructs/polymorphic_class' +``` + +As expected, the analyzer reports `stack#reset` as unused. + +> [!NOTE] +> The analyzer does not specify the type parameter of `stack`. This is because +> it does not distinguish the monomorphizations of `stack` and its polymoprhic +> definition. + +After removing the reported unused methods, the analyzer will not find anymore +unused method. Our work here is done. diff --git a/examples/docs/Makefile b/examples/docs/Makefile index ae38a077..3c8cfe69 100644 --- a/examples/docs/Makefile +++ b/examples/docs/Makefile @@ -4,8 +4,10 @@ all: build build: make -C exported_values + make -C methods clean: rm -f *~ *.cm* *.o *.obj make -C exported_values clean + make -C methods clean diff --git a/examples/docs/methods/Makefile b/examples/docs/methods/Makefile new file mode 100644 index 00000000..da62ef35 --- /dev/null +++ b/examples/docs/methods/Makefile @@ -0,0 +1,13 @@ +.PHONY: clean build + +all: build + +build: + make -C code_constructs + make -C limitations + +clean: + rm -f *~ *.cm* *.o *.obj + make -C code_constructs clean + make -C limitations clean + diff --git a/examples/docs/methods/code_constructs/Makefile b/examples/docs/methods/code_constructs/Makefile new file mode 100644 index 00000000..33cff97b --- /dev/null +++ b/examples/docs/methods/code_constructs/Makefile @@ -0,0 +1,27 @@ +.PHONY: clean build + +all: build + +build: + make -C class build + make -C polymorphic_class build + make -C constructor build + make -C class_type build + make -C inheritance build + make -C immediate_object build + make -C factory_fun build + make -C object_type build + make -C coercion build + +clean: + rm -f *~ *.cm* *.o *.obj + make -C class clean + make -C polymorphic_class clean + make -C constructor clean + make -C class_type clean + make -C inheritance clean + make -C immediate_object clean + make -C factory_fun clean + make -C object_type clean + make -C coercion clean + diff --git a/examples/docs/methods/code_constructs/class/Makefile b/examples/docs/methods/code_constructs/class/Makefile new file mode 100644 index 00000000..7b8a068e --- /dev/null +++ b/examples/docs/methods/code_constructs/class/Makefile @@ -0,0 +1,12 @@ +SRC:=class_lib.mli class_lib.ml class_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/class/class_bin.ml b/examples/docs/methods/code_constructs/class/class_bin.ml new file mode 100644 index 00000000..335070dd --- /dev/null +++ b/examples/docs/methods/code_constructs/class/class_bin.ml @@ -0,0 +1,15 @@ +(* class_bin.ml *) +class unused_class = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Class_lib.int_stack in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/class/class_lib.ml b/examples/docs/methods/code_constructs/class/class_lib.ml new file mode 100644 index 00000000..518fc97a --- /dev/null +++ b/examples/docs/methods/code_constructs/class/class_lib.ml @@ -0,0 +1,15 @@ +(* class_lib.ml *) +class int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/class/class_lib.mli b/examples/docs/methods/code_constructs/class/class_lib.mli new file mode 100644 index 00000000..67f815e1 --- /dev/null +++ b/examples/docs/methods/code_constructs/class/class_lib.mli @@ -0,0 +1,8 @@ +(* class_lib.mli *) +class int_stack : + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end diff --git a/examples/docs/methods/code_constructs/class_type/Makefile b/examples/docs/methods/code_constructs/class_type/Makefile new file mode 100644 index 00000000..46bc7680 --- /dev/null +++ b/examples/docs/methods/code_constructs/class_type/Makefile @@ -0,0 +1,12 @@ +SRC:=class_type_lib.mli class_type_lib.ml class_type_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/class_type/class_type_bin.ml b/examples/docs/methods/code_constructs/class_type/class_type_bin.ml new file mode 100644 index 00000000..d759e973 --- /dev/null +++ b/examples/docs/methods/code_constructs/class_type/class_type_bin.ml @@ -0,0 +1,15 @@ +(* class_type_bin.ml *) +class type unused_class_type = object method unused_method : unit end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Class_type_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/class_type/class_type_lib.ml b/examples/docs/methods/code_constructs/class_type/class_type_lib.ml new file mode 100644 index 00000000..1dafd2a4 --- /dev/null +++ b/examples/docs/methods/code_constructs/class_type/class_type_lib.ml @@ -0,0 +1,23 @@ +(* class_type_lib.ml *) +class type int_stack = + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end + +let int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/class_type/class_type_lib.mli b/examples/docs/methods/code_constructs/class_type/class_type_lib.mli new file mode 100644 index 00000000..7d016c4f --- /dev/null +++ b/examples/docs/methods/code_constructs/class_type/class_type_lib.mli @@ -0,0 +1,10 @@ +(* class_type_lib.mli *) +class type int_stack = + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end + +val int_stack : int_stack diff --git a/examples/docs/methods/code_constructs/coercion/Makefile b/examples/docs/methods/code_constructs/coercion/Makefile new file mode 100644 index 00000000..cb75cadf --- /dev/null +++ b/examples/docs/methods/code_constructs/coercion/Makefile @@ -0,0 +1,12 @@ +SRC:=coercion_lib.mli coercion_lib.ml coercion_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/coercion/coercion_bin.ml b/examples/docs/methods/code_constructs/coercion/coercion_bin.ml new file mode 100644 index 00000000..757b26da --- /dev/null +++ b/examples/docs/methods/code_constructs/coercion/coercion_bin.ml @@ -0,0 +1,6 @@ +(* coercion_bin.ml *) +open Coercion_lib + +let () = + let _coerce = (obj :> < used_by_requirement : unit >) in + () diff --git a/examples/docs/methods/code_constructs/coercion/coercion_lib.ml b/examples/docs/methods/code_constructs/coercion/coercion_lib.ml new file mode 100644 index 00000000..6295cfb6 --- /dev/null +++ b/examples/docs/methods/code_constructs/coercion/coercion_lib.ml @@ -0,0 +1,6 @@ +(* coercion_lib.ml *) +let obj = + object + method used_by_requirement = () + method unused = () + end diff --git a/examples/docs/methods/code_constructs/coercion/coercion_lib.mli b/examples/docs/methods/code_constructs/coercion/coercion_lib.mli new file mode 100644 index 00000000..920bfe09 --- /dev/null +++ b/examples/docs/methods/code_constructs/coercion/coercion_lib.mli @@ -0,0 +1,5 @@ +(* coercion_lib.mli *) +val obj : + < used_by_requirement : unit + ; unused : unit + > diff --git a/examples/docs/methods/code_constructs/constructor/Makefile b/examples/docs/methods/code_constructs/constructor/Makefile new file mode 100644 index 00000000..8b7ea530 --- /dev/null +++ b/examples/docs/methods/code_constructs/constructor/Makefile @@ -0,0 +1,12 @@ +SRC:=constructor_lib.mli constructor_lib.ml constructor_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/constructor/constructor_bin.ml b/examples/docs/methods/code_constructs/constructor/constructor_bin.ml new file mode 100644 index 00000000..31c9fb5a --- /dev/null +++ b/examples/docs/methods/code_constructs/constructor/constructor_bin.ml @@ -0,0 +1,15 @@ +(* constructor_bin.ml *) +class unused_class _ = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Constructor_lib.int_stack [] in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/constructor/constructor_lib.ml b/examples/docs/methods/code_constructs/constructor/constructor_lib.ml new file mode 100644 index 00000000..db48de6f --- /dev/null +++ b/examples/docs/methods/code_constructs/constructor/constructor_lib.ml @@ -0,0 +1,15 @@ +(* constructor_lib.ml *) +class int_stack init = + object + val mutable l : int list = init + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/constructor/constructor_lib.mli b/examples/docs/methods/code_constructs/constructor/constructor_lib.mli new file mode 100644 index 00000000..723aa6a5 --- /dev/null +++ b/examples/docs/methods/code_constructs/constructor/constructor_lib.mli @@ -0,0 +1,9 @@ +(* constructor_lib.mli *) +class int_stack : + int list -> + object + method push : int -> unit + method pop : unit + method peek : int option + method reset : unit + end diff --git a/examples/docs/methods/code_constructs/factory_fun/Makefile b/examples/docs/methods/code_constructs/factory_fun/Makefile new file mode 100644 index 00000000..78329836 --- /dev/null +++ b/examples/docs/methods/code_constructs/factory_fun/Makefile @@ -0,0 +1,12 @@ +SRC:=factory_fun_lib.mli factory_fun_lib.ml factory_fun_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml b/examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml new file mode 100644 index 00000000..d30aafa1 --- /dev/null +++ b/examples/docs/methods/code_constructs/factory_fun/factory_fun_bin.ml @@ -0,0 +1,15 @@ +(* factoy_fun_bin.ml *) +let unused_factory () = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Factory_fun_lib in + let n = 42 in + push_n_times n (get_stack ()); + while (get_stack ())#peek <> None do + (get_stack ())#pop; + done diff --git a/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.ml b/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.ml new file mode 100644 index 00000000..cf79464b --- /dev/null +++ b/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.ml @@ -0,0 +1,16 @@ +(* factoy_fun_lib.ml *) +let stack = ref [] + +let get_stack () = + object + method push x = stack := x::!stack + method pop = + match !stack with + | [] -> () + | _::tl -> stack := tl + method peek = + match !stack with + | [] -> None + | hd::_ -> Some hd + method reset = stack := [] + end diff --git a/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli b/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli new file mode 100644 index 00000000..42fd5287 --- /dev/null +++ b/examples/docs/methods/code_constructs/factory_fun/factory_fun_lib.mli @@ -0,0 +1,8 @@ +(* factoy_fun_lib.mli *) +val get_stack : + unit -> + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > diff --git a/examples/docs/methods/code_constructs/immediate_object/Makefile b/examples/docs/methods/code_constructs/immediate_object/Makefile new file mode 100644 index 00000000..fdb7811a --- /dev/null +++ b/examples/docs/methods/code_constructs/immediate_object/Makefile @@ -0,0 +1,12 @@ +SRC:=immediate_object_lib.mli immediate_object_lib.ml immediate_object_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml b/examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml new file mode 100644 index 00000000..b6b71d3f --- /dev/null +++ b/examples/docs/methods/code_constructs/immediate_object/immediate_object_bin.ml @@ -0,0 +1,15 @@ +(* immediate_object_bin.ml *) +let unused_obj = object method unused_method = () end + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Immediate_object_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.ml b/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.ml new file mode 100644 index 00000000..46646150 --- /dev/null +++ b/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.ml @@ -0,0 +1,15 @@ +(* immediate_object_lib.ml *) +let int_stack = + object + val mutable l = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli b/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli new file mode 100644 index 00000000..9220599f --- /dev/null +++ b/examples/docs/methods/code_constructs/immediate_object/immediate_object_lib.mli @@ -0,0 +1,7 @@ +(* immediate_object_lib.mli *) +val int_stack : + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > diff --git a/examples/docs/methods/code_constructs/inheritance/Makefile b/examples/docs/methods/code_constructs/inheritance/Makefile new file mode 100644 index 00000000..a8db8764 --- /dev/null +++ b/examples/docs/methods/code_constructs/inheritance/Makefile @@ -0,0 +1,12 @@ +SRC:=inheritance_lib.mli inheritance_lib.ml inheritance_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/inheritance/inheritance_bin.ml b/examples/docs/methods/code_constructs/inheritance/inheritance_bin.ml new file mode 100644 index 00000000..532093f4 --- /dev/null +++ b/examples/docs/methods/code_constructs/inheritance/inheritance_bin.ml @@ -0,0 +1,6 @@ +(* inheritance_bin.ml *) +let () = + let p = new Inheritance_lib.parent in + let c = new Inheritance_lib.child in + p#used; + c#used_by_child diff --git a/examples/docs/methods/code_constructs/inheritance/inheritance_lib.ml b/examples/docs/methods/code_constructs/inheritance/inheritance_lib.ml new file mode 100644 index 00000000..8eb8b34c --- /dev/null +++ b/examples/docs/methods/code_constructs/inheritance/inheritance_lib.ml @@ -0,0 +1,12 @@ +(* inheritance_lib.ml *) +class parent = + object + method unused = () + method used = () + method used_by_child = () + end + +class child = + object + inherit parent + end diff --git a/examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli b/examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli new file mode 100644 index 00000000..1873ad9e --- /dev/null +++ b/examples/docs/methods/code_constructs/inheritance/inheritance_lib.mli @@ -0,0 +1,12 @@ +(* inheritance_lib.mli *) +class parent : + object + method unused : unit + method used : unit + method used_by_child : unit + end + +class child : + object + inherit parent + end diff --git a/examples/docs/methods/code_constructs/object_type/Makefile b/examples/docs/methods/code_constructs/object_type/Makefile new file mode 100644 index 00000000..ee407925 --- /dev/null +++ b/examples/docs/methods/code_constructs/object_type/Makefile @@ -0,0 +1,12 @@ +SRC:=object_type_lib.mli object_type_lib.ml object_type_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/object_type/object_type_bin.ml b/examples/docs/methods/code_constructs/object_type/object_type_bin.ml new file mode 100644 index 00000000..83ea1a17 --- /dev/null +++ b/examples/docs/methods/code_constructs/object_type/object_type_bin.ml @@ -0,0 +1,15 @@ +(* object_type_bin.ml *) +type unused_t = < unused_method : unit > + +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let open Object_type_lib in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/object_type/object_type_lib.ml b/examples/docs/methods/code_constructs/object_type/object_type_lib.ml new file mode 100644 index 00000000..8985da89 --- /dev/null +++ b/examples/docs/methods/code_constructs/object_type/object_type_lib.ml @@ -0,0 +1,22 @@ +(* object_type_lib.ml *) +type int_stack = + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > + +let int_stack = + object + val mutable l : int list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/object_type/object_type_lib.mli b/examples/docs/methods/code_constructs/object_type/object_type_lib.mli new file mode 100644 index 00000000..03f65b42 --- /dev/null +++ b/examples/docs/methods/code_constructs/object_type/object_type_lib.mli @@ -0,0 +1,9 @@ +(* object_type_lib.mli *) +type int_stack = + < push : int -> unit + ; pop : unit + ; peek : int option + ; reset : unit + > + +val int_stack : int_stack diff --git a/examples/docs/methods/code_constructs/polymorphic_class/Makefile b/examples/docs/methods/code_constructs/polymorphic_class/Makefile new file mode 100644 index 00000000..8e6af3f1 --- /dev/null +++ b/examples/docs/methods/code_constructs/polymorphic_class/Makefile @@ -0,0 +1,12 @@ +SRC:=polymorphic_class_lib.mli polymorphic_class_lib.ml polymorphic_class_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml new file mode 100644 index 00000000..e0809bff --- /dev/null +++ b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_bin.ml @@ -0,0 +1,13 @@ +(* polymorphic_class_bin.ml *) +let push_n_times n stack = + for i = 1 to n do + stack#push i; + done + +let () = + let int_stack = new Polymorphic_class_lib.stack in + let n = 42 in + push_n_times n int_stack; + while int_stack#peek <> None do + int_stack#pop; + done diff --git a/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.ml b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.ml new file mode 100644 index 00000000..efeaa52d --- /dev/null +++ b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.ml @@ -0,0 +1,15 @@ +(* polymorphic_class_lib.ml *) +class ['a] stack = + object + val mutable l : 'a list = [] + method push x = l <- x::l + method pop = + match l with + | [] -> () + | _::tl -> l <- tl + method peek = + match l with + | [] -> None + | hd::_ -> Some hd + method reset = l <- [] + end diff --git a/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli new file mode 100644 index 00000000..d91c0c48 --- /dev/null +++ b/examples/docs/methods/code_constructs/polymorphic_class/polymorphic_class_lib.mli @@ -0,0 +1,8 @@ +(* polymorphic_class_lib.mli *) +class ['a] stack : + object + method push : 'a -> unit + method pop : unit + method peek : 'a option + method reset : unit + end diff --git a/examples/docs/methods/limitations/Makefile b/examples/docs/methods/limitations/Makefile new file mode 100644 index 00000000..1123cd42 --- /dev/null +++ b/examples/docs/methods/limitations/Makefile @@ -0,0 +1,13 @@ +.PHONY: clean build + +all: build + +build: + make -C alias build + make -C factory_fun_indir build + +clean: + rm -f *~ *.cm* *.o *.obj + make -C alias clean + make -C factory_fun_indir clean + diff --git a/examples/docs/methods/limitations/alias/Makefile b/examples/docs/methods/limitations/alias/Makefile new file mode 100644 index 00000000..d2d83742 --- /dev/null +++ b/examples/docs/methods/limitations/alias/Makefile @@ -0,0 +1,12 @@ +SRC:=alias_lib.mli alias_lib.ml alias_bin.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/limitations/alias/alias_bin.ml b/examples/docs/methods/limitations/alias/alias_bin.ml new file mode 100644 index 00000000..9effa51b --- /dev/null +++ b/examples/docs/methods/limitations/alias/alias_bin.ml @@ -0,0 +1,6 @@ +(* alias_bin.ml *) +open Alias_lib + +let () = + original#used; + alias#used_by_alias diff --git a/examples/docs/methods/limitations/alias/alias_lib.ml b/examples/docs/methods/limitations/alias/alias_lib.ml new file mode 100644 index 00000000..830c0ee8 --- /dev/null +++ b/examples/docs/methods/limitations/alias/alias_lib.ml @@ -0,0 +1,9 @@ +(* alias_lib.ml *) +let original = + object + method used = () + method used_by_alias = () + method unused = () + end + +let alias = original diff --git a/examples/docs/methods/limitations/alias/alias_lib.mli b/examples/docs/methods/limitations/alias/alias_lib.mli new file mode 100644 index 00000000..569ad584 --- /dev/null +++ b/examples/docs/methods/limitations/alias/alias_lib.mli @@ -0,0 +1,12 @@ +(* alias_lib.mli *) +val original : + < used : unit + ; used_by_alias : unit + ; unused : unit + > + +val alias : + < used : unit + ; used_by_alias : unit + ; unused : unit + > diff --git a/examples/docs/methods/limitations/factory_fun_indir/Makefile b/examples/docs/methods/limitations/factory_fun_indir/Makefile new file mode 100644 index 00000000..0b8d6204 --- /dev/null +++ b/examples/docs/methods/limitations/factory_fun_indir/Makefile @@ -0,0 +1,12 @@ +SRC:=factory_fun_indir.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -M all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml b/examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml new file mode 100644 index 00000000..1c1961fa --- /dev/null +++ b/examples/docs/methods/limitations/factory_fun_indir/factory_fun_indir.ml @@ -0,0 +1,13 @@ +(* factoy_fun_indir.ml *) +let factory_with_intermediate_binding () = + let res = + object method unused_method = () end + in + res + +let random_factory () = + if Random.bool () then + object method m = () end + else + let res = object method m = () end in + res