package comby
A tool for structural code search and replace that supports ~every language
Install
Dune Dependency
Authors
Maintainers
Sources
comby-kernel.1.7.0.tar.gz
md5=ee6556d8bd9b25ed0445ebe23862e48a
sha512=e6386c8ce5ef14bbcab2b0ead5b1edc39375438f56330d5f02e81e467afe6623a7e299f97f26008d77bbc62850c6dc63a7cbe5b81671b5183ff3adeee5946bb3
doc/src/comby.pipeline/pipeline.ml.html
Source file pipeline.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
open Core open Comby_kernel open Configuration open Command_configuration open Command_input open Statistics open Matchers let verbose_out_file = "/tmp/comby.out" let debug = Sys.getenv "DEBUG_COMBY" |> Option.is_some let timed_run (module Matcher : Matcher.S) ?(fast_offset_conversion = false) ?filepath ~configuration ~source ~specification:(Specification.{ match_template = template; rule; rewrite_template }) () = (match rewrite_template with | Some template -> Matcher.set_rewrite_template template; | None -> ()); Matcher.all ~configuration ?filepath ?rule ~template ~source () |> List.map ~f:(Match.convert_offset ~fast:fast_offset_conversion ~source) type output = | Matches of (Match.t list * int) | Replacement of (Replacement.t list * string * int) | Nothing let with_timeout timeout source ~f = try Statistics.Time.time_out ~after:timeout f (); with Statistics.Time.Time_out -> Format.eprintf "Timeout for input: %s!@." (show_input_kind source); Out_channel.with_file ~append:true verbose_out_file ~f:(fun out_channel -> Out_channel.output_lines out_channel [Format.sprintf "TIMEOUT: %s@." (show_input_kind source) ]); [] let log_to_file path = Out_channel.with_file ~append:true verbose_out_file ~f:(fun out_channel -> Out_channel.output_lines out_channel [Format.sprintf "Processing %s%!" path]) let process_single_source matcher ?(fast_offset_conversion = false) ?(verbose = false) ?(timeout = 3) ?metasyntax ?fresh ?(substitute_in_place = true) configuration source (Specification.{ rewrite_template; _ } as specification) = try let filepath, input_text = match source with | String input_text -> None, input_text | Path path -> if verbose then log_to_file path; Some path, In_channel.read_all path in let matches = with_timeout timeout source ~f:(fun () -> timed_run matcher ~fast_offset_conversion ~configuration ~specification ?filepath ~source:input_text ()) in match rewrite_template with | None -> Matches (matches, List.length matches) | Some rewrite_template -> match matches with | [] -> (* If there are no matches, return the original source (for editor support) if substitute_in_place is active. *) if substitute_in_place then Replacement ([], input_text, 0) else Nothing | matches -> (* FIXME this should be configured where it's done in command_configuration.ml *) let external_handler = External_semantic.lsif_hover in let source = if substitute_in_place then Some input_text else None in match Rewrite.all ?source ?metasyntax ?fresh ?filepath ~external_handler ~rewrite_template matches with | None -> Nothing | Some { rewritten_source; in_place_substitutions } -> Replacement (in_place_substitutions, rewritten_source, List.length matches) with | exn -> if debug then Format.eprintf "Big error: %s@." (Exn.to_string exn); Nothing let output_result output_printer source_path source_content result = match result with | Nothing -> () | Matches (matches, _) -> output_printer (Printer.Matches { source_path; matches }) | Replacement (replacements, result, _) -> let source_content = match source_content with | String content -> content | Path path -> In_channel.read_all path in output_printer (Printer.Replacements { source_path; replacements; result; source_content }) type run_mode = | Interactive | Command_line of { output_printer : Printer.t ; output_path : string option } let run_on_specifications mode specifications process (input : single_source) = let result = List.fold specifications ~init:Nothing ~f:(fun result specification -> let input = match result with | Nothing | Matches _ -> input | Replacement (_, content, _) -> String content in match result, process input specification with | any, Nothing | Nothing, any -> any | Matches (l, n), Matches (l', n') -> Matches (l@l', n+n') | Replacement (l, _, n), Replacement (l', content, n') -> Replacement (l@l', content, n+n') | Matches _, Replacement (l, content, n) | Replacement (l, content, n), Matches _ -> Format.eprintf "WARNING: input configuration specifies both rewrite \ and match templates. I am choosing to only process the \ configurations with both a 'match' and 'rewrite' part. \ If you only want to see matches, add -match-only to \ suppress this warning@."; Replacement (l, content, n) ) in let count = match result with | Nothing -> 0 | Matches (_, n) | Replacement (_, _, n) -> n in match mode with | Command_line { output_printer; output_path } -> output_result output_printer output_path input result; None, count | Interactive -> match result with | Replacement (_, content, _) -> Some content, count | _ -> None, 0 let write_statistics number_of_matches sources start_time = let total_time = Statistics.Time.stop start_time in let lines_of_code, number_of_files = match sources with | `String source -> List.length (String.split_lines source), 1 | `Paths paths -> let lines_of_code = Fold.loc_paths paths in lines_of_code, List.length paths | `Zip (zip_file, paths) -> let lines_of_code = Fold.loc_zip zip_file paths in lines_of_code, List.length paths | _ -> failwith "No single path handled here" in let statistics = { number_of_files ; lines_of_code ; number_of_matches ; total_time = total_time } in Format.eprintf "%s@." @@ Yojson.Safe.pretty_to_string @@ Statistics.to_yojson statistics let run_batch ~f:per_unit sources compute_mode bound_count = match compute_mode with | `Sequential -> Sequential.process ~f:per_unit bound_count sources | `Parany number_of_workers -> Parallel_parany.process ~f:per_unit number_of_workers bound_count sources | `Hack_parallel number_of_workers -> Parallel_hack.process ~f:per_unit number_of_workers bound_count sources let run_interactive specifications matcher fast_offset_conversion match_configuration substitute_in_place verbose timeout sources compute_mode interactive_review = let with_rewrites ~input ~path:_ = run_on_specifications Interactive specifications (fun (input : single_source) specification -> process_single_source matcher ~fast_offset_conversion ~verbose ~timeout ~substitute_in_place match_configuration input specification) input in let paths = match sources with | `Paths paths -> paths | _ -> failwith "Cannot run interactive mode with this input source, must be file paths." in let rewrites, count = match compute_mode with | `Sequential -> Sequential.process_interactive ~f:with_rewrites paths | `Parany number_of_workers -> Parallel_parany.process_interactive ~f:with_rewrites paths number_of_workers | `Hack_parallel number_of_workers -> Parallel_hack.process_interactive ~f:with_rewrites paths number_of_workers in let { editor; default_is_accept } = interactive_review in Interactive.run editor default_is_accept count rewrites; count let run { matcher ; sources ; specifications ; substitute_in_place ; run_options = { verbose ; match_timeout = timeout ; dump_statistics ; disable_substring_matching ; fast_offset_conversion ; match_newline_toplevel ; bound_count ; compute_mode } ; output_printer ; interactive_review ; metasyntax } = let fresh = match compute_mode with | `Sequential -> None | _ -> Some (fun () -> Uuid_unix.(Fn.compose Uuid.to_string create ())) in let match_configuration = Matchers.Configuration.create ~disable_substring_matching ~match_kind:Fuzzy ~match_newline_toplevel ~substitute_in_place ?fresh () in let start_time = Statistics.Time.start () in let per_unit ~(input : single_source) ~output_path = run_on_specifications (Command_line { output_printer; output_path }) specifications (fun input specification -> process_single_source matcher ~fast_offset_conversion ~verbose ~timeout ?metasyntax ?fresh ~substitute_in_place match_configuration input specification) input |> snd (* only count result for Command_line *) in let count = match interactive_review with | None -> begin match sources with | `String source -> per_unit ~input:(String source) ~output_path:None | #batch_input as sources -> run_batch ~f:per_unit sources compute_mode bound_count end | Some interactive_review -> run_interactive specifications matcher fast_offset_conversion match_configuration substitute_in_place verbose timeout sources compute_mode interactive_review in if dump_statistics then write_statistics count sources start_time let execute matcher ?timeout ?metasyntax ?fresh ?(configuration = Matchers.Configuration.create ()) ?substitute_in_place source specification = process_single_source matcher ~fast_offset_conversion:false ~verbose:false ?timeout ?metasyntax ?fresh ?substitute_in_place configuration source specification
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>