diff --git a/package.json b/package.json index 7ce024f..b76732e 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ { "command": "edk2code.getItemTreePath", - "title": "Get tree path" + "title": "Copy tree node path" }, { "command": "edk2code.focusOnNode", @@ -168,7 +168,7 @@ "edk2code.enableDiagnostics": { "order": 2, "type": "boolean", - "markdownDescription": "Experimental diagnostics for EDK2", + "markdownDescription": "Experimental diagnostics for EDK2. It will show EDK2 errors in Vs Code Problem window", "default": true }, "edk2code.useEdkCallHierarchy": { diff --git a/src/Languages/buildFolder.ts b/src/Languages/buildFolder.ts index adda1cb..1216d5c 100644 --- a/src/Languages/buildFolder.ts +++ b/src/Languages/buildFolder.ts @@ -2,12 +2,15 @@ import path = require("path"); import * as vscode from 'vscode'; import * as fs from 'fs'; import { gCscope, gDebugLog, gWorkspacePath } from "../extension"; -import { getRealPath, getRealPathRelative, normalizePath, readLines, split, toPosix } from "../utils"; +import { getRealPath, getRealPathRelative, isWorkspacePath, normalizePath, readLines, split, toPosix } from "../utils"; import glob = require("fast-glob"); import { writeEdkCodeFolderFile } from "../edk2CodeFolder"; +import { isFixWorkspacePath } from "../ui/messages"; export class BuildFolder { buildFolderPaths: string[]=[]; + replaceWorkspacePath: string|undefined; + constructor(folderPath: string[]) { this.buildFolderPaths = folderPath; } @@ -47,6 +50,32 @@ export class BuildFolder { if (l.startsWith("Active Platform: ")) { let buildActivePlatform: string = split(l, ":", 2)[1].trim(); + gDebugLog.info(`Active platform: ${buildActivePlatform}`); + if(!fs.existsSync(buildActivePlatform) && !isWorkspacePath(buildActivePlatform)){ + gDebugLog.warning(`Active platform Build "${buildActivePlatform}" is not in current Vscode workspace folder "${gWorkspacePath}"`); + if(await isFixWorkspacePath(buildActivePlatform, gWorkspacePath)){ + const oldWorkspacePath = this.findBuildWorkspacePath(buildActivePlatform); + if (oldWorkspacePath) { + + const newBuildActivePlatform = path.normalize(buildActivePlatform).replace(oldWorkspacePath, gWorkspacePath); + if (fs.existsSync(newBuildActivePlatform)) { + buildActivePlatform = newBuildActivePlatform; + gDebugLog.verbose(`Corrected Active platform: ${buildActivePlatform}`); + if(this.replaceWorkspacePath !== undefined && this.replaceWorkspacePath !== oldWorkspacePath){ + gDebugLog.error(`Multiple original workspace paths found: ${this.replaceWorkspacePath} and ${oldWorkspacePath}`); + } + this.replaceWorkspacePath = oldWorkspacePath; + } else { + gDebugLog.error(`Active build platform not found: ${newBuildActivePlatform}`); + } + + } else{ + gDebugLog.warning(`Old workspace path not found for: ${buildActivePlatform}`); + } + } + } + + buildActivePlatform = getRealPathRelative(buildActivePlatform); gDebugLog.verbose(`Active platform: ${buildActivePlatform}`); dscFiles.add(buildActivePlatform); @@ -61,6 +90,21 @@ export class BuildFolder { } } + findBuildWorkspacePath(wrongPath:string){ + const wrongPathParts = wrongPath.split(/[\\/]/); + let oldPathWorkspace = []; + while(wrongPathParts.length > 0){ + const testPath = path.join(gWorkspacePath, ...wrongPathParts); + if(fs.existsSync(testPath)){ + return oldPathWorkspace.join(path.sep); + } + const part = wrongPathParts.shift(); + oldPathWorkspace.push(part); + gDebugLog.verbose(`Removed part: ${part}`); + } + return undefined; + } + async copyMapFilesList(){ let maplist = []; for (const buildPaths of this.buildFolderPaths) { @@ -72,7 +116,14 @@ export class BuildFolder { writeEdkCodeFolderFile("mapFiles.json",JSON.stringify(maplist, null, 2)); } - copyFilesToRoot() { + replaceOldWorkspacePath(p:string){ + if(this.replaceWorkspacePath !== undefined){ + return path.normalize(p).replace(this.replaceWorkspacePath, gWorkspacePath); + } + return p; + } + + copyCompileInfoToRoot() { let cscopeMap = new Map(); let moduleReport = []; let compileCommands:string[] = []; @@ -87,19 +138,31 @@ export class BuildFolder { let cscopeLines = readLines(path.join(folder, "CompileInfo", "cscope.files")); for (const l of cscopeLines) { - cscopeMap.set(l.toUpperCase(), l); + cscopeMap.set(l.toUpperCase(), this.replaceOldWorkspacePath(l)); + } + + + let compileInfoText = fs.readFileSync(path.join(folder, "CompileInfo", "compile_commands.json")).toString(); + let modulesText = fs.readFileSync(path.join(folder, "CompileInfo", "module_report.json")).toString(); + + if(this.replaceWorkspacePath!==undefined){ + // make path json compatible + const jsonReplacePath = this.replaceWorkspacePath.replaceAll(/\\/g, "\\\\").replaceAll("/", "\\/"); + const jsonWorkspacePath = gWorkspacePath.replaceAll(/\\/g, "\\\\").replaceAll("/", "\\/"); + compileInfoText = compileInfoText.replaceAll(jsonReplacePath, jsonWorkspacePath); + modulesText = modulesText.replaceAll(jsonReplacePath, jsonWorkspacePath); } - let commands = JSON.parse(fs.readFileSync(path.join(folder, "CompileInfo", "compile_commands.json")).toString()); + let commands = JSON.parse(compileInfoText); // Merge compile commands for (const cmd of commands) { - compileCommands.push(cmd); + compileCommands.push(cmd); } - let modules = JSON.parse(fs.readFileSync(path.join(folder, "CompileInfo", "module_report.json")).toString()); // Merge build report + let modules = JSON.parse(modulesText); for (const mod of modules) { - moduleReport.push(mod); + moduleReport.push(mod); } } let filteredCscope = []; diff --git a/src/Languages/symbolProvider.ts b/src/Languages/symbolProvider.ts index 4d26ac9..3b4cd13 100644 --- a/src/Languages/symbolProvider.ts +++ b/src/Languages/symbolProvider.ts @@ -4,53 +4,44 @@ import { getStaticPath, itsPcdSelected } from '../utils'; import path = require('path'); import { CompletionItemKind } from 'vscode'; import { ParserFactory } from '../edkParser/parserFactory'; -import { gConfigAgent, gEdkWorkspaces } from '../extension'; +import { gConfigAgent, gEdkWorkspaces, gGrayOutController } from '../extension'; import { Debouncer } from '../debouncer'; export class EdkSymbolProvider implements vscode.DocumentSymbolProvider { - private _idUpdateNeeded: boolean = true; constructor() { - vscode.workspace.onDidChangeTextDocument(this.setFlag, this); + vscode.workspace.onDidSaveTextDocument(this.updateEdkWorkspace, this); + } - private setFlag(event: vscode.TextDocumentChangeEvent) { - const languageIds = ["edk2_dsc", "edk2_inf", "edk2_dec", "edk2_fdf"]; - if (languageIds.includes(event.document.languageId)) { - this._idUpdateNeeded = true; - } + private async updateEdkWorkspace(document: vscode.TextDocument) { + if (document.languageId === 'edk2_dsc' || document.languageId === 'edk2_fdf') { + // create document from dscPath + let wp = await gEdkWorkspaces.getWorkspace(document.uri); + if(wp.length){ + + const debouncer = Debouncer.getInstance(); + debouncer.debounce("updateDocumentSymbols",async () => { + await wp[0].proccessWorkspace(); + }, gConfigAgent.getDelayToRefreshWorkspace()); + + if (document.languageId === 'edk2_fdf') { + await wp[0].fdfPostProcces(document); + } + } + } + } public async provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken) { // Create a parser for the document let factory = new ParserFactory(); - let parser = factory.getParser(document); if (parser) { await parser.parseFile(); - - if (document.languageId === 'edk2_dsc' || document.languageId === 'edk2_fdf') { - // create document from dscPath - let wp = await gEdkWorkspaces.getWorkspace(document.uri); - if(wp.length){ - // By defautl use the first workspace to parse the dsc file - if(this._idUpdateNeeded){ - const debouncer = Debouncer.getInstance(); - debouncer.debounce("updateDocumentSymbols",async () => { - await wp[0].proccessWorkspace(); - this._idUpdateNeeded = false; - }, gConfigAgent.getDelayToRefreshWorkspace()); - } - if (document.languageId === 'edk2_fdf') { - await wp[0].fdfPostProcces(document); - }else{ - await wp[0].grayoutDocument(document); - } - } - } return parser.symbolsTree; } return []; diff --git a/src/configuration.ts b/src/configuration.ts index 5f4a062..c7c59d6 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -262,7 +262,6 @@ export class ConfigAgent { } getDelayToRefreshWorkspace() { - console.log(this.get("delayToRefreshWorkspace")); return this.get("delayToRefreshWorkspace"); } diff --git a/src/contextState/cmds.ts b/src/contextState/cmds.ts index 32df2a2..5884209 100644 --- a/src/contextState/cmds.ts +++ b/src/contextState/cmds.ts @@ -18,7 +18,7 @@ import { InfParser } from "../edkParser/infParser"; import { EdkSymbolInfLibrary } from "../symbols/infSymbols"; import { debuglog } from "util"; import { deleteEdkCodeFolder, existsEdkCodeFolderFile } from "../edk2CodeFolder"; -import { EdkInfNode } from "../treeElements/Library"; +import { EdkInfNode, EdkInfNodeLibrary } from "../treeElements/Library"; import { TreeItem } from "../treeElements/TreeItem"; import { EdkModule, ModuleReport } from "../moduleReport"; import { infoMissingCompileInfo } from "../ui/messages"; @@ -104,7 +104,7 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; gConfigAgent.clearWpConfiguration(); await gConfigAgent.setBuildDefines(buildData.buildDefines); await gConfigAgent.setBuildDscPaths(buildData.dscFiles); - buildFolder.copyFilesToRoot(); + buildFolder.copyCompileInfoToRoot(); // If cscope.file is not generated, then calculate files based on dsc parsing if(existsEdkCodeFolderFile(".missing")){ @@ -356,6 +356,7 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; export async function showEdkMap(moduleUri:vscode.Uri) { let parser = await getParser(moduleUri); let contextModule = moduleUri; + let contextSelected = false; if(parser && (parser instanceof InfParser) ){ // Check if INF file is a library if(parser.isLibrary()){ @@ -384,6 +385,7 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; return; } contextModule = vscode.Uri.file(selectedOption.module.path); + contextSelected = true; }else{ @@ -416,7 +418,13 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; const sectionRange = libraries[0].parent?.range.start; if(sectionRange===undefined){continue;} let librarySet = new Set(); - let moduleNode = new EdkInfNode(moduleUri, contextModule, sectionRange, wp, libraries[0].parent!, librarySet); + let moduleNode; + if(parser.isLibrary()){ + moduleNode = new EdkInfNodeLibrary(moduleUri, contextModule, sectionRange, wp, libraries[0].parent!, librarySet); + }else{ + + moduleNode = new EdkInfNode(moduleUri, contextModule, sectionRange, wp, libraries[0].parent!, librarySet); + } edkLensTreeDetailProvider.addChildren(moduleNode); @@ -609,7 +617,7 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; } } } catch (error) { - gDebugLog.error(String(error)); + gDebugLog.error(`reloadSymbols: ${error}`); } } @@ -665,10 +673,7 @@ import { checkCppConfiguration } from "../cppProviders/cppUtils"; } let posixWorkspacePath = toPosix(gWorkspacePath); - gDebugLog.debug(Array.from(filesSet).toString()); - gDebugLog.debug("####################"); - gDebugLog.debug(Array.from(globFilesList).toString()); - + gDebugLog.info(`Cscope files found: ${filesSet.size}`); for (const globFile of globFilesList) { // Just ignore EDK files diff --git a/src/cppProviders/msCpp.ts b/src/cppProviders/msCpp.ts index ce1ad2e..97fcda4 100644 --- a/src/cppProviders/msCpp.ts +++ b/src/cppProviders/msCpp.ts @@ -72,7 +72,7 @@ export class MsCppProvider extends CppProvider { } } catch (error) { - gDebugLog.error(String(error)); + gDebugLog.error(`Error fixing c_cpp_properties.json: ${error}`); } return true; } diff --git a/src/debouncer.ts b/src/debouncer.ts index 2860c45..9dc5dc7 100644 --- a/src/debouncer.ts +++ b/src/debouncer.ts @@ -27,8 +27,3 @@ export class Debouncer { } } -// Usage -const debouncer = Debouncer.getInstance(); -debouncer.debounce('log', () => { - console.log("Function executed after debounce delay"); -}, 300); diff --git a/src/debugLog.ts b/src/debugLog.ts index f2524ec..846a366 100644 --- a/src/debugLog.ts +++ b/src/debugLog.ts @@ -27,23 +27,25 @@ export class DebugLog { } public error(text:string){ - this.out(`Error: ${text}`, LogLevel.error); + this.out(`[Edk2Code Error] ${text}`, LogLevel.error); + let callStack = (new Error()).stack || ''; + this.out(`[Edk2Code Stack]\n${callStack}`, LogLevel.error); } public info(text:string){ - this.out(`Info: ${text}`, LogLevel.info); + this.out(`[Edk2Code Info] ${text}`, LogLevel.info); } public verbose(text:string){ - this.out(`Verb: ${text}`, LogLevel.verbose); + this.out(`[Edk2Code Verb] ${text}`, LogLevel.verbose); } public warning(text:string){ - this.out(`Warn: ${text}`, LogLevel.warning); + this.out(`[Edk2Code Warn] ${text}`, LogLevel.warning); } public debug(text:string){ - this.out(`Debug: ${text}`, LogLevel.debug); + this.out(`[Edk2Code Debug] ${text}`, LogLevel.debug); } diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 5ea86f6..be2186a 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -133,6 +133,7 @@ export class DiagnosticManager { { if(gConfigAgent.isDiagnostics() === false){ + this.clearAllProblems(); return undefined; } diff --git a/src/edk2CodeFolder.ts b/src/edk2CodeFolder.ts index df05721..d0914ad 100644 --- a/src/edk2CodeFolder.ts +++ b/src/edk2CodeFolder.ts @@ -53,7 +53,7 @@ export function deleteEdkCodeFolder() { try { fs.rmSync(p, { recursive: true, force: true }); } catch (error: any) { - gDebugLog.error(error); + gDebugLog.error(`deleteEdkCodeFolder: ${error}`); } createEdkCodeFolder(); } diff --git a/src/edkParser/languageParser.ts b/src/edkParser/languageParser.ts index 442ccd2..29c0ab5 100644 --- a/src/edkParser/languageParser.ts +++ b/src/edkParser/languageParser.ts @@ -54,7 +54,7 @@ export abstract class BlockParser { const line = docParser.getLineAt(currentIndex); if (!line) { - gDebugLog.error("Wrong line"); + gDebugLog.error(`Wrong line: ${currentIndex} at ${docParser.document.fileName}`); return; } diff --git a/src/grayout.ts b/src/grayout.ts index bca982c..8c24de1 100644 --- a/src/grayout.ts +++ b/src/grayout.ts @@ -1,39 +1,41 @@ import * as vscode from 'vscode'; import { getCurrentDocument } from './utils'; +import { gDebugLog } from './extension'; export class GrayoutController { decoration:vscode.TextEditorDecorationType|undefined; document:vscode.TextDocument; range:vscode.Range[]; + changeEvent:vscode.Disposable; + public constructor(document:vscode.TextDocument, range:vscode.Range[]) { this.document = document; this.range = range; // let subscriptions: vscode.Disposable[] = []; - // vscode.window.onDidChangeActiveTextEditor(this.doGrayOut, this, subscriptions); - // vscode.workspace.onDidSaveTextDocument(this.doGrayOut, this, subscriptions); + this.changeEvent = vscode.window.onDidChangeActiveTextEditor(()=>{ + if(vscode.window.activeTextEditor?.document.uri.fsPath === this.document.uri.fsPath){ + this.doGrayOut(); + } + }, this); } - clearDecorator(){ - - } grayoutRange(unusdedRanges:vscode.Range[]) { - + gDebugLog.verbose("grayoutRange()"); let activeEditor = vscode.window.activeTextEditor; if(!activeEditor){return;} if(activeEditor.document !== this.document){return;} - if(this.decoration){ - this.decoration.dispose(); - } - + gDebugLog.verbose(`Unused Ranges: ${JSON.stringify(unusdedRanges)}`); + this.disposeDecoration(); + let decoration = vscode.window.createTextEditorDecorationType({ isWholeLine: true, light: { @@ -59,8 +61,23 @@ export class GrayoutController { } + + dispose(){ + this.disposeDecoration(); + this.changeEvent?.dispose(); + } + + disposeDecoration(){ + if(this.decoration){ + this.decoration.dispose(); + } + } + doGrayOut(){ - this.grayoutRange(this.range); + if (vscode.window.visibleTextEditors.some(editor => editor.document.uri.fsPath === this.document.uri.fsPath)) { + gDebugLog.info(`doGrayOut(): ${this.document.uri.fsPath}`); + this.grayoutRange(this.range); + } } } \ No newline at end of file diff --git a/src/index/edkWorkspace.ts b/src/index/edkWorkspace.ts index 55df721..5e665cd 100644 --- a/src/index/edkWorkspace.ts +++ b/src/index/edkWorkspace.ts @@ -315,7 +315,6 @@ export class EdkWorkspace { definesFdf: WorkspaceDefinitions = new WorkspaceDefinitions(); private pcdDefinitions: Map> = new Map(); - private grayoutControllers:Map; private libraryTypeTrack = new Map(); private _filesLibraries: InfDsc[] = []; @@ -333,13 +332,14 @@ export class EdkWorkspace { this._filesModules = value; } private _filesDsc: vscode.TextDocument[] = []; + private _filesFdf: vscode.TextDocument[] = []; + public get filesDsc(): vscode.TextDocument[] { return this._filesDsc; } public set filesDsc(value: vscode.TextDocument[]) { this._filesDsc = value; } - private _filesFdf: vscode.TextDocument[] = []; public get filesFdf(): vscode.TextDocument[] { return this._filesFdf; } @@ -347,6 +347,23 @@ export class EdkWorkspace { this._filesFdf = value; } + private _grayoutControllers:GrayoutController[] = []; + + public updateGrayoutRange(document: vscode.TextDocument, range: vscode.Range[]){ + for (const grayoutController of this._grayoutControllers) { + + if(grayoutController.document.uri.fsPath === document.uri.fsPath){ + grayoutController.range = range; + grayoutController.doGrayOut(); + return; + } + } + const dscGrayoutController = new GrayoutController(document, range); + dscGrayoutController.doGrayOut(); + this._grayoutControllers.push(dscGrayoutController); + + } + public dscList(){ return this.filesDsc.map(x=>x.uri.fsPath); } @@ -365,7 +382,6 @@ export class EdkWorkspace { this.mainDsc = document.uri; // generate random number this.id = Math.floor(Math.random() * 100000000000000); - this.grayoutControllers = new Map(); } @@ -386,6 +402,10 @@ export class EdkWorkspace { this.filesLibraries = []; this.filesModules = []; this.filesDsc = []; + for (const ctrl of this._grayoutControllers) { + ctrl.dispose(); + } + this._grayoutControllers = []; this.libraryTypeTrack = new Map(); @@ -400,7 +420,7 @@ export class EdkWorkspace { this.parsedDocuments = new Map(); let mainDscDocument = await vscode.workspace.openTextDocument(this.mainDsc); - await this._proccessDsc(mainDscDocument); + await this._processDocument(mainDscDocument, "DSC"); for (const conditionOpen of this.conditionOpen) { DiagnosticManager.error(conditionOpen.uri,conditionOpen.lineNo,EdkDiagnosticCodes.conditionalMissform, "Condition block not closed"); } @@ -515,63 +535,61 @@ export class EdkWorkspace { } - private async _proccessDsc(document: vscode.TextDocument) { + private async _processDocument(document: vscode.TextDocument, type: 'DSC' | 'FDF') { DiagnosticManager.clearProblems(document.uri); - gDebugLog.verbose(`_proccessDsc: ${document.fileName}`); - // Add document to inactiveLines + gDebugLog.verbose(`_process${type}: ${document.fileName}`); + if (this.isDocumentInIndex(document)) { - gDebugLog.warning(`_proccessDsc: ${document.fileName} already in inactiveLines`); + gDebugLog.warning(`_process${type}: ${document.fileName} already in inactiveLines`); return; } + let doucumentGrayoutRange = []; this.parsedDocuments.set(document.uri.fsPath, []); - this.filesDsc.push(document); + if (type === 'DSC') { + this.filesDsc.push(document); + } else { + this.filesFdf.push(document); + } let text = document.getText().split(/\r?\n/); let lineIndex = -1; - let isRangeActive = false; let unuseRangeStart = 0; - - gDebugLog.verbose(`# Parsing DSC Document: ${document.uri.fsPath}`); + gDebugLog.verbose(`# Parsing ${type} Document: ${document.uri.fsPath}`); for (let line of text) { - lineIndex++; gDebugLog.verbose(`\t\t${lineIndex}: ${line}`); - line = this.stripComment(line); - // Skip comments - if(line.length === 0){continue;} + if (line.length === 0){continue;} - - // Check PCDS - // find PCDS variables - if(line.match(REGEX_PCD_LINE)){ - let [fullPcd, pcdValue] = split(line,"|",2); + // PCDs + if (line.match(REGEX_PCD_LINE)) { + let [fullPcd, pcdValue] = split(line, "|", 2); pcdValue = pcdValue.split("|")[0].trim(); - if(pcdValue.startsWith('L"')){ + if (pcdValue.startsWith('L"')) { pcdValue = pcdValue.slice(1); } let [pcdNamespace, pcdName] = split(fullPcd, ".", 2); - if(!this.pcdDefinitions.has(pcdNamespace)){ + if (!this.pcdDefinitions.has(pcdNamespace)) { this.pcdDefinitions.set(pcdNamespace, new Map()); } this.pcdDefinitions.get(pcdNamespace)?.set( pcdName, { - name:pcdName, - value:pcdValue, - position: new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))} - ); + name: pcdName, + value: pcdValue, + position: new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)) + } + ); } - // replace definitions line = this.defines.replaceDefines(line); line = this.replacePcds(line); - let isInActiveCode = this.processConditional(line, lineIndex, document.uri); + if (!isInActiveCode) { if (!isRangeActive) { isRangeActive = true; @@ -580,31 +598,26 @@ export class EdkWorkspace { continue; } - - - - - if (isRangeActive === true) { + if (isRangeActive) { isRangeActive = false; - let arr = this.parsedDocuments.get(document.uri.fsPath); - if (arr) { - let lineIndexEnd = lineIndex-1; - arr.push(new vscode.Range(new vscode.Position(unuseRangeStart, 0), new vscode.Position(lineIndexEnd, 0))); - } else { - gDebugLog.error(`_proccessDsc: ${document.fileName} has no range for unuseRange`); - } + let lineIndexEnd = lineIndex - 1; + doucumentGrayoutRange.push(new vscode.Range(new vscode.Position(unuseRangeStart, 0), new vscode.Position(lineIndexEnd, 0))); } - let match = line.match(REGEX_DSC_SECTION); - if (match) { - const sectionType = match[0].split(".")[0]; - if(!dscSectionTypes.includes(sectionType.toLowerCase())){ - DiagnosticManager.warning(document.uri,lineIndex,EdkDiagnosticCodes.unknownSectionType, sectionType); + if (type === 'DSC') { + // Sections + let match = line.match(REGEX_DSC_SECTION); + if (match) { + const sectionType = match[0].split(".")[0]; + if (!dscSectionTypes.includes(sectionType.toLowerCase())) { + DiagnosticManager.warning(document.uri, lineIndex, EdkDiagnosticCodes.unknownSectionType, sectionType); + } + this.sectionsStack = [match[0]]; + continue; } - this.sectionsStack = [match[0]]; - continue; } + // Defines if (line.match(REGEX_DEFINE)) { let key = line.replace(/define/gi, "").trim(); key = split(key, "=", 2)[0].trim(); @@ -612,90 +625,87 @@ export class EdkWorkspace { if (value.includes(`$(${key})`)) { gDebugLog.info(`Circular define: ${key}: ${value}`); } else { - this.defines.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex,0))); + if (type === 'DSC') { + this.defines.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))); + } else { + this.definesFdf.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))); + } } continue; } + // Includes if (line.match(REGEX_INCLUDE)) { - let value = line.replace(/!include/gi, "").trim(); let location = await gPathFind.findPath(value, document.uri.fsPath); - - if(location.length > 0){ + if (location.length > 0) { let includedDocument = await openTextDocument(location[0].uri); - await this._proccessDsc(includedDocument); + if (type === 'DSC') { + await this._processDocument(includedDocument, 'DSC'); + } else { + this.filesFdf.push(includedDocument); + await this._processDocument(includedDocument, 'FDF'); + } } - - continue; } + if (type === 'DSC') { - - - // Libraries - match = line.match(REGEX_LIBRARY_PATH); - if (match) { - // get matched string - let filePath = match[0].trim(); - let results = await gPathFind.findPath(filePath, document.uri.fsPath); - if(results.length === 0){ - DiagnosticManager.error(document.uri,lineIndex,EdkDiagnosticCodes.missingPath, filePath); - } - let newLibDefinition = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[this.sectionsStack.length - 1], line); - const libName = newLibDefinition.text.split("|")[0].trim(); - const libNameTag = libName +" - "+newLibDefinition.getModuleTypeStr(); - - if(this.libraryTypeTrack.has(libNameTag) && (libName.toLocaleLowerCase() !== "null")){ - if(this.sectionsStack[this.sectionsStack.length-1].toLowerCase().endsWith(".inf")){ - // If parent its a module, the this is n overwrite so its ok. - continue; + // Libraries + let match = line.match(REGEX_LIBRARY_PATH); + if (match) { + let filePath = match[0].trim(); + let results = await gPathFind.findPath(filePath, document.uri.fsPath); + if (results.length === 0) { + DiagnosticManager.error(document.uri, lineIndex, EdkDiagnosticCodes.missingPath, filePath); } - - let previousLibDefinition = this.libraryTypeTrack.get(libNameTag)!; - DiagnosticManager.warning(previousLibDefinition.location.uri, previousLibDefinition.location.range.start.line, - EdkDiagnosticCodes.duplicateStatement, - `Library overwritten: ${libName}`, - [vscode.DiagnosticTag.Unnecessary], - [new vscode.DiagnosticRelatedInformation(newLibDefinition.location, "New definition")]); - - // Find and remove originalLibrary from this.filesLibraries - const index = this.filesLibraries.indexOf(previousLibDefinition); - if (index > -1) { - this.filesLibraries[index] = newLibDefinition; + let newLibDefinition = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[this.sectionsStack.length - 1], line); + const libName = newLibDefinition.text.split("|")[0].trim(); + const libNameTag = libName + " - " + newLibDefinition.getModuleTypeStr(); + if (this.libraryTypeTrack.has(libNameTag) && (libName.toLocaleLowerCase() !== "null") && newLibDefinition.parent === undefined) { + if (this.sectionsStack[this.sectionsStack.length - 1].toLowerCase().endsWith(".inf")) { + continue; + } + let previousLibDefinition = this.libraryTypeTrack.get(libNameTag)!; + DiagnosticManager.warning(previousLibDefinition.location.uri, previousLibDefinition.location.range.start.line, + EdkDiagnosticCodes.duplicateStatement, + `Library overwritten: ${libName}`, + [vscode.DiagnosticTag.Unnecessary], + [new vscode.DiagnosticRelatedInformation(newLibDefinition.location, "New definition")]); + const index = this.filesLibraries.indexOf(previousLibDefinition); + if (index > -1) { + this.filesLibraries[index] = newLibDefinition; + } + } else { + this.filesLibraries.push(newLibDefinition); } - }else{ - this.filesLibraries.push(newLibDefinition); + this.libraryTypeTrack.set(libNameTag, newLibDefinition); + continue; } - this.libraryTypeTrack.set(libNameTag,newLibDefinition); - continue; - } - - // Modules - match = line.match(REGEX_MODULE_PATH); - if (match) { - // get matched string - let filePath = match[0].trim(); - let results = await gPathFind.findPath(filePath, document.uri.fsPath); - if(results.length === 0){ - DiagnosticManager.error(document.uri,lineIndex,EdkDiagnosticCodes.missingPath, filePath); - } - let inf = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[0], line); - // If new module found. remove previous model from section stack - if(filePath.toLowerCase().endsWith(".inf")){ - if(this.sectionsStack[this.sectionsStack.length-1].toLowerCase().endsWith(".inf")){ - this.sectionsStack.pop(); + // Modules + match = line.match(REGEX_MODULE_PATH); + if (match) { + let filePath = match[0].trim(); + let results = await gPathFind.findPath(filePath, document.uri.fsPath); + if (results.length === 0) { + DiagnosticManager.error(document.uri, lineIndex, EdkDiagnosticCodes.missingPath, filePath); + } + let inf = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[0], line); + if (filePath.toLowerCase().endsWith(".inf")) { + if (this.sectionsStack[this.sectionsStack.length - 1].toLowerCase().endsWith(".inf")) { + this.sectionsStack.pop(); + } } + this.sectionsStack.push(filePath); + this.filesModules.push(inf); + continue; } - this.sectionsStack.push(filePath); - this.filesModules.push(inf); - continue; } - } + this.updateGrayoutRange(document, doucumentGrayoutRange); } private getLangId(uri:vscode.Uri){ @@ -870,7 +880,7 @@ export class EdkWorkspace { if (this.flashDefinitionDocument) { if (!this.isDocumentInIndex(this.flashDefinitionDocument)) { this.filesFdf = []; - await this._proccessFdf(this.flashDefinitionDocument); + await this._processDocument(this.flashDefinitionDocument,"FDF"); } } this.workInProgress = false; @@ -879,126 +889,8 @@ export class EdkWorkspace { } - // TODO: Unifiy this function with _proccessDsc - private async _proccessFdf(document: vscode.TextDocument) { - gDebugLog.verbose(`findDefines Fdf: ${document.fileName}`); - DiagnosticManager.clearProblems(document.uri); - // Add document to inactiveLines - if (this.isDocumentInIndex(document)) { - gDebugLog.warning(`findDefines Fdf: ${document.fileName} already in inactiveLines`); - return; - } - this.parsedDocuments.set(document.uri.fsPath, []); - this.filesFdf.push(document); - let text = document.getText().split(/\r?\n/); - let lineIndex = -1; - - let isRangeActive = false; - let unuseRangeStart = 0; - for (let line of text) { - lineIndex++; - line = this.stripComment(line); - - // Skip comments - if(line.startsWith("#")){continue;} - - - // find PCDS variables - if(line.match(REGEX_PCD_LINE)){ - let [fullPcd, pcdValue] = split(line,"|",2); - pcdValue = pcdValue.split("|")[0].trim(); - if(pcdValue.startsWith('L"')){ - pcdValue = pcdValue.slice(1); - } - let [pcdNamespace, pcdName] = split(fullPcd, ".", 2); - if(!this.pcdDefinitions.has(pcdNamespace)){ - this.pcdDefinitions.set(pcdNamespace, new Map()); - } - this.pcdDefinitions.get(pcdNamespace)?.set( - pcdName, - { - name:pcdName, - value:pcdValue, - position: new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))} - ); - - } - - // replace definitions - line = this.defines.replaceDefines(line); - line = this.replacePcds(line); - - let isInActiveCode = this.processConditional(line, lineIndex, document.uri); - - - if (!isInActiveCode) { - if (!isRangeActive) { - isRangeActive = true; - unuseRangeStart = lineIndex; - } - continue; - } - - if (isRangeActive === true) { - isRangeActive = false; - let arr = this.parsedDocuments.get(document.uri.fsPath); - if (arr) { - let lineIndexEnd = lineIndex-1; - arr.push(new vscode.Range(new vscode.Position(unuseRangeStart, 0), new vscode.Position(lineIndexEnd, 0))); - } else { - gDebugLog.error(`findDefines: ${document.fileName} has no range for unuseRange`); - } - } - - if (line.match(/^define\s+(?:(?![=\!]).)*=.*/gi)) { - let key = line.replace(/define/gi, "").trim(); - key = split(key, "=", 2)[0].trim(); - let value = split(line, "=", 2)[1].trim(); - if (value.includes(`$(${key})`)) { - gDebugLog.info(`Circular define: ${key}: ${value}`); - } else { - this.definesFdf.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex,0))); - } - continue; - } - - if (line.match(REGEX_INCLUDE)) { - - let value = line.replace(/!include/gi, "").trim(); - let location = await gPathFind.findPath(value); - if(location.length > 0){ - let includedDocument = await openTextDocument(location[0].uri); - this.filesFdf.push(includedDocument); - await this._proccessFdf(includedDocument); - } - continue; - } - } - gDebugLog.verbose(`findDefines End: ${document.fileName}`); - - - } - - - async grayoutDocument(document: vscode.TextDocument) { - - if (this.processComplete) { - // check if document is in index documents - if (this.isDocumentInIndex(document)) { - let grayoutRange = this.getGrayoutRange(document); - let grayoutController = this.grayoutControllers.get(document.uri); - if(!grayoutController){ - grayoutController = new GrayoutController(document, grayoutRange); - this.grayoutControllers.set(document.uri, grayoutController); - } - grayoutController.grayoutRange(grayoutRange); - // grayoutController.doGrayOut(); - return; - } - } - } async fdfPostProcces(document: vscode.TextDocument) { // preprocess fdf files if (this.processComplete) { diff --git a/src/treeElements/Library.ts b/src/treeElements/Library.ts index 9fee923..0a600c1 100644 --- a/src/treeElements/Library.ts +++ b/src/treeElements/Library.ts @@ -12,6 +12,7 @@ import { ConfigAgent } from "../configuration"; + export class EdkInfNode extends EdkNode{ contextUri:vscode.Uri; librarySet:Set|undefined; @@ -19,21 +20,14 @@ export class EdkInfNode extends EdkNode{ super(uri, position, wp, edkObject); this.contextUri = contextUri; this.description = `${uri.fsPath}`; - this.iconPath = new vscode.ThemeIcon("file"); + this.iconPath = new vscode.ThemeIcon("extensions"); this.command = { "command": "vscode.open", "title":"Open file", "arguments": [this.uri] }; this.librarySet = librarySet; - if(librarySet){ - if(librarySet.has(uri.fsPath)){ - this.setDuplicatedLibrary(); - }else{ - librarySet.add(uri.fsPath); - console.log(`${uri.fsPath}`); - } - } + void getParser(this.uri).then(async (parser)=>{ if(parser){ @@ -72,7 +66,7 @@ export class EdkInfNode extends EdkNode{ for (const libDefinition of libDefinitions) { let filePaths = await gPathFind.findPath(libDefinition.path); for (const path of filePaths) { - let childLibNode = new EdkInfNode(path.uri, this.contextUri, new vscode.Position(0,0), this.workspace, library, this.librarySet); + let childLibNode = new EdkInfNodeLibrary(path.uri, this.contextUri, new vscode.Position(0,0), this.workspace, library, this.librarySet); this.addChildren(childLibNode); // Check circular dependencies @@ -114,9 +108,8 @@ export class EdkInfNode extends EdkNode{ if(!gConfigAgent.getExpandCircularOrDuplicateLibraries()){ this.collapsibleState = vscode.TreeItemCollapsibleState.None; } - this.description = `(Recursive library)`; - this.iconPath = new vscode.ThemeIcon("extensions-remote"); - this.tooltip = "Recursive library"; + this.description = `(Duplicated library)`; + this.tooltip = "Duplicated library"; } setCircularDependency(){ @@ -128,4 +121,19 @@ export class EdkInfNode extends EdkNode{ this.tooltip = "Circular library dependency"; } +} + +export class EdkInfNodeLibrary extends EdkInfNode{ + constructor(uri:vscode.Uri, contextUri:vscode.Uri, position:vscode.Position, wp:EdkWorkspace, edkObject:EdkSymbol, librarySet?:Set|undefined){ + super(uri, contextUri, position, wp, edkObject, librarySet); + this.iconPath = new vscode.ThemeIcon("library"); + if(librarySet){ + if(librarySet.has(uri.fsPath)){ + this.setDuplicatedLibrary(); + }else{ + librarySet.add(uri.fsPath); + gDebugLog.verbose(`${uri.fsPath}`); + } + } + } } \ No newline at end of file diff --git a/src/ui/messages.ts b/src/ui/messages.ts index 7b1b5c0..ed45ad8 100644 --- a/src/ui/messages.ts +++ b/src/ui/messages.ts @@ -24,24 +24,26 @@ export function infoMissingCompileInfo(){ -export function infoMissingCppExtension(){ - if(gConfigAgent.isWarningCppExtension()){ - void vscode.window.showInformationMessage("The MS C/C++ or Cland extension is not installed. Please install one of those to use full EDK2Code features.", - "Install MS C/C++ extension", - "Install Clangd extension", - "Don't show this warning again").then(async selection => - { - - if (selection === "Install MS C/C++ extension"){ - void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/ms-vscode.cpptools')); - } - - if (selection === "Install Clangd extension"){ - void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/llvm-vs-code-extensions.vscode-clangd')); - } - +export function infoMissingCppExtension() { + if (gConfigAgent.isWarningCppExtension()) { + void vscode.window.showInformationMessage( + "The MS C/C++ or Clangd extension is not installed. Please install one of those to use full EDK2Code features.", + "Install Extension", + "Don't show this message again", + "Close" + ).then(async selection => { + if (selection === "Install Extension") { + const extensionChoice = await vscode.window.showQuickPick( + ["C/C++ for Visual Studio Code", "Clangd"], + { placeHolder: "Select the extension to install" } + ); - if(selection === "Don't show this warning again"){ + if (extensionChoice === "C/C++ for Visual Studio Code") { + void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/ms-vscode.cpptools')); + } else if (extensionChoice === "Clangd") { + void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/llvm-vs-code-extensions.vscode-clangd')); + } + } else if (selection === "Don't show this message again") { await gConfigAgent.setWarningCppExtension(false); } }); @@ -49,6 +51,20 @@ export function infoMissingCppExtension(){ } +export async function isFixWorkspacePath(buildPath:string, workspacePath:string):Promise{ + return new Promise(async (resolve, reject) => { + return vscode.window.showInformationMessage(`The Active platform in the build directory "${buildPath}" is different than Vscode Workspace path folder "${workspacePath}". Do you want EDK2Code to attempt to fix it? **Build directory wont be modified by this**`, "Yes", "No").then(async selection => { + if (selection === "Yes"){ + resolve(true); + }else{ + resolve(false); + } + }); + }); + +} + + export async function updateCompilesCommandCpp():Promise{ return new Promise(async (resolve, reject) => { return vscode.window.showInformationMessage("c_cpp_properties.json/settings.json points to wrong compile_commands.json", "Fix").then(async selection => { diff --git a/src/utils.ts b/src/utils.ts index 8d8721d..d2bda4b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -192,7 +192,7 @@ export function getRealPath(inputPath: string) { let fullRealPath = fs.realpathSync.native(fullPath); // In case user is using subst. Replace workspace path - fullRealPath = path.join(gWorkspacePath, fullRealPath.slice(fullRealPath.length - path.relative(gWorkspacePath, fullPath).length)); + // fullRealPath = path.join(gWorkspacePath, fullRealPath.slice(fullRealPath.length - path.relative(gWorkspacePath, fullPath).length)); return fullRealPath; } @@ -273,7 +273,7 @@ export async function openTextDocument(uri: vscode.Uri) { return f; } catch (error) { - gDebugLog.error(String(error)); + gDebugLog.error(`Problem opening ${uri.fsPath}:\n ${error}`); return await createVirtualFile("error", ""); } @@ -309,7 +309,9 @@ export async function copyToClipboard(data:string, message:string="Data copied t export function isWorkspacePath(p: string) { - return !path.relative(gWorkspacePath, p).includes(".."); + let x = gWorkspacePath; + const relativePath = path.relative(gWorkspacePath, p); + return !relativePath.includes("..") && relativePath !== p; } export function trimSpaces(text: string) { @@ -375,21 +377,6 @@ export async function getSymbolAtLocation(uri: vscode.Uri, location: vscode.Loca return returnSymbol; } -export async function readLinesAsync(filePath: string) { - return new Promise((resolve, token) => { - gDebugLog.debug(`readLines: ${filePath}`); - filePath = getRealPath(filePath); - if (!fs.existsSync(filePath)) { - gDebugLog.warning(`readlines: File doesnt exist: ${filePath}`); - resolve([]); - } - - let data = fs.readFileSync(filePath).toString().split(/\r?\n/); - resolve(data); - } - ); - -} export function readLines(filePath: string) { @@ -468,13 +455,13 @@ var profileStartTime: number; var profileEndTime: number; export function profileStart() { profileStartTime = new Date().getTime(); - console.log("PROFILE START"); + gDebugLog.debug("PROFILE START"); } export function profileEnd() { profileEndTime = new Date().getTime(); let diff = profileEndTime - profileStartTime; - console.log(`PROFILE END: ${diff}`); + gDebugLog.debug(`PROFILE END: ${diff}`); }