Skip to content

Commit

Permalink
support module/interface definitions and hovers by searching for file…
Browse files Browse the repository at this point in the history
… name
  • Loading branch information
AndrewNolte committed Mar 13, 2024
1 parent ca07b5e commit 6ce85c4
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 153 deletions.
140 changes: 65 additions & 75 deletions src/commands/ModuleInstantiation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,71 +14,63 @@ export function instantiateModuleInteract() {
});
}

function instantiateModule(srcpath: string): Thenable<vscode.SnippetString> {
return new Promise<vscode.SnippetString>((resolve, _reject) => {
async function instantiateModule(srcpath: string): Promise<vscode.SnippetString | undefined> {
// Using Ctags to get all the modules in the file
let moduleName: string = '';
let portsName: string[] = [];
let parametersName: string[] = [];
let ctags: ModuleTags = new ModuleTags(logger);
let file: vscode.TextDocument = vscode.window.activeTextEditor.document;
let ctags: ModuleTags = new ModuleTags(logger, file);
logger.info('Executing ctags for module instantiation');
ctags
.execCtags(srcpath)
.then((output) => {
ctags.buildSymbolsList(output);
})
.then(async () => {
let module: Symbol;
let modules: Symbol[] = ctags.symbols.filter((tag) => tag.type === 'module');
// No modules found
if (modules.length <= 0) {
vscode.window.showErrorMessage('Verilog-HDL/SystemVerilog: No modules found in the file');
return;
}
// Only one module found
else if (modules.length === 1) {
module = modules[0];
}
// many modules found
else if (modules.length > 1) {
moduleName = await vscode.window.showQuickPick(
ctags.symbols.filter((tag) => tag.type === 'module').map((tag) => tag.name),
{
placeHolder: 'Choose a module to instantiate',
}
);
if (moduleName === undefined) {
return;
}
module = modules.filter((tag) => tag.name === moduleName)[0];
}
let scope = module.parentScope != '' ? module.parentScope + '.' + module.name : module.name;
let ports: Symbol[] = ctags.symbols.filter(
(tag) => tag.type === 'port' && tag.parentType === 'module' && tag.parentScope === scope
);
portsName = ports.map((tag) => tag.name);
let params: Symbol[] = ctags.symbols.filter(
(tag) =>
tag.type === 'parameter' && tag.parentType === 'module' && tag.parentScope === scope
);
parametersName = params.map((tag) => tag.name);
logger.info('Module name: ' + module.name);
let paramString = ``;
if (parametersName.length > 0) {
paramString = `\n#(\n${instantiatePort(parametersName)})\n`;
let output = await ctags.execCtags(srcpath);
await ctags.buildSymbolsList(output);
let module: Symbol;
let modules: Symbol[] = ctags.symbols.filter((tag) => tag.type === 'module');
// No modules found
if (modules.length <= 0) {
vscode.window.showErrorMessage('Verilog-HDL/SystemVerilog: No modules found in the file');
return undefined;
}
// Only one module found
else if (modules.length === 1) {
module = modules[0];
}
// many modules found
else if (modules.length > 1) {
moduleName = await vscode.window.showQuickPick(
ctags.symbols.filter((tag) => tag.type === 'module').map((tag) => tag.name),
{
placeHolder: 'Choose a module to instantiate',
}
logger.info('portsName: ' + portsName.toString());
resolve(
new vscode.SnippetString()
.appendText(module.name + ' ')
.appendText(paramString)
.appendPlaceholder('u_')
.appendPlaceholder(`${module.name}(\n`)
.appendText(instantiatePort(portsName))
.appendText(');\n')
);
});
});
);
if (moduleName === undefined) {
return undefined;
}
module = modules.filter((tag) => tag.name === moduleName)[0];
}
let scope = module.parentScope != '' ? module.parentScope + '.' + module.name : module.name;

Check warning on line 51 in src/commands/ModuleInstantiation.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

Expected '!==' and instead saw '!='

Check warning on line 51 in src/commands/ModuleInstantiation.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

Expected '!==' and instead saw '!='

Check warning on line 51 in src/commands/ModuleInstantiation.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

Expected '!==' and instead saw '!='
let ports: Symbol[] = ctags.symbols.filter(
(tag) => tag.type === 'port' && tag.parentType === 'module' && tag.parentScope === scope
);
portsName = ports.map((tag) => tag.name);
let params: Symbol[] = ctags.symbols.filter(
(tag) =>
tag.type === 'parameter' && tag.parentType === 'module' && tag.parentScope === scope
);
parametersName = params.map((tag) => tag.name);
logger.info('Module name: ' + module.name);
let paramString = ``;
if (parametersName.length > 0) {
paramString = `\n#(\n${instantiatePort(parametersName)})\n`;
}
logger.info('portsName: ' + portsName.toString());
return new vscode.SnippetString()
.appendText(module.name + ' ')
.appendText(paramString)
.appendPlaceholder('u_')
.appendPlaceholder(`${module.name}(\n`)
.appendText(instantiatePort(portsName))
.appendText(');\n');
}

function instantiatePort(ports: string[]): string {
Expand All @@ -103,7 +95,7 @@ function instantiatePort(ports: string[]): string {
return port;
}

function selectFile(currentDir?: string): Thenable<string> {
async function selectFile(currentDir?: string): Promise<string | undefined> {
currentDir = currentDir || vscode.workspace.rootPath;

let dirs = getDirectories(currentDir);
Expand All @@ -129,24 +121,22 @@ function selectFile(currentDir?: string): Thenable<string> {
});
});

return vscode.window
let selected = await vscode.window
.showQuickPick(items, {
placeHolder: 'Choose the module file',
})
.then((selected) => {
if (!selected) {
return undefined;
}
});
if (!selected) {
return undefined;
}

// if is a directory
let location = path.join(currentDir, selected.label);
if (fs.statSync(location).isDirectory()) {
return selectFile(location);
}
// if is a directory
let location = path.join(currentDir, selected.label);
if (fs.statSync(location).isDirectory()) {
return selectFile(location);
}

// return file path
return location;
});
// return file path
return location;
}

