Add error message when interpretation fails

One way it can fail is if the SARIF is too large. We explicitly call
out that error because the raw message received from the node runtime
is not very understandable.
This commit is contained in:
Andrew Eisenberg
2021-03-02 11:45:49 -08:00
parent 9e68b4f061
commit 6e40478440
3 changed files with 66 additions and 55 deletions

View File

@@ -4,6 +4,7 @@
- Respect the `codeQL.runningQueries.numberOfThreads` setting when creating SARIF files during result interpretation. [#771](https://github.com/github/vscode-codeql/pull/771) - Respect the `codeQL.runningQueries.numberOfThreads` setting when creating SARIF files during result interpretation. [#771](https://github.com/github/vscode-codeql/pull/771)
- Allow using raw LGTM project slugs for fetching LGTM databases. [#769](https://github.com/github/vscode-codeql/pull/769) - Allow using raw LGTM project slugs for fetching LGTM databases. [#769](https://github.com/github/vscode-codeql/pull/769)
- Better error messages when BQRS interpretation fails to produce SARIF. [#770](https://github.com/github/vscode-codeql/pull/770)
## 1.4.3 - 22 February 2021 ## 1.4.3 - 22 February 2021

View File

@@ -609,8 +609,12 @@ export class CodeQLCliServer implements Disposable {
let output: string; let output: string;
try { try {
output = await fs.readFile(interpretedResultsPath, 'utf8'); output = await fs.readFile(interpretedResultsPath, 'utf8');
} catch (err) { } catch (e) {
throw new Error(`Reading output of interpretation failed: ${err.stderr || err}`); const rawMessage = e.stderr || e.message;
const errorMessage = rawMessage.startsWith('Cannot create a string')
? `SARIF too large. ${rawMessage}`
: rawMessage;
throw new Error(`Reading output of interpretation failed: ${errorMessage}`);
} }
try { try {
return JSON.parse(output) as sarif.Log; return JSON.parse(output) as sarif.Log;

View File

@@ -236,61 +236,67 @@ export class InterfaceManager extends DisposableObject {
} }
private async handleMsgFromView(msg: FromResultsViewMsg): Promise<void> { private async handleMsgFromView(msg: FromResultsViewMsg): Promise<void> {
switch (msg.t) { try {
case 'viewSourceFile': { switch (msg.t) {
await jumpToLocation(msg, this.databaseManager, this.logger); case 'viewSourceFile': {
break; await jumpToLocation(msg, this.databaseManager, this.logger);
} break;
case 'toggleDiagnostics': { }
if (msg.visible) { case 'toggleDiagnostics': {
const databaseItem = this.databaseManager.findDatabaseItem( if (msg.visible) {
Uri.parse(msg.databaseUri) const databaseItem = this.databaseManager.findDatabaseItem(
); Uri.parse(msg.databaseUri)
if (databaseItem !== undefined) { );
await this.showResultsAsDiagnostics( if (databaseItem !== undefined) {
msg.origResultsPaths, await this.showResultsAsDiagnostics(
msg.metadata, msg.origResultsPaths,
databaseItem msg.metadata,
databaseItem
);
}
} else {
// TODO: Only clear diagnostics on the same database.
this._diagnosticCollection.clear();
}
break;
}
case 'resultViewLoaded':
this._panelLoaded = true;
this._panelLoadedCallBacks.forEach((cb) => cb());
this._panelLoadedCallBacks = [];
break;
case 'changeSort':
await this.changeRawSortState(msg.resultSetName, msg.sortState);
break;
case 'changeInterpretedSort':
await this.changeInterpretedSortState(msg.sortState);
break;
case 'changePage':
if (msg.selectedTable === ALERTS_TABLE_NAME) {
await this.showPageOfInterpretedResults(msg.pageNumber);
}
else {
await this.showPageOfRawResults(
msg.selectedTable,
msg.pageNumber,
// When we are in an unsorted state, we guarantee that
// sortedResultsInfo doesn't have an entry for the current
// result set. Use this to determine whether or not we use
// the sorted bqrs file.
this._displayedQuery?.sortedResultsInfo.has(msg.selectedTable) || false
); );
} }
} else { break;
// TODO: Only clear diagnostics on the same database. case 'openFile':
this._diagnosticCollection.clear(); await this.openFile(msg.filePath);
} break;
break; default:
assertNever(msg);
} }
case 'resultViewLoaded': } catch (e) {
this._panelLoaded = true; showAndLogErrorMessage(e.message, {
this._panelLoadedCallBacks.forEach((cb) => cb()); fullMessage: e.stack
this._panelLoadedCallBacks = []; });
break;
case 'changeSort':
await this.changeRawSortState(msg.resultSetName, msg.sortState);
break;
case 'changeInterpretedSort':
await this.changeInterpretedSortState(msg.sortState);
break;
case 'changePage':
if (msg.selectedTable === ALERTS_TABLE_NAME) {
await this.showPageOfInterpretedResults(msg.pageNumber);
}
else {
await this.showPageOfRawResults(
msg.selectedTable,
msg.pageNumber,
// When we are in an unsorted state, we guarantee that
// sortedResultsInfo doesn't have an entry for the current
// result set. Use this to determine whether or not we use
// the sorted bqrs file.
this._displayedQuery?.sortedResultsInfo.has(msg.selectedTable) || false
);
}
break;
case 'openFile':
await this.openFile(msg.filePath);
break;
default:
assertNever(msg);
} }
} }
@@ -626,7 +632,7 @@ export class InterfaceManager extends DisposableObject {
} catch (e) { } catch (e) {
// If interpretation fails, accept the error and continue // If interpretation fails, accept the error and continue
// trying to render uninterpreted results anyway. // trying to render uninterpreted results anyway.
this.logger.log( showAndLogErrorMessage(
`Exception during results interpretation: ${e.message}. Will show raw results instead.` `Exception during results interpretation: ${e.message}. Will show raw results instead.`
); );
} }