Find and remove dead code and unused APIs in OCaml projects
at main 193 lines 6.3 kB view raw
1(** Core types and utilities for prune *) 2 3(** {2 Location information} *) 4 5type location = private { 6 file : string; 7 start_line : int; 8 start_col : int; 9 end_line : int; 10 end_col : int; 11} 12 13val extend : 14 ?start_line:int -> end_line:int -> ?end_col:int -> location -> location 15(** [extend ?start_line ~end_line ?end_col location] extends a location's 16 boundaries. *) 17 18val merge : location -> location -> location 19(** [merge loc1 loc2] merges two locations into one encompassing both. *) 20 21val location : 22 line:int -> 23 ?end_line:int -> 24 start_col:int -> 25 end_col:int -> 26 string -> 27 location 28(** [location ~line ?end_line ~start_col ~end_col file] creates a location for a 29 single line. *) 30 31val pp_location : Format.formatter -> location -> unit 32(** [pp_location fmt location] pretty-prints a location. *) 33 34(** {2 Symbol information} *) 35 36type symbol_kind = 37 | Value (** Functions, variables, etc. *) 38 | Type (** Type declarations *) 39 | Module (** Module declarations *) 40 | Constructor (** Variant constructors *) 41 | Field (** Record fields *) 42 43val string_of_symbol_kind : symbol_kind -> string 44(** [string_of_symbol_kind kind] converts symbol kind to lowercase string for 45 user-facing display. *) 46 47type symbol_info = { name : string; kind : symbol_kind; location : location } 48 49(** {2 Occurrence information} *) 50 51type usage_classification = 52 | Unused 53 | Used_only_in_excluded (** Used only in excluded directories *) 54 | Used (** Used in at least one non-excluded location *) 55 | Unknown 56 (** Cannot determine usage via occurrences (e.g., modules, exceptions) *) 57 58val pp_usage_classification : Format.formatter -> usage_classification -> unit 59(** [pp_usage_classification fmt classification] pretty-prints a usage 60 classification. *) 61 62type occurrence_info = { 63 symbol : symbol_info; 64 occurrences : int; 65 locations : location list; 66 usage_class : usage_classification; 67} 68 69(** {2 Statistics} *) 70 71type stats = { 72 mli_exports_removed : int; 73 ml_implementations_removed : int; 74 iterations : int; 75 lines_removed : int; 76} 77(** Statistics about a prune run *) 78 79val empty_stats : stats 80(** [empty_stats] is an empty statistics record. *) 81 82val pp_stats : Format.formatter -> stats -> unit 83(** [pp_stats fmt stats] pretty-prints statistics. *) 84 85(** {2 Warning information} *) 86 87type warning_type = 88 | Unused_value (** Warning 32: unused value declaration *) 89 | Unused_type (** Warning 34: unused type declaration *) 90 | Unused_open (** Warning 33: unused open statement *) 91 | Unused_constructor (** Warning 37: unused constructor *) 92 | Unused_exception (** Warning 38: unused exception declaration *) 93 | Unused_field (** Warning 69: unused record field definition *) 94 | Unnecessary_mutable 95 (** Warning 69: mutable record field that is never mutated *) 96 | Signature_mismatch (** Compiler error: value required but not provided *) 97 | Unbound_field (** Compiler error: unbound record field *) 98 99val pp_warning_type : Format.formatter -> warning_type -> unit 100(** [pp_warning_type fmt warning_type] pretty-prints a warning type. *) 101 102(** Precision of location information from compiler warnings/errors *) 103type location_precision = 104 | Exact_definition 105 (** Location covers the full definition that should be removed. Doc 106 comments should be removed as they document the definition. *) 107 | Exact_statement 108 (** Location covers a full statement (like open) that should be removed. 109 No doc comments to remove as statements don't have doc comments. *) 110 | Needs_enclosing_definition 111 (** Location is just an identifier, needs merlin enclosing to find full 112 definition. Doc comments should be removed after finding enclosing. *) 113 | Needs_field_usage_parsing 114 (** Location is field name in record construction, needs special parsing. 115 No doc comments removal as we're removing usage, not definition. *) 116 117val precision_of_warning_type : warning_type -> location_precision 118(** [precision_of_warning_type warning_type] gets the location precision for a 119 given warning type. *) 120 121val symbol_kind_of_warning : warning_type -> symbol_kind 122(** [symbol_kind_of_warning warning_type] converts warning type to symbol kind. 123*) 124 125type warning_info = { 126 location : location; 127 name : string; 128 warning_type : warning_type; 129 location_precision : location_precision; 130} 131 132val pp_warning_info : Format.formatter -> warning_info -> unit 133(** [pp_warning_info fmt warning_info] pretty-prints a warning info. *) 134 135(** {2 Build tracking} *) 136 137type build_result = { 138 success : bool; 139 output : string; 140 exit_code : int; 141 warnings : warning_info list; (* Parsed warnings from build output *) 142} 143(** Result of a build operation *) 144 145type context 146(** Context for tracking build state across operations *) 147 148val empty_context : context 149(** [empty_context] is an empty context with no build result. *) 150 151(** {2 Error handling} *) 152 153type error = [ `Msg of string | `Build_error of context ] 154 155val pp_error : Format.formatter -> error -> unit 156(** [pp_error fmt error] pretty-prints an error. *) 157 158val update_build_result : context -> build_result -> context 159(** [update_build_result ctx result] updates context with a new build result. *) 160 161val last_build_result : context -> build_result option 162(** [last_build_result ctx] gets the last build result from context. *) 163 164(** Build error classification *) 165type build_error_type = 166 | No_error (** Build succeeded *) 167 | Fixable_errors of warning_info list 168 (** Errors that prune might be able to fix *) 169 | Other_errors of string (** Any other build errors - show full output *) 170 171(** {2 Merlin response types} *) 172 173type outline_item = { 174 kind : symbol_kind; 175 name : string; 176 location : location; 177 children : outline_item list option; 178} 179(** Outline item from merlin *) 180 181type outline_response = outline_item list 182(** Merlin response types *) 183 184type occurrences_response = location list 185 186val outline_response_of_json : 187 file:string -> Jsont.json -> (outline_response, error) result 188(** [outline_response_of_json ~file json] parses JSON response into outline. *) 189 190val occurrences_response_of_json : 191 root_dir:string -> Jsont.json -> (occurrences_response, error) result 192(** [occurrences_response_of_json ~root_dir json] parses JSON response into 193 occurrences. *)