function getDirectories(srcpath: string): string[] {
Expand All @@ -160,7 +150,7 @@ function getFiles(srcpath: string): string[] {
}

class ModuleTags extends Ctags {
buildSymbolsList(tags: string): Thenable<void> {
buildSymbolsList(tags: string): Promise<void> {
if (tags === '') {
return undefined;
}
Expand Down
119 changes: 87 additions & 32 deletions src/ctags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,13 @@ export class Ctags {
isDirty: boolean;
private logger: Logger;

constructor(logger: Logger) {
constructor(logger: Logger, document: vscode.TextDocument) {
this.symbols = [];
this.isDirty = true;
this.logger = logger;
this.doc = document;
}

setDocument(doc: vscode.TextDocument) {
this.doc = doc;
this.clearSymbols();
}

clearSymbols() {
this.isDirty = true;
Expand All @@ -161,7 +158,7 @@ export class Ctags {
return this.symbols;
}

execCtags(filepath: string): Thenable<string> {
async execCtags(filepath: string): Promise<string> {
this.logger.info('executing ctags');

let binPath: string = <string>(
Expand Down Expand Up @@ -210,13 +207,13 @@ export class Ctags {
return undefined;
}

buildSymbolsList(tags: string): Thenable<void> {
async buildSymbolsList(tags: string): Promise<void> {
try {
if (this.isDirty) {
this.logger.info('building symbols');
if (tags === '') {
this.logger.error('No output from ctags');
return undefined;
return;
}
// Parse ctags output
let lines: string[] = tags.split(/\r?\n/);
Expand Down Expand Up @@ -261,54 +258,112 @@ export class Ctags {
this.logger.info('Symbols: ' + this.symbols.toString());
this.isDirty = false;
}
return Promise.resolve();
} catch (e) {
this.logger.error(e.toString());
}
return undefined;
}

index(): Thenable<void> {
this.logger.info('indexing...');
return new Promise((resolve, _reject) => {
this.execCtags(this.doc.uri.fsPath)
.then((output) => this.buildSymbolsList(output))
.then(() => resolve());
});
async index(): Promise<void> {
this.logger.info('indexing ', this.doc.uri.fsPath);

let output = await this.execCtags(this.doc.uri.fsPath)

Check warning on line 269 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

Missing semicolon

Check warning on line 269 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

Missing semicolon

Check warning on line 269 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

Missing semicolon
console.log("output", output)

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

'console' is not defined

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

Missing semicolon

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

'console' is not defined

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

Missing semicolon

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

'console' is not defined

Check warning on line 270 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

Missing semicolon
await this.buildSymbolsList(output);
}
}

export class CtagsManager {
private static ctags: Ctags;
private filemap: Map<vscode.TextDocument, Ctags> = new Map();
private logger: Logger;

constructor(logger: Logger) {
configure(logger: Logger) {
this.logger = logger;
CtagsManager.ctags = new Ctags(logger.getChild('Ctags'));
}

configure() {
this.logger.info('ctags manager configure');
vscode.workspace.onDidSaveTextDocument(this.onSave.bind(this));
vscode.workspace.onDidCloseTextDocument(this.onClose.bind(this));
}

getCtags(doc: vscode.TextDocument): Ctags {
let ctags: Ctags = this.filemap.get(doc);
if (ctags === undefined) {
ctags = new Ctags(this.logger, doc);
this.filemap.set(doc, ctags);
}
return ctags;
}
onClose(doc: vscode.TextDocument) {
this.logger.info('on close');
this.filemap.delete(doc);
}

onSave(doc: vscode.TextDocument) {
this.logger.info('on save');
let ctags: Ctags = CtagsManager.ctags;
if (ctags.doc === undefined || ctags.doc.uri.fsPath === doc.uri.fsPath) {
CtagsManager.ctags.clearSymbols();
}
let ctags: Ctags = this.getCtags(doc);
ctags.clearSymbols();
}

static async getSymbols(doc: vscode.TextDocument): Promise<Symbol[]> {
let ctags: Ctags = CtagsManager.ctags;
if (ctags.doc === undefined || ctags.doc.uri.fsPath !== doc.uri.fsPath) {
ctags.setDocument(doc);
}
async getSymbols(doc: vscode.TextDocument): Promise<Symbol[]> {
let ctags: Ctags = this.getCtags(doc);
// If dirty, re index and then build symbols
if (ctags.isDirty) {
console.log("indxing ");

Check warning on line 309 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

'console' is not defined

Check warning on line 309 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

'console' is not defined

Check warning on line 309 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

'console' is not defined
await ctags.index();
}
return ctags.symbols;
}

async findMatches(document: vscode.TextDocument, targetText: string): Promise<vscode.DefinitionLink[]> {
console.log("finding matches asdf", document.uri.fsPath, "for", targetText);

Check warning on line 316 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

'console' is not defined

Check warning on line 316 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

'console' is not defined

Check warning on line 316 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

'console' is not defined
let symbols: Symbol[] = await this.getSymbols(document);
console.log("symbols", symbols, "for", document.uri.fsPath, targetText)

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

'console' is not defined

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

Missing semicolon

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

'console' is not defined

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

Missing semicolon

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

'console' is not defined

Check warning on line 318 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

Missing semicolon
let matchingSymbols: Symbol[] = [];
for (let i of symbols) {
if (i.name === targetText) {
matchingSymbols.push(i);
}
}
// console.log("matchingSymbols", matchingSymbols, "for", document.uri.fsPath, targetText);
let ret: vscode.DefinitionLink[] = matchingSymbols.map((i) => {
return {
document: document,
targetUri: document.uri,
targetRange: new vscode.Range(
i.startPosition,
new vscode.Position(i.startPosition.line, Number.MAX_VALUE)
),
targetSelectionRange: new vscode.Range(i.startPosition, i.endPosition),
};
});
console.log("ret", ret);

Check warning on line 337 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (macos-latest)

'console' is not defined

Check warning on line 337 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (ubuntu-latest)

'console' is not defined

Check warning on line 337 in src/ctags.ts

View workflow job for this annotation

GitHub Actions / Upload vsix package (windows-latest)

'console' is not defined
return ret;
}

/// also searched in targetText.sv
async findSymbol(document: vscode.TextDocument, targetText: string): Promise<vscode.DefinitionLink[]> {
// we know we want to search the current doc
// let tasks = [this.findMatches(document, targetText)];

let matches = await this.findMatches(document, targetText);


// kick off async job that looks for module.sv


let searchPattern = new vscode.RelativePattern(vscode.workspace.workspaceFolders[0], `**/${targetText}.sv`);
let files = await vscode.workspace.findFiles(searchPattern);
if (files.length !== 0) {
console.log("found", files[0].fsPath);
let file = await vscode.workspace.openTextDocument(files[0]);
// tasks.push(this.findMatches(file, targetText));
let modMatches = await this.findMatches(file, targetText);
matches = matches.concat(modMatches);
}

// const lists = await Promise.all(tasks);
// const lists = matches.concat(modMatches);
// combine into one using reduce
// let matchingSymbols = lists.reduce((acc, val) => acc.concat(val), []);
console.log("matchingSymbols", matches, "for", document.uri.fsPath, targetText);
return matches;
}
}
Loading

0 comments on commit 6ce85c4

Please sign in to comment.