Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {
VerilogIndexer(VerilogIndex &index) : index(index) {}
VerilogIndex &index;

template <typename T>
void recurseIfInMainBuffer(const T &node) {
if (definitelyOutsideMainBuffer(node, index.getBufferId()))
return;
visitDefault(node);
}

void insertSymbol(const slang::ast::Symbol *symbol, slang::SourceRange range,
bool isDefinition = true) {
if (symbol->name.empty())
Expand Down Expand Up @@ -104,10 +111,12 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {

void visit(const slang::ast::NetSymbol &expr) {
insertSymbol(&expr, expr.location, /*isDefinition=*/true);
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::VariableSymbol &expr) {
insertSymbol(&expr, expr.location, /*isDefinition=*/true);
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::ExplicitImportSymbol &expr) {
Expand All @@ -120,6 +129,7 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {
insertSymbol(def, item->package.location(), /*isDefinition=*/false);
}
}
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::WildcardImportSymbol &expr) {
Expand All @@ -132,6 +142,14 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {
insertSymbol(def, item->package.location(), false);
}
}
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::InstanceBodySymbol &expr) {
// Insert the symbols in the port list.
for (const auto *symbol : expr.getPortList())
index.insertSymbolDefinition(symbol);
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::InstanceSymbol &expr) {
Expand All @@ -155,10 +173,12 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {

// Link the module instance name back to the module definition
insertSymbol(def, expr.location, /*isDefinition=*/false);
recurseIfInMainBuffer(expr);
}

void visit(const slang::ast::VariableDeclStatement &expr) {
insertSymbol(&expr.symbol, expr.sourceRange, /*isDefinition=*/true);
recurseIfInMainBuffer(expr);
}

template <typename T>
Expand All @@ -168,12 +188,7 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {
if constexpr (std::is_base_of_v<slang::ast::Symbol, T>)
visitSymbol(node);

// Check if this node is already out of the main buffer.
if (definitelyOutsideMainBuffer(node, index.getBufferId()))
return;

// Otherwise, recurse and keep indexing.
ASTBase::template visitDefault<T>(node);
recurseIfInMainBuffer(node);
}

template <typename T>
Expand All @@ -184,17 +199,21 @@ struct VerilogIndexer : slang::ast::ASTVisitor<VerilogIndexer, true, true> {
void VerilogIndex::initialize(slang::ast::Compilation &compilation) {
const auto &root = compilation.getRoot();
VerilogIndexer visitor(*this);
for (auto *inst : root.topInstances) {

if (inst->body.location.buffer() != getBufferId())
// Index packages defined in the current main buffer
for (auto *package : compilation.getPackages()) {
if (package->location.buffer() != getBufferId())
continue;
// Visit the body of the top instance.
package->visit(visitor);
}

// Visit the body of the instance.
// Index modules defined in the current main buffer
for (auto *inst : root.topInstances) {
if (inst->body.location.buffer() != getBufferId())
continue;
// Visit the body of the top instance.
inst->body.visit(visitor);

// Insert the symbols in the port list.
for (const auto *symbol : inst->body.getPortList())
insertSymbolDefinition(symbol);
}

// Parse the source location from the main file.
Expand Down
38 changes: 38 additions & 0 deletions test/Tools/circt-verilog-lsp-server/package-indexing.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// RUN: circt-verilog-lsp-server -lit-test --source-location-include-dir=%S < %s | FileCheck %s
// REQUIRES: slang
// UNSUPPORTED: valgrind
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"verilog","capabilities":{},"trace":"off"}}
// -----
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{
"uri":"test:///test.sv",
"languageId":"verilog",
"version":1,
"text":"package test;\nlocalparam int unsigned testValue = 0;\nlocalparam int unsigned testValueB = testValue;\nendpackage"
}}}
// -----
// Find definition of `testValue`
{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{
"textDocument":{"uri":"test:///test.sv"},
"position":{"line":2,"character":39}
}}
// CHECK: "id": 1,
// CHECK-NEXT: "jsonrpc": "2.0",
// CHECK-NEXT: "result": [
// CHECK-NEXT: {
// CHECK-NEXT: "range": {
// CHECK-NEXT: "end": {
// CHECK-NEXT: "character": 33,
// CHECK-NEXT: "line": 1
// CHECK-NEXT: },
// CHECK-NEXT: "start": {
// CHECK-NEXT: "character": 24,
// CHECK-NEXT: "line": 1
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "uri": "test:///test.sv"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// -----
{"jsonrpc":"2.0","id":5,"method":"shutdown"}
// -----
{"jsonrpc":"2.0","method":"exit"}