diff --git a/src/services/DhService.ts b/src/services/DhService.ts index d4d5138b..6b06e95e 100644 --- a/src/services/DhService.ts +++ b/src/services/DhService.ts @@ -263,18 +263,25 @@ export abstract class DhService if (line != null) { // If selectionOnly is true, the line number in the error will be - // relative to the selection - const offsetLine = selectionOnly - ? line + editor.selection.start.line - 1 - : line - 1; + // relative to the selection (Python line numbers are 1 based. vscode + // line numbers are zero based.) + const fileLine = + (selectionOnly ? line + editor.selection.start.line : line) - 1; - const lineLength = editor.document.lineAt(offsetLine).text.length; + // There seems to be an error for certain Python versions where line + // numbers are shown as -1. In such cases, we'll just mark the first + // token on the first line to at least flag the file as having an error. + const startLine = Math.max(0, fileLine); + + // Zero length will flag a token instead of a line + const lineLength = + fileLine < 0 ? 0 : editor.document.lineAt(fileLine).text.length; // Diagnostic representing the line of code that produced the server error const diagnostic: vscode.Diagnostic = { message: value == null ? error : `${value}\n${error}`, severity: vscode.DiagnosticSeverity.Error, - range: new vscode.Range(offsetLine, 0, offsetLine, lineLength), + range: new vscode.Range(startLine, 0, startLine, lineLength), source: 'deephaven', }; diff --git a/src/util/errorUtils.ts b/src/util/errorUtils.ts index 456fbf9d..07d98de5 100644 --- a/src/util/errorUtils.ts +++ b/src/util/errorUtils.ts @@ -30,7 +30,7 @@ export function parseServerError(error: string): ParsedError { const [key, value] = line.split(':'); - if (key && value) { + if (key.length) { // Once we hit the Traceback, accumulate remaining lines if (key === 'Traceback (most recent call last)') { errorDetails.traceback = [value, ...lines].join('\n'); @@ -42,5 +42,17 @@ export function parseServerError(error: string): ParsedError { } } + // If top-level error isn't associated with File: "", look for the + // first match in the traceback. + if (errorDetails.file !== '' && errorDetails.traceback != null) { + const fileStringRegEx = /\s+File "", line (\d+), in /; + const [, lineNumberStr] = + fileStringRegEx.exec(errorDetails.traceback) ?? []; + + if (lineNumberStr != null) { + errorDetails.line = Number(lineNumberStr); + } + } + return errorDetails; }