diff --git a/src/runners/baseRunner/RunnerResultAnalyzer.ts b/src/runners/baseRunner/RunnerResultAnalyzer.ts
index 7c7cb4e..0497275 100644
--- a/src/runners/baseRunner/RunnerResultAnalyzer.ts
+++ b/src/runners/baseRunner/RunnerResultAnalyzer.ts
@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
-import * as path from 'path';
-import { Location, MarkdownString, Range, TestItem } from 'vscode';
+import { Location, MarkdownString, TestItem } from 'vscode';
import { IRunTestContext } from '../../types';
+import { processStackTraceLine } from '../utils';
export abstract class RunnerResultAnalyzer {
constructor(protected testContext: IRunTestContext) { }
@@ -21,46 +21,14 @@ export abstract class RunnerResultAnalyzer {
}
protected processStackTrace(data: string, traces: MarkdownString, currentItem: TestItem | undefined, projectName: string): void {
- const traceRegExp: RegExp = /(\s?at\s+)([\w$\\.]+\/)?((?:[\w$]+\.)+[<\w$>]+)\((.*)\)/;
- const traceResults: RegExpExecArray | null = traceRegExp.exec(data);
- if (traceResults) {
- const fullyQualifiedName: string = traceResults[3];
- if (this.isExcluded(fullyQualifiedName)) {
- return;
- }
-
- const location: string = traceResults[4];
- let sourceName: string | undefined;
- let lineNumLiteral: string | undefined;
- const locationResult: RegExpExecArray | null = /([\w-$]+\.java):(\d+)/.exec(location);
- if (locationResult) {
- sourceName = locationResult[1];
- lineNumLiteral = locationResult[2];
- }
-
- if (!sourceName || !lineNumLiteral) {
- traces.appendText(data);
- } else {
- const atLiteral: string = traceResults[1];
- const optionalModuleName: string = traceResults[2] || '';
- traces.appendText(atLiteral);
- traces.appendMarkdown(`${optionalModuleName + fullyQualifiedName}([${sourceName}:${lineNumLiteral}](command:_java.test.openStackTrace?${encodeURIComponent(JSON.stringify([data, projectName]))}))`);
- if (currentItem && path.basename(currentItem.uri?.fsPath || '') === sourceName) {
- const lineNum: number = parseInt(lineNumLiteral, 10);
- if (currentItem.uri) {
- if (!currentItem.range || (currentItem.range.start.line + 1 < lineNum && currentItem.range.end.line + 1 > lineNum)) {
- this.testMessageLocation = new Location(currentItem.uri, new Range(lineNum - 1, 0, lineNum, 0));
- } else {
- this.testMessageLocation = new Location(currentItem.uri, new Range(currentItem.range.start.line, 0, currentItem.range.start.line, 0));
- }
- }
- }
- }
- } else {
- // '<' & '>' will be escaped when displaying the test message, so replacing them to '[' & ']'.
- traces.appendText(data.replace(//g, ']'));
+ if (this.isExcluded(data)) {
+ return;
+ }
+
+ const location: Location | undefined = processStackTraceLine(data, traces, currentItem, projectName);
+ if (location) {
+ this.testMessageLocation = location;
}
- traces.appendMarkdown('
');
}
private isExcluded(stacktrace: string): boolean {
diff --git a/src/runners/utils.ts b/src/runners/utils.ts
index 80c1d36..dc0882e 100644
--- a/src/runners/utils.ts
+++ b/src/runners/utils.ts
@@ -1,10 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
-import { Location, TestItem, TestMessage, TestRun, Uri } from 'vscode';
+import { Location, MarkdownString, Range, TestItem, TestMessage, TestRun, Uri } from 'vscode';
import { JavaTestRunnerCommands } from '../constants';
import { asRange } from '../controller/utils';
import { executeJavaLanguageServerCommand } from '../utils/commandUtils';
+import * as path from 'path';
export async function findTestLocation(fullName: string): Promise {
const location: any | undefined = await executeJavaLanguageServerCommand(
@@ -52,3 +53,51 @@ export enum TestResultState {
// Test run failed for some other reason (compilation error, timeout, etc)
Errored = 6,
}
+
+/**
+ * Append the line of stack trace to the traces.
+ * @param lineOfMessage line of stack trace.
+ * @param traces stack trace in markdown string.
+ * @param currentItem current test item.
+ * @param projectName project name.
+ */
+export function processStackTraceLine(lineOfMessage: string, traces: MarkdownString, currentItem: TestItem | undefined, projectName: string): Location | undefined {
+ let testMessageLocation: Location | undefined;
+ const traceResults: RegExpExecArray | null = /(\s?at\s+)([\w$\\.]+\/)?((?:[\w$]+\.)+[<\w$>]+)\((.*)\)/.exec(lineOfMessage);
+ if (traceResults) {
+ const fullyQualifiedName: string = traceResults[3];
+ const location: string = traceResults[4];
+ let sourceName: string | undefined;
+ let lineNumLiteral: string | undefined;
+ const locationResult: RegExpExecArray | null = /([\w-$]+\.java):(\d+)/.exec(location);
+ if (locationResult) {
+ sourceName = locationResult[1];
+ lineNumLiteral = locationResult[2];
+ }
+
+ if (!sourceName || !lineNumLiteral) {
+ traces.appendText(lineOfMessage);
+ } else {
+ const atLiteral: string = traceResults[1];
+ const optionalModuleName: string = traceResults[2] || '';
+ traces.appendText(atLiteral);
+ traces.appendMarkdown(`${optionalModuleName + fullyQualifiedName}([${sourceName}:${lineNumLiteral}](command:_java.test.openStackTrace?${encodeURIComponent(JSON.stringify([lineOfMessage, projectName]))}))`);
+ if (currentItem && path.basename(currentItem.uri?.fsPath || '') === sourceName) {
+ const lineNum: number = parseInt(lineNumLiteral, 10);
+ if (currentItem.uri) {
+ if (!currentItem.range || (currentItem.range.start.line + 1 < lineNum && currentItem.range.end.line + 1 > lineNum)) {
+ testMessageLocation = new Location(currentItem.uri, new Range(lineNum - 1, 0, lineNum, 0));
+ } else {
+ testMessageLocation = new Location(currentItem.uri, new Range(currentItem.range.start.line, 0, currentItem.range.start.line, 0));
+ }
+ }
+ }
+ }
+ } else {
+ // '<' & '>' will be escaped when displaying the test message, so replacing them to '[' & ']'.
+ traces.appendText(lineOfMessage.replace(//g, ']'));
+ }
+ traces.appendMarkdown('
');
+
+ return testMessageLocation
+}