From c206ec23c9d3cf3d1afe0b4beb98e0ba7fa49242 Mon Sep 17 00:00:00 2001 From: Morgante Pell Date: Tue, 6 Aug 2024 16:48:27 -0400 Subject: [PATCH] feat: count all matches in total (#446) --- crates/cli_bin/tests/apply.rs | 6 +++--- crates/cli_bin/tests/snapshots/apply__compact_output.snap | 2 +- .../cli_bin/tests/snapshots/apply__match_only_format.snap | 5 ++--- .../tests/snapshots/apply__multifile_terraform_apply.snap | 5 ++--- crates/cli_bin/tests/snapshots/apply__output_jsonl.snap | 2 +- .../cli_bin/tests/snapshots/apply__terraform_complex.snap | 5 ++--- crates/core/src/api.rs | 6 ++++++ crates/marzano_messenger/src/emit.rs | 5 ++++- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/crates/cli_bin/tests/apply.rs b/crates/cli_bin/tests/apply.rs index f14c345d2..f43a417f8 100644 --- a/crates/cli_bin/tests/apply.rs +++ b/crates/cli_bin/tests/apply.rs @@ -1543,7 +1543,7 @@ fn filtered_apply() -> Result<()> { let stdout = String::from_utf8(output.stdout)?; println!("stdout: {:?}", stdout); - assert!(stdout.contains("2 matches")); + assert!(stdout.contains("3 matches")); let content = fs_err::read_to_string(dir.join("file.js"))?; assert_snapshot!(content); @@ -2077,7 +2077,7 @@ fn overrides_limit() -> Result<()> { "Command didn't finish successfully" ); - assert!(stdout.contains("found 2 matches")); + assert!(stdout.contains("2 files")); Ok(()) } @@ -2276,7 +2276,7 @@ fn applies_on_file_in_hidden_directory() -> Result<()> { ); let stdout = String::from_utf8(output.stdout)?; - assert!(stdout.contains("Processed 1 files and found 1 matches")); + assert!(stdout.contains("1 files")); let content: String = fs_err::read_to_string(dir.join(".circleci").join("config.yml"))?; assert_eq!(content, ""); diff --git a/crates/cli_bin/tests/snapshots/apply__compact_output.snap b/crates/cli_bin/tests/snapshots/apply__compact_output.snap index f51ff38e1..be4c1a001 100644 --- a/crates/cli_bin/tests/snapshots/apply__compact_output.snap +++ b/crates/cli_bin/tests/snapshots/apply__compact_output.snap @@ -15,4 +15,4 @@ expression: sorted_content ./small.ts:13:10 - matched ./small.ts:4:15 - matched ./small.ts:6:17 - matched -Processed 2 files and found 2 matches +Processed 2 files and found 13 matches diff --git a/crates/cli_bin/tests/snapshots/apply__match_only_format.snap b/crates/cli_bin/tests/snapshots/apply__match_only_format.snap index 9a5d3a96d..ab6698fca 100644 --- a/crates/cli_bin/tests/snapshots/apply__match_only_format.snap +++ b/crates/cli_bin/tests/snapshots/apply__match_only_format.snap @@ -1,5 +1,5 @@ --- -source: apps/marzano/cli/tests/apply.rs +source: crates/cli_bin/tests/apply.rs expression: content --- big.ts @@ -71,5 +71,4 @@ expression: content 118  return res.allout; 119 }; -Processed 1 files and found 1 matches - +Processed 1 files and found 10 matches diff --git a/crates/cli_bin/tests/snapshots/apply__multifile_terraform_apply.snap b/crates/cli_bin/tests/snapshots/apply__multifile_terraform_apply.snap index f7d9484af..1acd5dea0 100644 --- a/crates/cli_bin/tests/snapshots/apply__multifile_terraform_apply.snap +++ b/crates/cli_bin/tests/snapshots/apply__multifile_terraform_apply.snap @@ -1,5 +1,5 @@ --- -source: apps/marzano/cli/tests/apply.rs +source: crates/cli_bin/tests/apply.rs expression: "String::from_utf8(output.stdout)?" --- ./main.tf @@ -9,5 +9,4 @@ expression: "String::from_utf8(output.stdout)?" } -Processed 1 files and found 1 matches - +Processed 1 files and found 0 matches diff --git a/crates/cli_bin/tests/snapshots/apply__output_jsonl.snap b/crates/cli_bin/tests/snapshots/apply__output_jsonl.snap index 71d8cd51c..2fad433aa 100644 --- a/crates/cli_bin/tests/snapshots/apply__output_jsonl.snap +++ b/crates/cli_bin/tests/snapshots/apply__output_jsonl.snap @@ -4,4 +4,4 @@ expression: content --- {"__typename":"Match","messages":[],"variables":[{"name":"$new_files","scopedName":"0_0_$new_files","ranges":[]},{"name":"$program","scopedName":"0_1_$program","ranges":[]},{"name":"$filename","scopedName":"0_2_$filename","ranges":[]},{"name":"$absolute_filename","scopedName":"0_3_$absolute_filename","ranges":[]},{"name":"$GLOBAL_REWRITE_INSTRUCTION","scopedName":"0_4_$GLOBAL_REWRITE_INSTRUCTION","ranges":[]},{"name":"$GLOBAL_IMPORTED_SOURCES","scopedName":"0_5_$GLOBAL_IMPORTED_SOURCES","ranges":[]},{"name":"$GLOBAL_IMPORTED_NAMES","scopedName":"0_6_$GLOBAL_IMPORTED_NAMES","ranges":[]},{"name":"$body","scopedName":"2_0_$body","ranges":[]},{"name":"$code_with_markers","scopedName":"2_1_$code_with_markers","ranges":[]},{"name":"$instruct","scopedName":"2_2_$instruct","ranges":[]},{"name":"$messages","scopedName":"2_3_$messages","ranges":[]},{"name":"$pattern","scopedName":"2_4_$pattern","ranges":[]},{"name":"$answer","scopedName":"2_5_$answer","ranges":[]},{"name":"$final","scopedName":"2_6_$final","ranges":[]},{"name":"$body","scopedName":"3_0_$body","ranges":[{"start":{"line":1,"column":1},"end":{"line":14,"column":2},"startByte":0,"endByte":256}]},{"name":"$p","scopedName":"8_0_$p","ranges":[]},{"name":"$all_imports","scopedName":"8_1_$all_imports","ranges":[]},{"name":"$h","scopedName":"8_2_$h","ranges":[]},{"name":"$statements","scopedName":"8_3_$statements","ranges":[]},{"name":"$anchor","scopedName":"8_4_$anchor","ranges":[]},{"name":"$p","scopedName":"9_0_$p","ranges":[]},{"name":"$all_imports","scopedName":"9_1_$all_imports","ranges":[]},{"name":"$our_source","scopedName":"9_2_$our_source","ranges":[]},{"name":"$imported_names","scopedName":"9_3_$imported_names","ranges":[]},{"name":"$joined_imported_names","scopedName":"9_4_$joined_imported_names","ranges":[]},{"name":"$p","scopedName":"10_0_$p","ranges":[]},{"name":"$our_source","scopedName":"10_1_$our_source","ranges":[]},{"name":"$imported_names","scopedName":"10_2_$imported_names","ranges":[]},{"name":"$all_imports","scopedName":"10_3_$all_imports","ranges":[]},{"name":"$name","scopedName":"10_4_$name","ranges":[]},{"name":"$our_source","scopedName":"11_0_$our_source","ranges":[]},{"name":"$joined_imported_names","scopedName":"11_1_$joined_imported_names","ranges":[]},{"name":"$imports","scopedName":"11_2_$imports","ranges":[]},{"name":"$source","scopedName":"11_3_$source","ranges":[]},{"name":"$statement","scopedName":"11_4_$statement","ranges":[]},{"name":"$imports","scopedName":"12_0_$imports","ranges":[]},{"name":"$source","scopedName":"12_1_$source","ranges":[]},{"name":"$match","scopedName":"13_0_$match","ranges":[{"start":{"line":4,"column":15},"end":{"line":9,"column":4},"startByte":81,"endByte":172},{"start":{"line":6,"column":17},"end":{"line":8,"column":6},"startByte":129,"endByte":168},{"start":{"line":13,"column":10},"end":{"line":13,"column":39},"startByte":223,"endByte":252}]}],"sourceFile":"small.ts","content":"// This is a smaller example\nfunction() { \n console.log(\"thing\");\n const foo = () => {\n console.log(\"bar\");\n const bar = () => {\n console.log(\"baz\");\n }\n };\n // Not this\n // Delay a bit\n // Wow\n handle(() => { console.log(\"foo\"); });\n}","ranges":[{"start":{"line":4,"column":15},"end":{"line":9,"column":4},"startByte":81,"endByte":172},{"start":{"line":6,"column":17},"end":{"line":8,"column":6},"startByte":129,"endByte":168},{"start":{"line":13,"column":10},"end":{"line":13,"column":39},"startByte":223,"endByte":252}],"reason":null,"id":"[UUID]"} {"__typename":"Match","messages":[],"variables":[{"name":"$new_files","scopedName":"0_0_$new_files","ranges":[]},{"name":"$program","scopedName":"0_1_$program","ranges":[]},{"name":"$filename","scopedName":"0_2_$filename","ranges":[]},{"name":"$absolute_filename","scopedName":"0_3_$absolute_filename","ranges":[]},{"name":"$GLOBAL_REWRITE_INSTRUCTION","scopedName":"0_4_$GLOBAL_REWRITE_INSTRUCTION","ranges":[]},{"name":"$GLOBAL_IMPORTED_SOURCES","scopedName":"0_5_$GLOBAL_IMPORTED_SOURCES","ranges":[]},{"name":"$GLOBAL_IMPORTED_NAMES","scopedName":"0_6_$GLOBAL_IMPORTED_NAMES","ranges":[]},{"name":"$body","scopedName":"2_0_$body","ranges":[]},{"name":"$code_with_markers","scopedName":"2_1_$code_with_markers","ranges":[]},{"name":"$instruct","scopedName":"2_2_$instruct","ranges":[]},{"name":"$messages","scopedName":"2_3_$messages","ranges":[]},{"name":"$pattern","scopedName":"2_4_$pattern","ranges":[]},{"name":"$answer","scopedName":"2_5_$answer","ranges":[]},{"name":"$final","scopedName":"2_6_$final","ranges":[]},{"name":"$body","scopedName":"3_0_$body","ranges":[{"start":{"line":1,"column":1},"end":{"line":120,"column":1},"startByte":0,"endByte":3269}]},{"name":"$p","scopedName":"8_0_$p","ranges":[]},{"name":"$all_imports","scopedName":"8_1_$all_imports","ranges":[]},{"name":"$h","scopedName":"8_2_$h","ranges":[]},{"name":"$statements","scopedName":"8_3_$statements","ranges":[]},{"name":"$anchor","scopedName":"8_4_$anchor","ranges":[]},{"name":"$p","scopedName":"9_0_$p","ranges":[]},{"name":"$all_imports","scopedName":"9_1_$all_imports","ranges":[]},{"name":"$our_source","scopedName":"9_2_$our_source","ranges":[]},{"name":"$imported_names","scopedName":"9_3_$imported_names","ranges":[]},{"name":"$joined_imported_names","scopedName":"9_4_$joined_imported_names","ranges":[]},{"name":"$p","scopedName":"10_0_$p","ranges":[]},{"name":"$our_source","scopedName":"10_1_$our_source","ranges":[]},{"name":"$imported_names","scopedName":"10_2_$imported_names","ranges":[]},{"name":"$all_imports","scopedName":"10_3_$all_imports","ranges":[]},{"name":"$name","scopedName":"10_4_$name","ranges":[]},{"name":"$our_source","scopedName":"11_0_$our_source","ranges":[]},{"name":"$joined_imported_names","scopedName":"11_1_$joined_imported_names","ranges":[]},{"name":"$imports","scopedName":"11_2_$imports","ranges":[]},{"name":"$source","scopedName":"11_3_$source","ranges":[]},{"name":"$statement","scopedName":"11_4_$statement","ranges":[]},{"name":"$imports","scopedName":"12_0_$imports","ranges":[]},{"name":"$source","scopedName":"12_1_$source","ranges":[]},{"name":"$match","scopedName":"13_0_$match","ranges":[{"start":{"line":14,"column":39},"end":{"line":66,"column":4},"startByte":452,"endByte":1767},{"start":{"line":18,"column":19},"end":{"line":22,"column":6},"startByte":590,"endByte":710},{"start":{"line":24,"column":17},"end":{"line":26,"column":6},"startByte":729,"endByte":775},{"start":{"line":32,"column":26},"end":{"line":35,"column":6},"startByte":858,"endByte":933},{"start":{"line":36,"column":26},"end":{"line":39,"column":6},"startByte":961,"endByte":1036},{"start":{"line":40,"column":20},"end":{"line":51,"column":6},"startByte":1058,"endByte":1323},{"start":{"line":52,"column":20},"end":{"line":65,"column":6},"startByte":1345,"endByte":1761},{"start":{"line":71,"column":71},"end":{"line":71,"column":79},"startByte":1882,"endByte":1890},{"start":{"line":107,"column":25},"end":{"line":119,"column":2},"startByte":2904,"endByte":3267},{"start":{"line":109,"column":71},"end":{"line":109,"column":79},"startByte":2997,"endByte":3005}]}],"sourceFile":"big.ts","content":"import type { ChildProcessWithoutNullStreams } from 'child_process';\nimport { spawn } from 'child_process';\nimport type { stdlib } from '@getgrit/api';\n\nexport function wrap_exec({\n callback,\n cp,\n passOnNonZeroExitCode,\n}: {\n callback?: (write: (str: string) => void, end: () => void) => void;\n cp: ChildProcessWithoutNullStreams;\n passOnNonZeroExitCode: boolean | undefined;\n}): Promise {\n return new Promise((resolve) => {\n const allout = [] as string[];\n const stdout = [] as string[];\n const stderr = [] as string[];\n const write = (str: string): void => {\n process.stdin.cork();\n process.stdin.write(str);\n process.stdin.uncork();\n };\n\n const end = (): void => {\n process.stdin.end();\n };\n\n if (callback) {\n callback(write, end);\n }\n\n cp.stdout.on('data', (data: string) => {\n stdout.push(data);\n allout.push(data);\n });\n cp.stderr.on('data', (data: string) => {\n stderr.push(data);\n allout.push(data);\n });\n cp.on('error', (e) => {\n resolve({\n __typename: 'ShResult',\n kind: 'direct',\n success: false,\n code: -1,\n allout: allout.join(''),\n stdout: stdout.join(''),\n stderr: stderr.join(''),\n message: e.message,\n });\n });\n cp.on('close', (code: number) => {\n // Trailing info is more valuable than truncated.\n const message = stderr.join('').slice(-2000);\n resolve({\n __typename: 'ShResult',\n kind: 'direct',\n success: passOnNonZeroExitCode ? true : code === 0,\n code: code || 0,\n allout: allout.join(''),\n stdout: stdout.join(''),\n stderr: stderr.join(''),\n message,\n });\n });\n });\n}\n\nexport function baseSh(\n cmd: string,\n callback: (write: (str: string) => void, end: () => void) => void = () => {},\n cwd: string | URL | undefined = undefined,\n passOnNonZeroExitCode: boolean | undefined = undefined,\n env: NodeJS.ProcessEnv | undefined = undefined,\n detached?: boolean,\n): Promise {\n const cp = spawn(cmd, { shell: true, detached, cwd, env: { ...process.env, ...(env ?? {}) } });\n const interruptCP = function () {\n cp.emit('SIGINT');\n };\n\n try {\n const promise = wrap_exec({ callback, cp, passOnNonZeroExitCode });\n if (!detached) {\n return promise;\n }\n } finally {\n process.removeListener('SIGINT', interruptCP);\n }\n return Promise.resolve({\n __typename: 'ShResult',\n kind: 'detached',\n allout: 'Result is detached',\n stderr: '',\n stdout: 'Result is detached',\n code: 0,\n success: true,\n });\n}\n/**\n * The most basic sh. Sends output to console if anything goes wrong, that is, if status code != 0\n * @param cmd the command to run\n * @param callback the callback to run\n * @returns All output from the command.\n */\n\nexport const simpleSh = async (\n cmd: string,\n callback: (write: (str: string) => void, end: () => void) => void = () => {},\n cwd: string | URL | undefined = undefined,\n): Promise => {\n const res = await baseSh(cmd, callback, cwd);\n if (res.code !== 0) {\n console.log(res.stdout);\n console.error(res.stderr);\n throw new Error(res.stderr);\n }\n return res.allout;\n};\n","ranges":[{"start":{"line":14,"column":39},"end":{"line":66,"column":4},"startByte":452,"endByte":1767},{"start":{"line":18,"column":19},"end":{"line":22,"column":6},"startByte":590,"endByte":710},{"start":{"line":24,"column":17},"end":{"line":26,"column":6},"startByte":729,"endByte":775},{"start":{"line":32,"column":26},"end":{"line":35,"column":6},"startByte":858,"endByte":933},{"start":{"line":36,"column":26},"end":{"line":39,"column":6},"startByte":961,"endByte":1036},{"start":{"line":40,"column":20},"end":{"line":51,"column":6},"startByte":1058,"endByte":1323},{"start":{"line":52,"column":20},"end":{"line":65,"column":6},"startByte":1345,"endByte":1761},{"start":{"line":71,"column":71},"end":{"line":71,"column":79},"startByte":1882,"endByte":1890},{"start":{"line":107,"column":25},"end":{"line":119,"column":2},"startByte":2904,"endByte":3267},{"start":{"line":109,"column":71},"end":{"line":109,"column":79},"startByte":2997,"endByte":3005}],"reason":null,"id":"[UUID]"} -{"__typename":"AllDone","processed":2,"found":2,"reason":"allMatchesFound"} +{"__typename":"AllDone","processed":2,"found":13,"reason":"allMatchesFound"} diff --git a/crates/cli_bin/tests/snapshots/apply__terraform_complex.snap b/crates/cli_bin/tests/snapshots/apply__terraform_complex.snap index 06cc046f5..9728d7848 100644 --- a/crates/cli_bin/tests/snapshots/apply__terraform_complex.snap +++ b/crates/cli_bin/tests/snapshots/apply__terraform_complex.snap @@ -1,5 +1,5 @@ --- -source: apps/marzano/cli/tests/apply.rs +source: crates/cli_bin/tests/apply.rs expression: "String::from_utf8(output.stdout)?" --- Log in PlaygroundPattern: Warning: sequential matches at the top of the file. If a pattern matched outside of a sequential, but no longer matches, it is likely because naked patterns are automatically wrapped with `contains bubble ` @@ -90,5 +90,4 @@ Log in PlaygroundPattern: Warning: sequential matches at the top of the file. If module "test_module3" { -Processed 4 files and found 4 matches - +Processed 4 files and found 0 matches diff --git a/crates/core/src/api.rs b/crates/core/src/api.rs index ff4866df3..7cab7b2c0 100644 --- a/crates/core/src/api.rs +++ b/crates/core/src/api.rs @@ -214,6 +214,10 @@ impl MatchResult { } } + pub fn get_ranges(&self) -> Option<&Vec> { + fs::extract_ranges(self) + } + /// Given a MatchResult, create a MatchResult::Rewrite that suppresses the match. /// Returns None if it has any issues. pub fn get_rewrite_to_suppress<'a>( @@ -698,7 +702,9 @@ pub struct Message { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[serde(rename_all = "camelCase")] pub struct AllDone { + /// How many files have been processed pub processed: i32, + /// How many matches were found pub found: i32, pub reason: AllDoneReason, } diff --git a/crates/marzano_messenger/src/emit.rs b/crates/marzano_messenger/src/emit.rs index edb564ad8..21d847ff6 100644 --- a/crates/marzano_messenger/src/emit.rs +++ b/crates/marzano_messenger/src/emit.rs @@ -20,6 +20,7 @@ use crate::{format::format_result, workflows::PackagedWorkflowOutcome, SimpleLog #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] pub struct ApplyDetails { + /// How many matches were found total (total match range count) pub matched: i32, pub rewritten: i32, pub named_pattern: Option, @@ -110,7 +111,9 @@ pub trait Messager: Send + Sync { ) -> anyhow::Result { for r in execution_result { if is_match(&r) { - details.matched += 1; + if let Some(ranges) = r.get_ranges() { + details.matched += ranges.len() as i32; + } } if let MatchResult::Rewrite(_) = r { details.rewritten += 1;