Skip to content

Commit 2e1950d

Browse files
author
Moritz Scherer
committed
Add simple indexer
1 parent 0fa4326 commit 2e1950d

File tree

3 files changed

+116
-64
lines changed

3 files changed

+116
-64
lines changed

lib/Tools/circt-verilog-lsp-server/VerilogServerImpl/SlangProjectLookup.cpp

Lines changed: 108 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,55 @@
1818
#include "slang/ast/Lookup.h"
1919
#include "slang/ast/Scope.h"
2020
#include "slang/ast/Symbol.h"
21+
#include "slang/ast/symbols/CompilationUnitSymbols.h"
2122
#include "slang/diagnostics/Diagnostics.h"
2223
#include "slang/syntax/AllSyntax.h"
24+
#include "slang/syntax/SyntaxFacts.h"
2325
#include "slang/syntax/SyntaxKind.h"
26+
#include "slang/syntax/SyntaxNode.h"
2427
#include "slang/syntax/SyntaxTree.h"
2528
#include "slang/syntax/SyntaxVisitor.h"
2629
#include "slang/text/SourceLocation.h"
2730
#include "slang/text/SourceManager.h"
2831
#include "llvm/Support/LSP/Protocol.h"
29-
#include "llvm/Support/SourceMgr.h"
3032

33+
using namespace slang;
3134
using namespace slang::syntax;
35+
using namespace slang::ast;
36+
37+
struct DefIndex {
38+
// For now: name -> location (first hit wins). Upgrade to multimap if needed.
39+
std::unordered_map<std::string, slang::SourceLocation> byName;
40+
};
41+
42+
43+
static void indexDeclarators(const slang::syntax::SyntaxNode &node,
44+
DefIndex &out) {
45+
using namespace slang::syntax;
46+
47+
switch (node.kind) {
48+
case SyntaxKind::Declarator:
49+
if (auto *decl = node.as_if<DeclaratorSyntax>()) {
50+
auto nameText = decl->name.valueText(); // strips trivia
51+
auto loc = decl->name.location();
52+
if (!nameText.empty() && loc)
53+
out.byName.emplace(std::string(nameText), loc);
54+
}
55+
break;
56+
default:
57+
break;
58+
}
59+
}
60+
61+
/// Walk the syntax tree from its root down to collect all declarators;
62+
/// declarators contain symbol definitions we can lookup later.
63+
static void walk(const slang::syntax::SyntaxNode &node, DefIndex &out) {
64+
indexDeclarators(node, out);
65+
66+
for (size_t i = 0, e = node.getChildCount(); i < e; ++i)
67+
if (auto *c = node.childNode(i))
68+
walk(*c, out);
69+
}
3270

