in src/diagnostics/cmake.ts [79:167]
private _parseDiags(line: string) {
// This line of output terminates an `AUTHOR_WARNING`
const dev_warning_re = /^This warning is for project developers\./;
// Switch on the state to implement our crude FSM
switch (this._errorState.state) {
case 'init': {
const re = /CMake (.*?)(?: \(dev\))? at (.*?):(\d+) \((.*?)\):/;
const result = re.exec(line);
if (result) {
// We have encountered and error
const [full, level, filename, linestr, command] = result;
const lineno = oneLess(linestr);
const diagmap: { [k: string]: vscode.DiagnosticSeverity } = {
Warning: vscode.DiagnosticSeverity.Warning,
Error: vscode.DiagnosticSeverity.Error
};
const vsdiag = new vscode.Diagnostic(new vscode.Range(lineno, 0, lineno, 9999), full, diagmap[level]);
vsdiag.source = `CMake (${command})`;
vsdiag.relatedInformation = [];
const filepath = util.resolvePath(filename, this.sourceDir);
this._errorState.diag = {
filepath,
diag: vsdiag
};
this._errorState.state = 'diag';
this._errorState.blankLines = 0;
}
break;
}
case 'diag': {
console.assert(this._errorState.diag, 'No diagnostic?');
const call_stack_re = /^Call Stack \(most recent call first\):$/;
if (call_stack_re.test(line)) {
// We're in call stack mode!
this._errorState.state = 'stack';
this._errorState.blankLines = 0;
break;
}
if (line === '') {
// A blank line!
if (this._errorState.blankLines === 0) {
// First blank. Okay
this._errorState.blankLines++;
this._errorState.diag!.diag.message += '\n';
} else {
// Second blank line. Now we commit the diagnostic.
this._commitDiag();
}
} else if (dev_warning_re.test(line)) {
this._commitDiag();
} else {
// Reset blank line count
this._errorState.blankLines = 0;
// Add this line to the current diag accumulator
const trimmed = line.replace(/^ /, '');
this._errorState.diag!.diag.message += trimmed + '\n';
}
break;
}
case 'stack': {
// Meh... vscode doesn't really let us provide call stacks to diagnostics.
// We can't really do anything...
if (line.trim() === '') {
if (this._errorState.blankLines === 1) {
this._commitDiag();
} else {
this._errorState.blankLines++;
}
} else if (dev_warning_re.test(line)) {
this._commitDiag();
} else {
const stackElemRe = /^ (.*):(\d+) \((\w+)\)$/;
const mat = stackElemRe.exec(line);
if (mat) {
const [, filepath, lineNoStr, command] = mat;
const fileUri = vscode.Uri.file(util.resolvePath(filepath, this.sourceDir));
const lineNo = parseInt(lineNoStr) - 1;
const related = new vscode.DiagnosticRelatedInformation(
new vscode.Location(fileUri, new vscode.Range(lineNo, 0, lineNo, 999)),
`In call to '${command}' here`
);
console.assert(this._errorState.diag);
this._errorState.diag!.diag.relatedInformation!.push(related);
}
}
break;
}
}
}