diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2814b2f4..174ffe24 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,7 @@ env: CARGO_TERM_COLOR: always jobs: - build-and-test: + lib-build-and-test: name: Build & Test runs-on: ${{ matrix.os }} timeout-minutes: 30 @@ -56,10 +56,66 @@ jobs: run: cargo build --verbose - name: Run tests run: cargo test --verbose + + - name: Build release binary for extension tests (macOS ARM64 only) + if: matrix.target == 'aarch64-apple-darwin' + run: cargo build --release --target ${{ matrix.target }} + + - name: Upload release binary for extension tests (macOS ARM64 only) + if: matrix.target == 'aarch64-apple-darwin' + uses: actions/upload-artifact@v4 + with: + name: log2src-test-binary + path: target/${{ matrix.target }}/release/${{ matrix.artifact_name }} + if-no-files-found: error + + vscode-extension-test: + name: Test VS Code Extension + needs: [lib-build-and-test] + # Disabled: @vscode/test-electron can't launch the current VS Code release on macOS. + if: false + runs-on: macos-latest + timeout-minutes: 15 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download log2src binary + uses: actions/download-artifact@v4 + with: + name: log2src-test-binary + path: downloaded-binary + + - name: Setup binary for VS Code extension + run: | + mkdir -p editors/code/bin/darwin-arm64 + cp downloaded-binary/log2src editors/code/bin/darwin-arm64/ + chmod +x editors/code/bin/darwin-arm64/log2src + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.8.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'pnpm' + cache-dependency-path: 'editors/code/pnpm-lock.yaml' + + - name: Install Dependencies + working-directory: editors/code + run: pnpm install + + - name: Run tests + working-directory: editors/code + run: pnpm run test build-release: name: Build Release - needs: [build-and-test] + needs: [lib-build-and-test] if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') runs-on: ${{ matrix.os }} timeout-minutes: 30 diff --git a/editors/code/package.json b/editors/code/package.json index 482efe88..497f6aa5 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -3,6 +3,7 @@ "displayName": "log2src", "description": "A debugger driven by logs", "version": "0.0.1", + "publisher": "ttiimm", "author": { "name": "Tim Likarish Ellis" }, diff --git a/editors/code/src/debugAdapter.ts b/editors/code/src/debugAdapter.ts index 4434ebd2..96f68abc 100644 --- a/editors/code/src/debugAdapter.ts +++ b/editors/code/src/debugAdapter.ts @@ -41,6 +41,7 @@ interface SourceRef { lineNumber: number, column: number, name: string, + level: string, } interface ILaunchRequestArguments extends DebugProtocol.LaunchRequestArguments { diff --git a/editors/code/src/test/suite/debugAdapter.test.ts b/editors/code/src/test/suite/debugAdapter.test.ts new file mode 100644 index 00000000..9698b0e4 --- /dev/null +++ b/editors/code/src/test/suite/debugAdapter.test.ts @@ -0,0 +1,265 @@ +import * as assert from 'assert'; +import { DebugProtocol } from '@vscode/debugprotocol'; + +import { DebugSession, BinaryNotFoundError } from '../../debugAdapter'; + + +suite('DebugAdapter Test Suite', () => { + let debugSession: DebugSession | undefined; + let originalPlatform: string; + let originalArch: string; + + setup(() => { + originalPlatform = process.platform; + originalArch = process.arch; + }); + + teardown(() => { + Object.defineProperty(process, 'platform', { + value: originalPlatform, + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: originalArch, + configurable: true + }); + + if (debugSession) { + try { + (debugSession as any).dispose?.(); + } catch (e) { + // Ignore + } + debugSession = undefined; + } + }); + + suite('Constructor Tests', () => { + test('Should create debug session with correct binary path for darwin-arm64', () => { + Object.defineProperty(process, 'platform', { + value: 'darwin', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'arm64', + configurable: true + }); + + debugSession = new DebugSession(); + + assert.ok(debugSession, 'Debug session should be created'); + }); + + test('Should create debug session with correct binary path for linux-x64', () => { + Object.defineProperty(process, 'platform', { + value: 'linux', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'x64', + configurable: true + }); + + debugSession = new DebugSession(); + + assert.ok(debugSession, 'Debug session should be created'); + }); + + test('Should create debug session with correct binary path for win32-x64', () => { + Object.defineProperty(process, 'platform', { + value: 'win32', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'x64', + configurable: true + }); + + debugSession = new DebugSession(); + + assert.ok(debugSession, 'Debug session should be created'); + }); + + test('Should throw BinaryNotFoundError for unsupported platform', () => { + Object.defineProperty(process, 'platform', { + value: 'unsupported', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'unsupported', + configurable: true + }); + + assert.throws(() => { + new DebugSession(); + }, BinaryNotFoundError, 'Should throw BinaryNotFoundError for unsupported platform'); + }); + }); + + suite('Initialize Request Tests', () => { + setup(() => { + Object.defineProperty(process, 'platform', { + value: 'darwin', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'arm64', + configurable: true + }); + debugSession = new DebugSession(); + }); + + test('Should handle initialize request correctly', () => { + const args: DebugProtocol.InitializeRequestArguments = { + clientID: 'test-client', + clientName: 'Test Client', + adapterID: 'log2src', + pathFormat: 'path' + }; + + const response: DebugProtocol.InitializeResponse = { + request_seq: 1, + success: true, + command: 'initialize', + seq: 1, + type: 'response', + body: {} + }; + + let capturedResponse: DebugProtocol.InitializeResponse | undefined; + const originalSendResponse = (debugSession as any).sendResponse.bind(debugSession); + (debugSession as any).sendResponse = (resp: any) => { + capturedResponse = resp; + }; + + let eventSent = false; + const originalSendEvent = (debugSession as any).sendEvent.bind(debugSession); + (debugSession as any).sendEvent = () => { + eventSent = true; + }; + + try { + (debugSession as any).initializeRequest(response, args); + + assert.ok(capturedResponse, 'Response should be sent'); + assert.ok(eventSent, 'Event should be sent'); + + assert.ok(capturedResponse!.body, 'Response should have body'); + assert.strictEqual(capturedResponse!.body.supportsStepBack, true); + assert.strictEqual(capturedResponse!.body.supportTerminateDebuggee, true); + } finally { + (debugSession as any).sendResponse = originalSendResponse; + (debugSession as any).sendEvent = originalSendEvent; + } + }); + }); + + suite('Breakpoint Tests', () => { + setup(() => { + Object.defineProperty(process, 'platform', { + value: 'darwin', + configurable: true + }); + Object.defineProperty(process, 'arch', { + value: 'arm64', + configurable: true + }); + debugSession = new DebugSession(); + }); + + test('Should set breakpoints correctly', () => { + const sourcePath = '/test/source/file.log'; + const args: DebugProtocol.SetBreakpointsArguments = { + source: { path: sourcePath }, + breakpoints: [ + { line: 10 }, + { line: 20 }, + { line: 30 } + ] + }; + + const response: DebugProtocol.SetBreakpointsResponse = { + request_seq: 1, + success: true, + command: 'setBreakpoints', + seq: 1, + type: 'response', + body: { breakpoints: [] } + }; + + let capturedResponse: DebugProtocol.SetBreakpointsResponse | undefined; + const originalSendResponse = (debugSession as any).sendResponse.bind(debugSession); + (debugSession as any).sendResponse = (resp: any) => { + capturedResponse = resp; + }; + + let eventSent = false; + const originalSendEvent = (debugSession as any).sendEvent.bind(debugSession); + (debugSession as any).sendEvent = () => { + eventSent = true; + }; + + try { + (debugSession as any).setBreakPointsRequest(response, args); + + assert.ok(capturedResponse, 'Response should be sent'); + + assert.ok(capturedResponse!.body, 'Response should have body'); + assert.ok(capturedResponse!.body.breakpoints, 'Response should have breakpoints'); + assert.strictEqual(capturedResponse!.body.breakpoints.length, 3, 'Should have 3 breakpoints'); + + capturedResponse!.body.breakpoints.forEach((bp, index) => { + assert.strictEqual(bp.line, args.breakpoints![index].line, `Breakpoint ${index} should have correct line`); + }); + + assert.ok(eventSent, 'Should send stopped event'); + } finally { + (debugSession as any).sendResponse = originalSendResponse; + (debugSession as any).sendEvent = originalSendEvent; + } + }); + + test('Should handle empty breakpoints array', () => { + const sourcePath = '/test/source/file.log'; + const args: DebugProtocol.SetBreakpointsArguments = { + source: { path: sourcePath }, + breakpoints: [] + }; + + const response: DebugProtocol.SetBreakpointsResponse = { + request_seq: 1, + success: true, + command: 'setBreakpoints', + seq: 1, + type: 'response', + body: { breakpoints: [] } + }; + + let capturedResponse: DebugProtocol.SetBreakpointsResponse | undefined; + let eventSent = false; + + const originalSendResponse = (debugSession as any).sendResponse.bind(debugSession); + (debugSession as any).sendResponse = (resp: any) => { + capturedResponse = resp; + }; + + const originalSendEvent = (debugSession as any).sendEvent.bind(debugSession); + (debugSession as any).sendEvent = () => { + eventSent = true; + }; + + try { + (debugSession as any).setBreakPointsRequest(response, args); + + assert.ok(capturedResponse, 'Response should be sent'); + assert.ok(capturedResponse!.body, 'Response should have body'); + assert.ok(capturedResponse!.body.breakpoints, 'Response should have breakpoints array'); + assert.strictEqual(capturedResponse!.body.breakpoints.length, 0, 'Should have no breakpoints'); + assert.strictEqual(eventSent, false, 'Should not send stopped event for empty breakpoints'); + } finally { + (debugSession as any).sendResponse = originalSendResponse; + (debugSession as any).sendEvent = originalSendEvent; + } + }); + }); +}); \ No newline at end of file diff --git a/editors/code/src/test/suite/extension.test.ts b/editors/code/src/test/suite/extension.test.ts index b13f0a93..f789d580 100644 --- a/editors/code/src/test/suite/extension.test.ts +++ b/editors/code/src/test/suite/extension.test.ts @@ -5,8 +5,23 @@ import * as vscode from 'vscode'; suite('Extension Test Suite', () => { vscode.window.showInformationMessage('Start all tests.'); - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); + test('Extension should be present', () => { + assert.ok(vscode.extensions.getExtension('ttiimm.log2src-ext')); + }); + + test('Extension should activate', async () => { + const ext = vscode.extensions.getExtension('ttiimm.log2src-ext'); + assert.ok(ext); + await ext!.activate(); + assert.strictEqual(ext!.isActive, true); + }); + + test('Should register log2src debug type', async () => { + // Ensure extension is activated + const ext = vscode.extensions.getExtension('ttiimm.log2src-ext'); + await ext?.activate(); + + // Verify the extension activated successfully + assert.ok(ext?.isActive, 'Extension should be active'); }); }); diff --git a/src/java_symbols.rs b/src/java_symbols.rs index 9fa5d083..96742e75 100644 --- a/src/java_symbols.rs +++ b/src/java_symbols.rs @@ -13,6 +13,7 @@ //! constants it defines and, for each log call, the fully-qualified names the constant might //! have. After all the files are extracted, the references are resolved across the whole tree. +use crate::source_ref::LogLevel; use crate::source_query::SourceQuery; use crate::value_kind::ValueKind; use serde::{Deserialize, Serialize}; @@ -43,6 +44,7 @@ pub(crate) struct MessageRef { pub block_id: u32, /// The reference as written in the source, like `Messages.LOG_STARTING`. pub text: String, + pub level: LogLevel, pub vars: Vec, /// The kind of value produced by each expression in `vars`. pub var_kinds: Vec, diff --git a/src/lib.rs b/src/lib.rs index f9864caf..890ebf57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub use progress::ProgressUpdate; pub use progress::WorkInfo; use source_query::QueryResult; pub use source_query::SourceQuery; -pub use source_ref::SourceRef; +pub use source_ref::{LogLevel, SourceRef}; #[derive(Error, Debug, Diagnostic, Clone, Default)] pub enum LogError { @@ -147,7 +147,7 @@ pub enum CacheEntrySchema { /// The revision value is a simple way to invalidate the cache entries by changing the number. #[derive(Serialize, Deserialize, Debug)] pub enum Revision { - #[serde(rename = "25")] + #[serde(rename = "26")] Current, } @@ -317,7 +317,7 @@ impl SourceTree { .filter_map(|(file_id, index)| { self.files_with_statements.get(file_id)?.statement(*index) }) - .sorted_by(|lhs, rhs| compare_candidates(lhs, rhs, Some(lineno))); + .sorted_by(|lhs, rhs| compare_candidates(lhs, rhs, Some(lineno), log_ref.level())); first_match(candidates, body, Some(lineno), |src_ref| src_ref) } @@ -350,7 +350,8 @@ impl SourceTree { } }); let lineno = log_ref.details.as_ref().and_then(|details| details.lineno); - candidates.sort_by(|lhs, rhs| compare_candidates(lhs.1, rhs.1, lineno)); + let level = log_ref.level(); + candidates.sort_by(|lhs, rhs| compare_candidates(lhs.1, rhs.1, lineno, level)); let (stmt_id, src_ref) = first_match(candidates, body, lineno, |(_, src_ref)| src_ref)?; if let Some((filename, lineno)) = self.line_cache_key(log_ref) { let mut cache = self @@ -414,15 +415,23 @@ fn line_distance(src_ref: &SourceRef, lineno: Option) -> usize { } /// Order the candidate statements for a log message from best to worst. Higher quality is -/// better and, for the same quality, a statement closer to the line number in the log message. -/// The line number is only a tie-breaker since it is not always the line of the log call, like -/// for a message built in a lambda. Then, a statement with fewer placeholders is better. Any -/// remaining tie goes to the earliest location in the source so that the choice does not depend -/// on the order the candidates were found in. -fn compare_candidates(lhs: &SourceRef, rhs: &SourceRef, lineno: Option) -> Ordering { +/// better and, for the same quality, a statement with the same level as the log message, and +/// then one closer to the line number in the log message. The line number is only a +/// tie-breaker since it is not always the line of the log call, like for a message built in a +/// lambda. Then, a statement with fewer placeholders is better. Any remaining tie goes to the +/// earliest location in the source so that the choice does not depend on the order the +/// candidates were found in. +fn compare_candidates( + lhs: &SourceRef, + rhs: &SourceRef, + lineno: Option, + level: Option, +) -> Ordering { let distance = |src_ref: &SourceRef| line_distance(src_ref, lineno); + let level_matches = |src_ref: &SourceRef| level == Some(src_ref.level); rhs.quality .cmp(&lhs.quality) + .then_with(|| level_matches(rhs).cmp(&level_matches(lhs))) .then_with(|| distance(lhs).cmp(&distance(rhs))) // A placeholder can be empty, so a message like "Done" matches both "Done" and "Done{}". .then_with(|| lhs.kinds.len().cmp(&rhs.kinds.len())) @@ -1066,6 +1075,27 @@ impl SourceLanguage { ) (#not-any-of? @macro-name "format" "vec") ) + ; macros that take the level before the format string, like + ; `log!(Level::Warn, "...")` or `tracing::event!(Level::INFO, "...")` + (macro_invocation macro: (_) @macro-name + (token_tree . + (identifier) @_level . (string_literal) @log + ) + (#match? @macro-name "(^|::)(log|event)$") + (#not-eq? @_level "target") + ) + (macro_invocation macro: (_) @macro-name + (token_tree . + (identifier) . (identifier) . (string_literal) @log + ) + (#match? @macro-name "(^|::)(log|event)$") + ) + (macro_invocation macro: (_) @macro-name + (token_tree . + (identifier) . (identifier) . (identifier) . (string_literal) @log + ) + (#match? @macro-name "(^|::)(log|event)$") + ) "# } SourceLanguage::Java => { @@ -1082,7 +1112,7 @@ impl SourceLanguage { [(string_literal) (binary_expression)] @arguments) ] (#match? @object-name "log(ger)?|LOG(GER)?") - (#match? @method-name "^log$|fine|debug|info|warn|trace|error") + (#match? @method-name "^log$|fine|debug|info|warn|trace|error|severe|fatal") ) ; A message that is a constant, like log.info(Messages.LOG_STARTING, name) (method_invocation @@ -1090,7 +1120,7 @@ impl SourceLanguage { name: (identifier) @method-name arguments: (argument_list . [(identifier) (field_access)] @message-ref) (#match? @object-name "log(ger)?|LOG(GER)?") - (#match? @method-name "fine|debug|info|warn|trace|error") + (#match? @method-name "fine|debug|info|warn|trace|error|severe|fatal") ) ; java.util.logging's log(Level, String, ...) with a constant message (method_invocation @@ -1128,6 +1158,18 @@ impl SourceLanguage { ) ) ) + ; `logger.log(logging.WARNING, "...")` + ( + (expression_statement + (call + function: (_) @func + arguments: (argument_list . + (_) . [(string) (concatenated_string)] @args + ) + ) + ) + (#match? @func "(^|\\.)log$") + ) "# } SourceLanguage::Kotlin => { @@ -1327,6 +1369,8 @@ pub struct LogDetails<'a> { #[serde(skip_serializing_if = "Option::is_none")] pub lineno: Option, #[serde(skip_serializing)] + pub level: Option, + #[serde(skip_serializing)] pub body: Option<&'a str>, #[serde(skip_serializing_if = "Option::is_none")] pub trace: Option>, @@ -1337,6 +1381,7 @@ impl<'a> LogDetails<'a> { self.thread.is_none() && self.file.is_none() && self.lineno.is_none() + && self.level.is_none() && self.body.is_none() && self.trace.is_none() } @@ -1361,6 +1406,7 @@ impl<'a> LogRefBuilder<'a> { .map(|m| m.as_str().parse::().unwrap_or_default()), ) .with_thread(captures.name("thread").map(|m| m.as_str())) + .with_level(captures.name("level").map(|m| m.as_str())) .with_body(captures.name("body").map(|m| m.as_str())) .build(content) } @@ -1377,6 +1423,10 @@ impl<'a> LogRefBuilder<'a> { self.details.lineno = lineno; self } + pub fn with_level(mut self, level: Option<&'a str>) -> Self { + self.details.level = level.and_then(LogLevel::from_log_text); + self + } pub fn with_body(mut self, body: Option<&'a str>) -> Self { let (body, trace) = if let Some(body) = body { @@ -1437,12 +1487,16 @@ impl<'a> LogRef<'a> { self.line } } + + pub fn level(&self) -> Option { + self.details.and_then(|details| details.level) + } } pub fn link_to_source<'a>(log_ref: &LogRef, src_refs: &'a [SourceRef]) -> Option<&'a SourceRef> { let candidates = src_refs .iter() - .sorted_by(|lhs, rhs| compare_candidates(lhs, rhs, None)); + .sorted_by(|lhs, rhs| compare_candidates(lhs, rhs, None, log_ref.level())); first_match(candidates, log_ref.body(), None, |src_ref| src_ref) } @@ -1596,6 +1650,7 @@ pub fn extract_logging_guarded(sources: &[CodeSource], guard: &WorkGuard) -> Vec "message_ref" => { let range = result.range; let text = &code.buffer[range.start_byte..range.end_byte]; + let level = result.level(); message_refs.push(MessageRef { line_no: range.start_point.row + 1, end_line_no: range.end_point.row + 1, @@ -1604,6 +1659,7 @@ pub fn extract_logging_guarded(sources: &[CodeSource], guard: &WorkGuard) -> Vec qualified_name: result.qualified_name, block_id: result.block_id, text: text.to_string(), + level, vars: vec![], var_kinds: vec![], candidates: symbols.candidates(text, range.start_byte), @@ -1690,6 +1746,7 @@ mod tests { thread: None, file: Some("JvmPauseMonitor"), lineno: Some(146), + level: Some(LogLevel::Info), body: Some("JvmPauseMonitor-n0: Started"), trace: None, }); @@ -3949,6 +4006,200 @@ def main(x, t, pct): ); } + fn extract_levels(path: &str, source: &str) -> Vec<(String, LogLevel)> { + let code = CodeSource::from_string(&Path::new(path), source); + extract_logging(&[code], &ProgressTracker::new()) + .pop() + .unwrap() + .log_statements + .into_iter() + .map(|src_ref| (src_ref.text, src_ref.level)) + .collect() + } + + #[test] + fn test_levels_rust() { + let levels = extract_levels( + "in-mem.rs", + r#" +fn main() { + trace!("trace message"); + debug!("debug message"); + info!("info message"); + log::warn!("warn message"); + tracing::error!("error message"); + println!("plain message"); + log::log!(Level::Warn, "log macro message"); + tracing::event!(tracing::Level::INFO, "event macro message"); + log!(lvl, "level variable message"); + log!(target: "app", "target message"); +} +"#, + ); + assert_eq!( + levels, + vec![ + ("\"trace message\"".to_string(), LogLevel::Trace), + ("\"debug message\"".to_string(), LogLevel::Debug), + ("\"info message\"".to_string(), LogLevel::Info), + ("\"warn message\"".to_string(), LogLevel::Warn), + ("\"error message\"".to_string(), LogLevel::Error), + ("\"plain message\"".to_string(), LogLevel::Unknown), + ("\"log macro message\"".to_string(), LogLevel::Warn), + ("\"event macro message\"".to_string(), LogLevel::Info), + ("\"level variable message\"".to_string(), LogLevel::Unknown), + ] + ); + } + + #[test] + fn test_levels_java() { + let levels = extract_levels( + "in-mem.java", + r#" +class Main { + void run() { + LOG.trace("trace message"); + log.debug("debug message"); + logger.info("info message"); + LOGGER.warn("warn message"); + LOG.error("error message"); + log.severe("severe message"); + LOG.fatal("fatal message"); + log.finest("finest message"); + log.log(Level.WARNING, "level arg message"); + } +} +"#, + ); + assert_eq!( + levels, + vec![ + ("\"trace message\"".to_string(), LogLevel::Trace), + ("\"debug message\"".to_string(), LogLevel::Debug), + ("\"info message\"".to_string(), LogLevel::Info), + ("\"warn message\"".to_string(), LogLevel::Warn), + ("\"error message\"".to_string(), LogLevel::Error), + ("\"severe message\"".to_string(), LogLevel::Error), + ("\"fatal message\"".to_string(), LogLevel::Fatal), + ("\"finest message\"".to_string(), LogLevel::Trace), + ("\"level arg message\"".to_string(), LogLevel::Warn), + ] + ); + } + + #[test] + fn test_levels_cpp() { + let levels = extract_levels( + "in-mem.cc", + r#" +int main(int argc, char* argv[]) { + spdlog::info("info message"); + logger->warn("warn message"); + SPDLOG_ERROR("error message"); + spdlog::critical("critical message"); + log_debug("lnav debug message"); + log_warning("lnav warn message"); + syslog(LOG_ERR, "syslog error message"); + spdlog::log(spdlog::level::trace, "spdlog trace message"); + report_error("not a log message"); + printf("plain message"); + log_info("conn error", "second message"); + logger->info(err, "variable arg message"); + logInfo("camel message"); + errors.error("not a log message either"); +} +"#, + ); + assert_eq!( + levels, + vec![ + ("\"info message\"".to_string(), LogLevel::Info), + ("\"warn message\"".to_string(), LogLevel::Warn), + ("\"error message\"".to_string(), LogLevel::Error), + ("\"critical message\"".to_string(), LogLevel::Fatal), + ("\"lnav debug message\"".to_string(), LogLevel::Debug), + ("\"lnav warn message\"".to_string(), LogLevel::Warn), + ("\"syslog error message\"".to_string(), LogLevel::Error), + ("\"spdlog trace message\"".to_string(), LogLevel::Trace), + ("\"not a log message\"".to_string(), LogLevel::Unknown), + ("\"plain message\"".to_string(), LogLevel::Unknown), + ("\"conn error\"".to_string(), LogLevel::Info), + ("\"second message\"".to_string(), LogLevel::Info), + ("\"variable arg message\"".to_string(), LogLevel::Info), + ("\"camel message\"".to_string(), LogLevel::Info), + ( + "\"not a log message either\"".to_string(), + LogLevel::Unknown + ), + ] + ); + } + + #[test] + fn test_levels_python() { + let levels = extract_levels( + "in-mem.py", + r#" +def main(): + logger.debug("debug message") + logging.info("info message") + logger.warning("warn message") + self.log.error("error message") + logger.exception("exception message") + logger.critical("critical message") + print("plain message") + warnings.warn("deprecated message") + parser.error("bad arg message") + logger.log(logging.WARNING, "level arg message") + logging.log(level, "level variable message") +"#, + ); + assert_eq!( + levels, + vec![ + ("\"debug message\"".to_string(), LogLevel::Debug), + ("\"info message\"".to_string(), LogLevel::Info), + ("\"warn message\"".to_string(), LogLevel::Warn), + ("\"error message\"".to_string(), LogLevel::Error), + ("\"exception message\"".to_string(), LogLevel::Error), + ("\"critical message\"".to_string(), LogLevel::Fatal), + ("\"plain message\"".to_string(), LogLevel::Unknown), + ("\"deprecated message\"".to_string(), LogLevel::Unknown), + ("\"bad arg message\"".to_string(), LogLevel::Unknown), + ("\"level arg message\"".to_string(), LogLevel::Warn), + ("\"level variable message\"".to_string(), LogLevel::Unknown), + ] + ); + } + + #[test] + fn test_link_to_source_by_level() { + let code = CodeSource::from_string( + &Path::new("in-mem.rs"), + r#" +fn main() { + debug!("retry"); + warn!("retry"); +} +"#, + ); + let src_refs = extract_logging(&[code], &ProgressTracker::new()) + .pop() + .unwrap() + .log_statements; + let log_format: LogFormat = r"^(?\w+) (?.*)$".try_into().unwrap(); + for (line, expected) in [ + ("DEBUG retry", LogLevel::Debug), + ("WARN retry", LogLevel::Warn), + ] { + let log_ref = + LogRefBuilder::new().build_from_captures(log_format.captures(line).unwrap(), line); + let result = link_to_source(&log_ref, &src_refs).unwrap(); + assert_eq!(result.level, expected, "{line}"); + } + } + const TRACE: &str = r#"JvmPauseMonitor-n0: Started java.lang.IllegalStateException: simulated failure for demo at org.example.Main.simulateError(Main.java:50) diff --git a/src/snapshots/log2src__tests__backtrace_re-3.snap b/src/snapshots/log2src__tests__backtrace_re-3.snap index 9c484775..f890c95b 100644 --- a/src/snapshots/log2src__tests__backtrace_re-3.snap +++ b/src/snapshots/log2src__tests__backtrace_re-3.snap @@ -11,6 +11,7 @@ expression: src_refs qualifiedName: in-mem.run blockId: 24 text: "\"{}: Started\"" + level: Info quality: 8 pattern: "(?s)^(.*): Started$" args: @@ -35,6 +36,7 @@ expression: src_refs qualifiedName: in-mem.run blockId: 69 text: "\"{}: Stopped\"" + level: Info quality: 8 pattern: "(?s)^(.*): Stopped$" args: diff --git a/src/snapshots/log2src__tests__basic_kotlin.snap b/src/snapshots/log2src__tests__basic_kotlin.snap index 15587bf6..7d85bdd4 100644 --- a/src/snapshots/log2src__tests__basic_kotlin.snap +++ b/src/snapshots/log2src__tests__basic_kotlin.snap @@ -11,6 +11,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Started {} with {} threads\"" + level: Info quality: 18 pattern: (?s)^Started (.*) with (.*) threads$ args: @@ -41,6 +42,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Hello $user, you have ${user.messages.size} messages\"" + level: Info quality: 21 pattern: "(?s)^Hello (.*), you have (.*) messages$" args: @@ -67,6 +69,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Mixed {} and $count \\$5\\ttab\"" + level: Debug quality: 16 pattern: "(?s)^Mixed (.*) and (.*) \\$5\\ttab$" args: @@ -95,6 +98,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Lazy ${user.id}\"" + level: Info quality: 4 pattern: (?s)^Lazy (.*)$ args: @@ -117,6 +121,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Failed for $user\"" + level: Error quality: 9 pattern: (?s)^Failed for (.*)$ args: @@ -139,6 +144,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Concat \" + count + \" items\"" + level: Warn quality: 11 pattern: (?s)^Concat (.*) items$ args: @@ -161,6 +167,7 @@ expression: src_refs qualifiedName: com.example.Server.handle blockId: 89 text: "\"Failed [count=${user.messages.size}] \" +\n \"after ${count / 1000.0} sec, \" + count + \" left\"" + level: Warn quality: 29 pattern: "(?s)^Failed \\[count=(.*)\\] after (.*) sec, (.*) left$" args: diff --git a/src/snapshots/log2src__tests__basic_python.snap b/src/snapshots/log2src__tests__basic_python.snap index 06140e8f..aa52b095 100644 --- a/src/snapshots/log2src__tests__basic_python.snap +++ b/src/snapshots/log2src__tests__basic_python.snap @@ -11,6 +11,7 @@ expression: src_refs qualifiedName: main blockId: 21 text: "\"foo %s \\N{greek small letter pi}\"" + level: Info quality: 4 pattern: (?s)^foo (.*) .$ args: @@ -35,6 +36,7 @@ expression: src_refs qualifiedName: main blockId: 21 text: "f'Hello, {args[1]}!'" + level: Info quality: 7 pattern: "(?s)^Hello, (.*)!$" args: @@ -57,6 +59,7 @@ expression: src_refs qualifiedName: main blockId: 21 text: "f\"warning message:\\nlow disk space\"" + level: Warn quality: 29 pattern: "(?s)^warning message:\\nlow disk space$" args: [] @@ -75,6 +78,7 @@ expression: src_refs qualifiedName: main blockId: 21 text: "rf\"\"\"info message:\nprocessing \\started -- {args[0]}\"\"\"" + level: Info quality: 35 pattern: "(?s)^info message:\\nprocessing \\\\started -- (.*)$" args: diff --git a/src/snapshots/log2src__tests__extract_logging.snap b/src/snapshots/log2src__tests__extract_logging.snap index a7fe013d..7cad74c4 100644 --- a/src/snapshots/log2src__tests__extract_logging.snap +++ b/src/snapshots/log2src__tests__extract_logging.snap @@ -11,6 +11,7 @@ expression: src_refs qualifiedName: main blockId: 43 text: "\"you're only as funky as your last cut\"" + level: Debug quality: 30 pattern: "(?s)^you're only as funky as your last cut$" args: [] @@ -29,6 +30,7 @@ expression: src_refs qualifiedName: nope blockId: 224 text: "\"this won't match i={}; j={}\"" + level: Debug quality: 19 pattern: "(?s)^this won't match i=(.*); j=(.*)$" args: @@ -59,6 +61,7 @@ expression: src_refs qualifiedName: namedarg0 blockId: 326 text: "\"{salutation}, {name}!\"" + level: Debug quality: 2 pattern: "(?s)^(.*), (.*)!$" args: @@ -85,6 +88,7 @@ expression: src_refs qualifiedName: namedarg blockId: 427 text: "\"Hello, {name}!\"" + level: Debug quality: 7 pattern: "(?s)^Hello, (.*)!$" args: @@ -107,6 +111,7 @@ expression: src_refs qualifiedName: namedarg2 blockId: 548 text: "\"{salutation}, {name}!\"" + level: Debug quality: 2 pattern: "(?s)^(.*), (.*)!$" args: diff --git a/src/snapshots/log2src__tests__link_to_quality_source.snap b/src/snapshots/log2src__tests__link_to_quality_source.snap index e437331d..987518b4 100644 --- a/src/snapshots/log2src__tests__link_to_quality_source.snap +++ b/src/snapshots/log2src__tests__link_to_quality_source.snap @@ -11,6 +11,7 @@ name: namedarg qualifiedName: namedarg blockId: 427 text: "\"Hello, {name}!\"" +level: Debug quality: 7 pattern: "(?s)^Hello, (.*)!$" args: diff --git a/src/source_query.rs b/src/source_query.rs index 1fb6fe66..b274d524 100644 --- a/src/source_query.rs +++ b/src/source_query.rs @@ -4,7 +4,7 @@ use tree_sitter::{ Language, Node, Parser, Point, Query, QueryCursor, Range as TSRange, StreamingIterator, Tree, }; -use crate::source_ref::{ArgCounter, FormatArgument, Substitution}; +use crate::source_ref::{ArgCounter, FormatArgument, LogLevel, Substitution}; use crate::value_kind::ValueKind; use crate::{CodeSource, SourceLanguage}; use regex::Regex; @@ -32,6 +32,24 @@ pub(crate) struct QueryResult { pub raw: bool, /// For an argument of the log call, the kind of value it produces. pub value_kind: ValueKind, + /// The text of the last capture before the format string, which is the name of the logging + /// function/macro/method being called (e.g. `log::warn`, `logger.info`). + pub call_name: Option, + /// The text of the arguments before the format string, which might include the log level, + /// as in `syslog(LOG_ERR, "...")`. + pub leading_args: Vec, +} + +impl QueryResult { + /// The level of the log call. A level constant passed as an argument, like + /// `syslog(LOG_ERR, ...)`, takes precedence over the name of the call. + pub fn level(&self) -> LogLevel { + self.leading_args + .iter() + .find_map(|arg| LogLevel::from_level_arg(arg)) + .or_else(|| self.call_name.as_deref().and_then(LogLevel::from_name)) + .unwrap_or(LogLevel::Unknown) + } } impl<'a> SourceQuery<'a> { @@ -145,7 +163,12 @@ impl<'a> SourceQuery<'a> { let matches = cursor.matches(&query, self.tree.root_node(), self.source.as_bytes()); matches.for_each(|m| { let mut got_string_literal = false; + let mut call_name: Option = None; for capture in m.captures { + // captures starting with an underscore are only used for predicates + if query.capture_names()[capture.index as usize].starts_with('_') { + continue; + } let mut child = capture.node; let mut concat_pattern = None; let mut concat_args = vec![]; @@ -208,6 +231,10 @@ impl<'a> SourceQuery<'a> { } _ => { if !got_string_literal { + // remember the name of the logging call so the log level can be + // derived from it. + let range = capture.node.byte_range(); + call_name = Some(self.source[range].to_string()); continue; } } @@ -227,6 +254,8 @@ impl<'a> SourceQuery<'a> { args: std::mem::take(&mut concat_args), raw: false, value_kind: ValueKind::Any, + call_name: call_name.clone(), + leading_args: self.leading_args(child), }); if self.source_language == SourceLanguage::Python && matches!(child.kind(), "string" | "concatenated_string") @@ -277,6 +306,8 @@ impl<'a> SourceQuery<'a> { args: vec![], raw: false, value_kind, + call_name: None, + leading_args: vec![], }); } } @@ -718,6 +749,50 @@ impl<'a> SourceQuery<'a> { false } + /// Collect the arguments before the format string that might be a log level, like the + /// `LOG_ERR` in `syslog(LOG_ERR, "...")` or the `Level::Warn` in `log!(Level::Warn, "...")`. + fn leading_args(&self, node: Node) -> Vec { + let mut args = Vec::new(); + match node.parent().map(|p| p.kind()) { + Some("argument_list") => { + let mut prev = node.prev_named_sibling(); + while let Some(arg) = prev { + // Only names can be level constants, other arguments like string literals + // could contain level words that aren't relevant. + if matches!( + arg.kind(), + "identifier" + | "qualified_identifier" + | "field_expression" + | "field_access" + | "attribute" + ) { + args.push(self.source[arg.byte_range()].to_string()); + } + prev = arg.prev_named_sibling(); + } + args.reverse(); + } + Some("token_tree") => { + // Macro arguments are a flat list of tokens, so split the text before the + // format string on commas. + let parent = node.parent().unwrap(); + let start = parent.start_byte() + 1; + if start < node.start_byte() { + args.extend( + self.source[start..node.start_byte()] + .split(',') + .map(str::trim) + .filter(|arg| !arg.is_empty() && !arg.contains('"')) + .map(str::to_string), + ); + } + } + _ => {} + } + args + } + fn find_fn_range(node: Node) -> Range { // println!("node.kind()={:?}", node.kind()); match node.kind() { diff --git a/src/source_ref.rs b/src/source_ref.rs index 93802dd1..48d978ca 100644 --- a/src/source_ref.rs +++ b/src/source_ref.rs @@ -14,6 +14,120 @@ pub enum FormatArgument { Placeholder, } +/// The normalized level of a log statement, derived from the name of the logging call. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub enum LogLevel { + Trace, + Debug, + Info, + Warn, + Error, + Fatal, + /// The level could not be determined, which also means the statement might not be logging + /// at all, like a `printf()` or a call that just happens to take a string. + Unknown, +} + +impl LogLevel { + /// Map the name of a logging function/macro/method, like `log::warn`, `logger.warning`, + /// `spdlog::info`, `log_debug`, `logInfo`, or `SPDLOG_ERROR`, to a level. Returns `None` + /// for names that don't indicate a level, like `println`, `printf`, or `parser.error`. + pub fn from_name(name: &str) -> Option { + Self::classify(name, false) + } + + /// Map an argument that is passed to a logging call, like `LOG_ERR`, `logging.WARNING`, or + /// `spdlog::level::warn`, to a level. Unlike [`LogLevel::from_name`], the argument has to + /// be qualified by something logging related, so that a variable like `err` is ignored. + pub fn from_level_arg(arg: &str) -> Option { + Self::classify(arg, true) + } + + /// Map the level text from a log message, like `WARN` or `error`, to a level. + pub fn from_log_text(text: &str) -> Option { + Self::from_word(&text.trim().to_lowercase()) + } + + fn classify(name: &str, require_qualifier: bool) -> Option { + let mut segments: Vec<&str> = name + .split(|c: char| !(c.is_alphanumeric() || c == '_')) + .filter(|s| !s.is_empty()) + .collect(); + let mut words = split_words(segments.pop()?); + let last = words.pop()?; + // For names like `log_debug`, `SPDLOG_INFO`, or `LOG_ERR`, the level is at the end and + // one of the other words needs to look logging related so that something like + // `report_error` is not treated as a log statement. + if !words.is_empty() { + return if words.iter().any(|w| is_logging_word(w)) { + Self::from_word(&last) + } else { + None + }; + } + // For a qualified name, like `logger.warn` or `spdlog::level::info`, the qualifier + // needs to look logging related so that something like `warnings.warn` or + // `parser.error` is not treated as a log statement. + let qualified = segments + .iter() + .flat_map(|seg| split_words(seg)) + .any(|w| is_logging_word(&w)); + if qualified || (segments.is_empty() && !require_qualifier) { + Self::from_word(&last) + } else { + None + } + } + + fn from_word(word: &str) -> Option { + match word { + "trace" | "finer" | "finest" => Some(LogLevel::Trace), + "debug" | "dbg" | "fine" => Some(LogLevel::Debug), + "info" | "notice" => Some(LogLevel::Info), + "warn" | "warning" => Some(LogLevel::Warn), + "error" | "err" | "exception" | "severe" => Some(LogLevel::Error), + "fatal" | "critical" | "crit" | "alert" | "emerg" => Some(LogLevel::Fatal), + _ => None, + } + } +} + +fn is_logging_word(word: &str) -> bool { + word.contains("log") || matches!(word, "level" | "lvl" | "tracing") +} + +/// Split an identifier into lowercase words on underscores and case changes, so `log_debug`, +/// `logDebug`, `LogDebug`, and `LOG_DEBUG` all become `["log", "debug"]`. +fn split_words(ident: &str) -> Vec { + let chars: Vec = ident.chars().collect(); + let mut words = Vec::new(); + let mut word = String::new(); + for (i, &c) in chars.iter().enumerate() { + if c == '_' { + if !word.is_empty() { + words.push(std::mem::take(&mut word)); + } + continue; + } + if c.is_uppercase() && !word.is_empty() { + let prev = chars[i - 1]; + let next_is_lower = chars.get(i + 1).is_some_and(|n| n.is_lowercase()); + // Split `logDebug` before the `D` and `LOGDebug` before the `D`, but not `SPDLOG`. + if prev.is_lowercase() + || prev.is_ascii_digit() + || (prev.is_uppercase() && next_is_lower) + { + words.push(std::mem::take(&mut word)); + } + } + word.extend(c.to_lowercase()); + } + if !word.is_empty() { + words.push(word); + } + words +} + #[derive(Clone, Debug, Serialize)] pub struct CallSite { pub name: String, @@ -105,6 +219,7 @@ pub struct SourceRef { #[serde(rename(serialize = "blockId"))] pub block_id: u32, pub text: String, + pub level: LogLevel, pub quality: usize, #[serde(with = "serde_regex")] pub(crate) pattern: Regex, @@ -149,6 +264,7 @@ struct MessageMatcher { impl SourceRef { pub(crate) fn new(code: &CodeSource, result: QueryResult) -> Option { let range = result.range; + let level = result.level(); let source = code.buffer.as_str(); let text = source[range.start_byte..range.end_byte].to_string(); let line_no = range.start_point.row + 1; @@ -190,6 +306,7 @@ impl SourceRef { qualified_name: result.qualified_name, block_id: result.block_id, text, + level, quality, pattern_str: matcher.as_str().to_string(), pattern: matcher, @@ -234,6 +351,7 @@ impl SourceRef { qualified_name: message_ref.qualified_name.clone(), block_id: message_ref.block_id, text: message_ref.text.clone(), + level: message_ref.level, quality, pattern_str: matcher.as_str().to_string(), pattern: matcher, @@ -628,6 +746,81 @@ fn literal_to_regex(raw: bool, language: SourceLanguage, segment: &str) -> Strin mod tests { use super::*; + #[test] + fn test_log_level_from_name() { + let cases = [ + ("debug", Some(LogLevel::Debug)), + ("log::warn", Some(LogLevel::Warn)), + ("tracing::trace", Some(LogLevel::Trace)), + ("error", Some(LogLevel::Error)), + ("info", Some(LogLevel::Info)), + ("spdlog::info", Some(LogLevel::Info)), + ("spdlog::critical", Some(LogLevel::Fatal)), + ("logger->warn", Some(LogLevel::Warn)), + ("SPDLOG_ERROR", Some(LogLevel::Error)), + ("logger.warning", Some(LogLevel::Warn)), + ("logging.exception", Some(LogLevel::Error)), + ("self.log.critical", Some(LogLevel::Fatal)), + ("fine", Some(LogLevel::Debug)), + ("log_debug", Some(LogLevel::Debug)), + ("log_warning", Some(LogLevel::Warn)), + ("LOG_ERR", Some(LogLevel::Error)), + ("LOG_CRIT", Some(LogLevel::Fatal)), + ("APLOG_MARK", None), + ("spdlog::level::warn", Some(LogLevel::Warn)), + ("LEVEL_INFO", Some(LogLevel::Info)), + ("println", None), + ("printf", None), + ("print", None), + ("report_error", None), + ("logInfo", Some(LogLevel::Info)), + ("LogWarning", Some(LogLevel::Warn)), + ("m_logger->logError", Some(LogLevel::Error)), + ("LOGError", Some(LogLevel::Error)), + ("reportError", None), + ("tracing::error", Some(LogLevel::Error)), + ("spdlog::get(\"app\")->warn", Some(LogLevel::Warn)), + ("warnings.warn", None), + ("parser.error", None), + ("errors.error", None), + ]; + for (name, expected) in cases { + assert_eq!(LogLevel::from_name(name), expected, "{name}"); + } + } + + #[test] + fn test_log_level_from_level_arg() { + let cases = [ + ("LOG_ERR", Some(LogLevel::Error)), + ("spdlog::level::trace", Some(LogLevel::Trace)), + ("logging.WARNING", Some(LogLevel::Warn)), + ("Level::Warn", Some(LogLevel::Warn)), + ("tracing::Level::INFO", Some(LogLevel::Info)), + ("Level.SEVERE", Some(LogLevel::Error)), + ("err", None), + ("info", None), + ("level", None), + ("errors.error", None), + ]; + for (name, expected) in cases { + assert_eq!(LogLevel::from_level_arg(name), expected, "{name}"); + } + } + + #[test] + fn test_log_level_from_log_text() { + let cases = [ + ("WARN", Some(LogLevel::Warn)), + ("warning", Some(LogLevel::Warn)), + (" ERROR ", Some(LogLevel::Error)), + ("W", None), + ]; + for (name, expected) in cases { + assert_eq!(LogLevel::from_name(name), expected, "{name}"); + } + } + #[test] fn test_build_matcher_needs_escape() { let MessageMatcher { diff --git a/tests/snapshots/test_java__basic.snap b/tests/snapshots/test_java__basic.snap index ef555a39..06a7dbc0 100644 --- a/tests/snapshots/test_java__basic.snap +++ b/tests/snapshots/test_java__basic.snap @@ -20,9 +20,9 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"Basic.main","blockId":234,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"Basic.main","blockId":234,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_invalid_utf.snap b/tests/snapshots/test_java__basic_invalid_utf.snap index f7705635..4dd3f7dc 100644 --- a/tests/snapshots/test_java__basic_invalid_utf.snap +++ b/tests/snapshots/test_java__basic_invalid_utf.snap @@ -20,10 +20,10 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"Basic.main","blockId":234,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"Basic.main","blockId":234,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} {"error":{"message":"unable to read line 2","source":"stream did not contain valid UTF-8"}} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_range.snap b/tests/snapshots/test_java__basic_range.snap index dbd874bd..688b189b 100644 --- a/tests/snapshots/test_java__basic_range.snap +++ b/tests/snapshots/test_java__basic_range.snap @@ -24,7 +24,7 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/Basic.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"Basic.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_slf4j-2.snap b/tests/snapshots/test_java__basic_slf4j-2.snap index 80f63ec6..a813a1a0 100644 --- a/tests/snapshots/test_java__basic_slf4j-2.snap +++ b/tests/snapshots/test_java__basic_slf4j-2.snap @@ -20,7 +20,7 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","level":"Info","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","level":"Debug","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_slf4j-3.snap b/tests/snapshots/test_java__basic_slf4j-3.snap index db56267d..b3308055 100644 --- a/tests/snapshots/test_java__basic_slf4j-3.snap +++ b/tests/snapshots/test_java__basic_slf4j-3.snap @@ -20,8 +20,8 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","level":"Info","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","level":"Debug","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} ----- stderr ----- ⚠ failed to read cache file "cache.XXX" diff --git a/tests/snapshots/test_java__basic_slf4j.snap b/tests/snapshots/test_java__basic_slf4j.snap index 80f63ec6..a813a1a0 100644 --- a/tests/snapshots/test_java__basic_slf4j.snap +++ b/tests/snapshots/test_java__basic_slf4j.snap @@ -20,7 +20,7 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":10,"endLineNumber":10,"column":20,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Application starting\"","level":"Info","quality":19,"pattern":"(?s)^Application starting$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Application starting"]},"variables":[]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{java_dir}/BasicSlf4j.java","language":"Java","lineNumber":12,"endLineNumber":13,"column":21,"name":"main","qualifiedName":"org.example.Main.main","blockId":250,"text":"\"Debug message: args length = {}\"","level":"Debug","quality":24,"pattern":"(?s)^Debug message: args length = (.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.length"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Debug message: args length = ",""]},"variables":[{"expr":"args.length","value":"0"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_with_log.snap b/tests/snapshots/test_java__basic_with_log.snap index 5295769e..f9be54c4 100644 --- a/tests/snapshots/test_java__basic_with_log.snap +++ b/tests/snapshots/test_java__basic_with_log.snap @@ -20,9 +20,9 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":13,"name":"main","qualifiedName":"BasicWithLog.main","blockId":231,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":13,"name":"main","qualifiedName":"BasicWithLog.main","blockId":231,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithLog.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":17,"name":"foo","qualifiedName":"BasicWithLog.foo","blockId":606,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_with_log_format-2.snap b/tests/snapshots/test_java__basic_with_log_format-2.snap index 4d8dc771..cbec5594 100644 --- a/tests/snapshots/test_java__basic_with_log_format-2.snap +++ b/tests/snapshots/test_java__basic_with_log_format-2.snap @@ -20,9 +20,9 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"file":"BasicWithCustom","lineno":15}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":15,"endLineNumber":15,"column":16,"name":"main","qualifiedName":"BasicWithCustom.main","blockId":233,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":15}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":15,"endLineNumber":15,"column":16,"name":"main","qualifiedName":"BasicWithCustom.main","blockId":233,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_with_log_format.snap b/tests/snapshots/test_java__basic_with_log_format.snap index 4d8dc771..cbec5594 100644 --- a/tests/snapshots/test_java__basic_with_log_format.snap +++ b/tests/snapshots/test_java__basic_with_log_format.snap @@ -20,9 +20,9 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"file":"BasicWithCustom","lineno":15}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":15,"endLineNumber":15,"column":16,"name":"main","qualifiedName":"BasicWithCustom.main","blockId":233,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":15}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":15,"endLineNumber":15,"column":16,"name":"main","qualifiedName":"BasicWithCustom.main","blockId":233,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{"details":{"file":"BasicWithCustom","lineno":22}},"srcRef":{"sourcePath":"{java_dir}/BasicWithCustom.java","language":"Java","lineNumber":22,"endLineNumber":22,"column":20,"name":"foo","qualifiedName":"BasicWithCustom.foo","blockId":508,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_java__basic_with_upper.snap b/tests/snapshots/test_java__basic_with_upper.snap index 4a4f2fbf..e7996664 100644 --- a/tests/snapshots/test_java__basic_with_upper.snap +++ b/tests/snapshots/test_java__basic_with_upper.snap @@ -20,9 +20,9 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"BasicWithUpper.main","blockId":234,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":18,"endLineNumber":18,"column":16,"name":"main","qualifiedName":"BasicWithUpper.main","blockId":234,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{java_dir}/BasicWithUpper.java","language":"Java","lineNumber":25,"endLineNumber":25,"column":20,"name":"foo","qualifiedName":"BasicWithUpper.foo","blockId":618,"text":"\"Hello from foo i=\\{i}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":[{"Named":"i"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} ----- stderr ----- diff --git a/tests/snapshots/test_kotlin__basic.snap b/tests/snapshots/test_kotlin__basic.snap index b8fb769d..b0ed6da7 100644 --- a/tests/snapshots/test_kotlin__basic.snap +++ b/tests/snapshots/test_kotlin__basic.snap @@ -20,10 +20,10 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":20,"endLineNumber":20,"column":16,"name":"main","qualifiedName":"org.example.BasicKt.main","blockId":518,"text":"\"Application starting with {} args\"","quality":27,"pattern":"(?s)^Application starting with (.*) args$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.size"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Application starting with "," args"]},"variables":[{"expr":"args.size","value":"0"}]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":11,"endLineNumber":11,"column":20,"name":"run","qualifiedName":"org.example.Worker.run","blockId":270,"text":"\"Worker {} starting\"","quality":14,"pattern":"(?s)^Worker (.*) starting$","args":["Placeholder"],"argKinds":["Any"],"vars":["name"],"varKinds":["Any"],"kinds":["Any"],"segments":["Worker "," starting"]},"variables":[{"expr":"name","value":"alpha"}]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":13,"endLineNumber":13,"column":25,"name":"run","qualifiedName":"org.example.Worker.run","blockId":353,"text":"\"$name processing item $i of ${count - 1}\"","quality":16,"pattern":"(?s)^(.*) processing item (.*) of (.*)$","args":[{"Named":"name"},{"Named":"i"},{"Named":"count - 1"}],"argKinds":["Any","Any","Any"],"vars":[],"varKinds":[],"kinds":["Any","Any","Any"],"segments":[""," processing item "," of ",""]},"variables":[{"expr":"name","value":"alpha"},{"expr":"i","value":"0"},{"expr":"count - 1","value":"1"}]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":13,"endLineNumber":13,"column":25,"name":"run","qualifiedName":"org.example.Worker.run","blockId":353,"text":"\"$name processing item $i of ${count - 1}\"","quality":16,"pattern":"(?s)^(.*) processing item (.*) of (.*)$","args":[{"Named":"name"},{"Named":"i"},{"Named":"count - 1"}],"argKinds":["Any","Any","Any"],"vars":[],"varKinds":[],"kinds":["Any","Any","Any"],"segments":[""," processing item "," of ",""]},"variables":[{"expr":"name","value":"alpha"},{"expr":"i","value":"1"},{"expr":"count - 1","value":"1"}]} -{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":15,"endLineNumber":15,"column":23,"name":"run","qualifiedName":"org.example.Worker.run","blockId":270,"text":"\"Worker $name done\"","quality":10,"pattern":"(?s)^Worker (.*) done$","args":[{"Named":"name"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Worker "," done"]},"variables":[{"expr":"name","value":"alpha"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":20,"endLineNumber":20,"column":16,"name":"main","qualifiedName":"org.example.BasicKt.main","blockId":518,"text":"\"Application starting with {} args\"","level":"Info","quality":27,"pattern":"(?s)^Application starting with (.*) args$","args":["Placeholder"],"argKinds":["Any"],"vars":["args.size"],"varKinds":["Integer"],"kinds":["Any"],"segments":["Application starting with "," args"]},"variables":[{"expr":"args.size","value":"0"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":11,"endLineNumber":11,"column":20,"name":"run","qualifiedName":"org.example.Worker.run","blockId":270,"text":"\"Worker {} starting\"","level":"Info","quality":14,"pattern":"(?s)^Worker (.*) starting$","args":["Placeholder"],"argKinds":["Any"],"vars":["name"],"varKinds":["Any"],"kinds":["Any"],"segments":["Worker "," starting"]},"variables":[{"expr":"name","value":"alpha"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":13,"endLineNumber":13,"column":25,"name":"run","qualifiedName":"org.example.Worker.run","blockId":353,"text":"\"$name processing item $i of ${count - 1}\"","level":"Debug","quality":16,"pattern":"(?s)^(.*) processing item (.*) of (.*)$","args":[{"Named":"name"},{"Named":"i"},{"Named":"count - 1"}],"argKinds":["Any","Any","Any"],"vars":[],"varKinds":[],"kinds":["Any","Any","Any"],"segments":[""," processing item "," of ",""]},"variables":[{"expr":"name","value":"alpha"},{"expr":"i","value":"0"},{"expr":"count - 1","value":"1"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":13,"endLineNumber":13,"column":25,"name":"run","qualifiedName":"org.example.Worker.run","blockId":353,"text":"\"$name processing item $i of ${count - 1}\"","level":"Debug","quality":16,"pattern":"(?s)^(.*) processing item (.*) of (.*)$","args":[{"Named":"name"},{"Named":"i"},{"Named":"count - 1"}],"argKinds":["Any","Any","Any"],"vars":[],"varKinds":[],"kinds":["Any","Any","Any"],"segments":[""," processing item "," of ",""]},"variables":[{"expr":"name","value":"alpha"},{"expr":"i","value":"1"},{"expr":"count - 1","value":"1"}]} +{"logRef":{"details":{"thread":"123"}},"srcRef":{"sourcePath":"{kotlin_dir}/org/example/Basic.kt","language":"Kotlin","lineNumber":15,"endLineNumber":15,"column":23,"name":"run","qualifiedName":"org.example.Worker.run","blockId":270,"text":"\"Worker $name done\"","level":"Info","quality":10,"pattern":"(?s)^Worker (.*) done$","args":[{"Named":"name"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Worker "," done"]},"variables":[{"expr":"name","value":"alpha"}]} ----- stderr ----- diff --git a/tests/snapshots/test_rust__basic.snap b/tests/snapshots/test_rust__basic.snap index ec4ebb60..4b53ad38 100644 --- a/tests/snapshots/test_rust__basic.snap +++ b/tests/snapshots/test_rust__basic.snap @@ -20,11 +20,11 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":6,"endLineNumber":6,"column":11,"name":"main","qualifiedName":"main","blockId":42,"text":"\"Hello from main\"","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":19,"endLineNumber":19,"column":11,"name":"bar","qualifiedName":"bar","blockId":244,"text":"\"Hello from bar j={j}\"","quality":14,"pattern":"(?s)^Hello from bar j=(.*)$","args":[{"Named":"j"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from bar j=",""]},"variables":[{"expr":"j","value":"4"}]} -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":23,"endLineNumber":23,"column":11,"name":"baz","qualifiedName":"baz","blockId":308,"text":"\"Hello from baz i={1} j={0}\"","quality":16,"pattern":"(?s)^Hello from baz i=(.*) j=(.*)$","args":[{"Positional":1},{"Positional":0}],"argKinds":["Any","Any"],"vars":["j","i"],"varKinds":["Any","Any"],"kinds":["Any","Any"],"segments":["Hello from baz i="," j=",""]},"variables":[{"expr":"i","value":"5"},{"expr":"j","value":"6"}]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":6,"endLineNumber":6,"column":11,"name":"main","qualifiedName":"main","blockId":42,"text":"\"Hello from main\"","level":"Debug","quality":13,"pattern":"(?s)^Hello from main$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from main"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"0"}]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"1"}]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"foo","qualifiedName":"foo","blockId":186,"text":"\"Hello from foo i={}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from foo i=(.*)$","args":["Placeholder"],"argKinds":["Any"],"vars":["i"],"varKinds":["Any"],"kinds":["Any"],"segments":["Hello from foo i=",""]},"variables":[{"expr":"i","value":"2"}]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":19,"endLineNumber":19,"column":11,"name":"bar","qualifiedName":"bar","blockId":244,"text":"\"Hello from bar j={j}\"","level":"Debug","quality":14,"pattern":"(?s)^Hello from bar j=(.*)$","args":[{"Named":"j"}],"argKinds":["Any"],"vars":[],"varKinds":[],"kinds":["Any"],"segments":["Hello from bar j=",""]},"variables":[{"expr":"j","value":"4"}]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/basic.rs","language":"Rust","lineNumber":23,"endLineNumber":23,"column":11,"name":"baz","qualifiedName":"baz","blockId":308,"text":"\"Hello from baz i={1} j={0}\"","level":"Debug","quality":16,"pattern":"(?s)^Hello from baz i=(.*) j=(.*)$","args":[{"Positional":1},{"Positional":0}],"argKinds":["Any","Any"],"vars":["j","i"],"varKinds":["Any","Any"],"kinds":["Any","Any"],"segments":["Hello from baz i="," j=",""]},"variables":[{"expr":"i","value":"5"},{"expr":"j","value":"6"}]} ----- stderr ----- diff --git a/tests/snapshots/test_rust__stack.snap b/tests/snapshots/test_rust__stack.snap index ba2d63b3..449783eb 100644 --- a/tests/snapshots/test_rust__stack.snap +++ b/tests/snapshots/test_rust__stack.snap @@ -22,6 +22,6 @@ info: success: true exit_code: 0 ----- stdout ----- -{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/stack.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"b","qualifiedName":"b","blockId":139,"text":"\"Hello from b\"","quality":10,"pattern":"(?s)^Hello from b$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from b"]},"variables":[]} +{"logRef":{},"srcRef":{"sourcePath":"{example_dir}/stack.rs","language":"Rust","lineNumber":15,"endLineNumber":15,"column":11,"name":"b","qualifiedName":"b","blockId":139,"text":"\"Hello from b\"","level":"Debug","quality":10,"pattern":"(?s)^Hello from b$","args":[],"argKinds":[],"vars":[],"varKinds":[],"kinds":[],"segments":["Hello from b"]},"variables":[]} ----- stderr -----