3371
static bool isLocationInRange(slang::SourceRange r, slang::SourceLocation loc) {
3472
if (!r.start() || !r.end())
@@ -37,6 +75,65 @@ static bool isLocationInRange(slang::SourceRange r, slang::SourceLocation loc) {
3775
return r.start().offset() <= o && o < r.end().offset();
3876
}
3977

78+
namespace {
79+
/// Visitor that tries to produce a definition `SourceLocation` for a node.
80+
struct DefinitionVisitor : public slang::syntax::SyntaxVisitor<
81+
std::optional<slang::SourceLocation>> {
82+
using Base = SyntaxVisitor<std::optional<slang::SourceLocation>>;
83+
using Base::visit;
84+
85+
DefinitionVisitor(const slang::ast::Compilation &comp,
86+
const slang::ast::Scope &rootScope,
87+
slang::SourceLocation queryLoc, DefIndex &defIndex)
88+
: comp(comp), rootScope(rootScope), queryLoc(queryLoc),
89+
defIndex(defIndex) {}
90+
91+
// Hierarchy instantiation -> resolve the *type* globally.
92+
std::optional<slang::SourceLocation>
93+
visit(const HierarchyInstantiationSyntax &n) {
94+
auto res = comp.tryGetDefinition(n.type.valueText(), rootScope);
95+
if (res.definition)
96+
return res.definition->location;
97+
return std::nullopt;
98+
}
99+
100+
// Declaration name (e.g., "logic x;") — treat cursor as the def.
101+
std::optional<slang::SourceLocation> visit(const DeclaratorSyntax &) {
102+
return queryLoc;
103+
}
104+
105+
// Module header (cursor on module name) — treat cursor as the def.
106+
std::optional<slang::SourceLocation> visit(const ModuleHeaderSyntax &) {
107+
return queryLoc;
108+
}
109+
110+
// Instance name (u0) — TODO (not implemented).
111+
std::optional<slang::SourceLocation> visit(const InstanceNameSyntax &) {
112+
return std::nullopt;
113+
}
114+
115+
// Generic name — TODO: local scope lookup.
116+
std::optional<slang::SourceLocation> visit(const IdentifierNameSyntax &node) {
117+
auto it = defIndex.byName.find(std::string(node.identifier.valueText()));
118+
if (it == defIndex.byName.end())
119+
return std::nullopt;
120+
return it->second;
121+
}
122+
123+
// Fallback for all other node kinds.
124+
template <typename T>
125+
std::optional<slang::SourceLocation> visit(const T &) {
126+
return std::nullopt;
127+
}
128+
129+
const slang::ast::Compilation &comp;
130+
const slang::ast::Scope &rootScope;
131+
slang::SourceLocation queryLoc;
132+
DefIndex &defIndex;
133+
};
134+
135+
} // namespace
136+
40137
slang::SourceLocation
41138
SlangProjectLookup::lspPositionToSlangLocation(slang::BufferID buf,
42139
const llvm::lsp::Position &pos) {
@@ -123,79 +220,33 @@ SlangProjectLookup::getSyntaxNodeAt(slang::BufferID mainBufferId,
123220
return findSmallestNodeAt(root, loc);
124221
}
125222

126-
namespace {
127-
/// Visitor that tries to produce a definition `SourceLocation` for a node.
128-
struct DefinitionVisitor
129-
: public slang::syntax::SyntaxVisitor<std::optional<slang::SourceLocation>> {
130-
using Base = SyntaxVisitor<std::optional<slang::SourceLocation>>;
131-
using Base::visit;
132-
133-
DefinitionVisitor(const slang::ast::Compilation &comp, const slang::ast::Scope &rootScope,
134-
slang::SourceLocation queryLoc)
135-
: comp(comp), rootScope(rootScope), queryLoc(queryLoc) {}
136-
137-
// Hierarchy instantiation -> resolve the *type* globally.
138-
std::optional<slang::SourceLocation>
139-
visit(const HierarchyInstantiationSyntax &n) {
140-
llvm::dbgs() << "valueText: " << n.type.valueText() << "\n";
141-
auto res = comp.tryGetDefinition(n.type.valueText(), rootScope);
142-
if (res.definition)
143-
return res.definition->location;
144-
return std::nullopt;
145-
}
146-
147-
// Declaration name (e.g., "logic x;") — treat cursor as the def.
148-
std::optional<slang::SourceLocation> visit(const DeclaratorSyntax &) {
149-
return queryLoc;
150-
}
151-
152-
// Module header (cursor on module name) — treat cursor as the def.
153-
std::optional<slang::SourceLocation> visit(const ModuleHeaderSyntax &) {
154-
return queryLoc;
155-
}
156-
157-
// Instance name (u0) — TODO (not implemented).
158-
std::optional<slang::SourceLocation> visit(const InstanceNameSyntax &) {
159-
return std::nullopt;
160-
}
161-
162-
// Generic name — TODO: local scope lookup.
163-
std::optional<slang::SourceLocation> visit(const NameSyntax &) {
164-
return std::nullopt;
165-
}
166-
167-
// Fallback for all other node kinds.
168-
template <typename T>
169-
std::optional<slang::SourceLocation> visit(const T &) {
170-
return std::nullopt;
171-
}
172-
173-
const slang::ast::Compilation &comp;
174-
const slang::ast::Scope &rootScope;
175-
slang::SourceLocation queryLoc;
176-
};
177-
178-
} // namespace
179-
180223
llvm::FailureOr<const slang::SourceLocation>
181224
SlangProjectLookup::tryFindDefinitionAt(slang::BufferID mainBufferId,
182225
slang::SourceLocation loc) {
183226

184227
const SyntaxNode *node;
185228
llvm::FailureOr<const SyntaxNode *> n = getSyntaxNodeAt(mainBufferId, loc);
229+
186230
if (failed(n))
187231
return llvm::failure();
188232
node = n.value();
189233

234+
// Find the root (topmost) syntax node of this tree.
235+
const SyntaxNode *root = node;
236+
for (const SyntaxNode *cur = node; cur; cur = cur->parent)
237+
root = cur; // root ends up as the last non-null
238+
239+
DefIndex d;
240+
walk(*root, d);
190241

191-
DefinitionVisitor v{compilation, rootSymbol, loc};
242+
DefinitionVisitor v{compilation, rootSymbol, loc, d};
192243

193244
// Try at the node first…
194245
if (auto hit = node->visit(v))
195246
return *hit;
196247

197248
// …then walk up parents to broaden the context.
198-
for (const SyntaxNode* p = node->parent; p; p = p->parent) {
249+
for (const SyntaxNode *p = node->parent; p; p = p->parent) {
199250
if (auto hit = p->visit(v))
200251
return *hit;
201252
}

lib/Tools/circt-verilog-lsp-server/VerilogServerImpl/SlangProjectLookup.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
#include "llvm/Support/LSP/Logging.h"
1514
#include "llvm/Support/LSP/Protocol.h"
1615

1716
namespace slang {
@@ -28,14 +27,17 @@ namespace ast {
2827
class Compilation;
2928
class Scope;
3029
} // namespace ast
30+
namespace analysis {
31+
class AnalyzedDesign;
32+
} // namespace analysis
3133
} // namespace slang
3234

3335
/// A helper for translating between LLVM::LSP and Slang.
3436
struct SlangProjectLookup {
3537
SlangProjectLookup(const slang::ast::Compilation &compilation,
3638
const slang::ast::Scope &rootSymbol,
3739
const slang::SourceManager &sourceManager)
38-
: compilation(compilation), rootSymbol(rootSymbol),
40+
: compilation(compilation), rootSymbol(rootSymbol),
3941
sourceManager(sourceManager) {}
4042

4143
/// Convert an LSP `Position` (line / character) into a Slang `SourceLocation`

lib/Tools/circt-verilog-lsp-server/VerilogServerImpl/VerilogServer.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@
1919
#include "circt/Tools/circt-verilog-lsp-server/CirctVerilogLspServerMain.h"
2020
#include "slang/ast/Compilation.h"
2121
#include "slang/ast/Scope.h"
22-
#include "slang/ast/symbols/CompilationUnitSymbols.h"
2322
#include "slang/diagnostics/DiagnosticClient.h"
2423
#include "slang/diagnostics/Diagnostics.h"
2524
#include "slang/driver/Driver.h"
26-
#include "slang/syntax/AllSyntax.h"
2725
#include "slang/syntax/SyntaxTree.h"
2826
#include "slang/text/SourceLocation.h"
2927
#include "slang/text/SourceManager.h"
@@ -225,14 +223,14 @@ VerilogDocument::VerilogDocument(
225223

226224
// --- Apply project command files (the “-C”s) to this per-buffer driver ---
227225
for (const std::string &cmdFile : context.getPreloadedCommandFiles()) {
228-
if (!driver.processCommandFiles(cmdFile, true, true)) {
226+
if (!driver.processCommandFiles(cmdFile, false, true)) {
229227
circt::lsp::Logger::error(Twine("Failed to open command file ") +
230228
cmdFile);
231229
}
232230
}
233231

234232
driver.options.compilationFlags.emplace(
235-
slang::ast::CompilationFlags::LintMode, false);
233+
slang::ast::CompilationFlags::LintMode, false);
236234
driver.options.compilationFlags.emplace(
237235
slang::ast::CompilationFlags::DisableInstanceCaching, false);
238236

@@ -296,7 +294,8 @@ VerilogDocument::getDefinitionAt(const llvm::lsp::Position &pos) {
296294
auto &comp = getSlangCompilation();
297295
const auto &sm = comp.getSourceManager();
298296

299-
SlangProjectLookup sl = SlangProjectLookup(comp, comp.getRoot(), *sm);
297+
SlangProjectLookup sl =
298+
SlangProjectLookup(comp, comp.getRootNoFinalize(), *sm);
300299
slang::SourceLocation loc = sl.lspPositionToSlangLocation(mainBufferId, pos);
301300

302301
// Identify a name-like syntax under the cursor.

0 commit comments

Comments
 (0)