private _parseDiags()

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;
            }
        }
    }