| // Copyright 2025 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import path from 'path'; |
| import * as vscode from 'vscode'; |
| |
| const buildSeverity: Record<string, vscode.DiagnosticSeverity> = { |
| 'error': vscode.DiagnosticSeverity.Error, |
| 'warn': vscode.DiagnosticSeverity.Warning, |
| 'note': vscode.DiagnosticSeverity.Information |
| }; |
| |
| /** |
| * Diagnostic Collection Class |
| * Checks for C++ and Rust build syntax errors from Fuchsia builds and routes |
| * to the extension's problem matcher. |
| * |
| * Python and GN are not included since the recommended language server extensions |
| * handle these cases. |
| */ |
| export class FuchsiaDiagnostics { |
| private collection = vscode.languages.createDiagnosticCollection('fuchsia'); |
| private entries: Array<[vscode.Uri, vscode.Diagnostic[]]> = []; |
| private fileSet: Set<string> = new Set(); |
| private fuchsiaProblemMatcher: any; |
| |
| constructor(packageJSON: any) { |
| this.fuchsiaProblemMatcher = packageJSON.contributes.problemMatchers; |
| } |
| |
| /** |
| * Matches message and adds to diagnostics collection |
| * @param msg Message to match to problem matcher |
| */ |
| match(msg: string) { |
| const matcher = this.fuchsiaProblemMatcher.find( |
| (item: { name: string; }) => item.name === 'cpp-rust-build'); |
| const pattern = new RegExp(matcher!.pattern.regexp, 'g'); |
| const matches = msg.matchAll(pattern); |
| |
| // Assumes in fuchsia directory |
| const workspaceFolder = vscode.workspace.workspaceFolders; |
| if (!workspaceFolder) { |
| return; |
| } |
| const workspacePath = workspaceFolder[0].uri.fsPath; |
| |
| // Prevent duplicates of matches |
| for (const match of matches) { |
| if (this.fileSet.has(match[0])) { |
| continue; |
| } |
| this.fileSet.add(match[0]); |
| const fullPath = path.join(workspacePath, match[matcher!.pattern.file]); |
| this.entries.push([vscode.Uri.file(fullPath), [{ |
| message: match[matcher!.pattern.message], |
| range: new vscode.Range( |
| new vscode.Position(parseInt(match[matcher!.pattern.line]) - 1, |
| parseInt(match[matcher!.pattern.column]) - 1), |
| new vscode.Position(parseInt(match[matcher!.pattern.line]) - 1, |
| parseInt(match[matcher!.pattern.column]) - 1)), |
| severity: buildSeverity[match[matcher!.pattern.severity]] |
| }]]); |
| } |
| this.collection.set(this.entries); |
| } |
| |
| /** |
| * Clear the collection |
| */ |
| clear() { |
| this.entries = []; |
| this.fileSet.clear(); |
| this.collection.clear(); |
| } |
| |
| /** |
| * Returns current list of matches for a uri resource |
| * @returns |
| */ |
| get(): Array<[vscode.Uri, vscode.Diagnostic[]]> { |
| let collection: Array<[vscode.Uri, vscode.Diagnostic[]]> = []; |
| this.entries.forEach((entry) => { |
| console.log(entry[0]); |
| let uri = entry[0]; |
| let getDiagnostics = this.collection.get(uri); |
| if (getDiagnostics) { |
| collection.push([uri, [...getDiagnostics]]); |
| } |
| }); |
| return collection; |
| } |
| } |