Skip to content

Commit b66a297

Browse files
committed
chore: Add APIs to get text from AST nodes
1 parent 6a2700b commit b66a297

File tree

4 files changed

+55
-43
lines changed

4 files changed

+55
-43
lines changed

src/frontend/cxx/cxx_document.cc

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,8 @@
2121
#include "cxx_document.h"
2222

2323
#include <cxx/ast.h>
24-
#include <cxx/ast_slot.h>
25-
#include <cxx/ast_visitor.h>
2624
#include <cxx/control.h>
2725
#include <cxx/gcc_linux_toolchain.h>
28-
#include <cxx/lexer.h>
29-
#include <cxx/lsp/enums.h>
30-
#include <cxx/lsp/requests.h>
3126
#include <cxx/lsp/types.h>
3227
#include <cxx/macos_toolchain.h>
3328
#include <cxx/preprocessor.h>
@@ -209,43 +204,28 @@ auto CxxDocument::translationUnit() const -> TranslationUnit* {
209204
return &d->unit;
210205
}
211206

212-
namespace {
213-
214-
struct Visit {
215-
CxxDocument* doc_;
216-
std::function<bool(AST*)> visitor;
217-
ASTSlot slotInfo;
218-
219-
void preVisit(AST* ast) {
220-
if (!ast) return;
221-
222-
if (visitor(ast)) return;
223-
224-
// do a pre-visit using the low-level AST API
207+
auto CxxDocument::textOf(AST* ast) -> std::optional<std::string_view> {
208+
return textInRange(ast->firstSourceLocation(), ast->lastSourceLocation());
209+
}
225210

226-
const auto slotCount = slotInfo(ast, 0).slotCount;
211+
auto CxxDocument::textInRange(SourceLocation start, SourceLocation end)
212+
-> std::optional<std::string_view> {
213+
auto& unit = d->unit;
214+
auto preprocessor = unit.preprocessor();
227215

228-
for (int index = 0; index < slotCount; ++index) {
229-
const auto childInfo = slotInfo(ast, index);
216+
const auto startToken = unit.tokenAt(start);
217+
const auto endToken = unit.tokenAt(end.previous());
230218

231-
if (childInfo.kind == ASTSlotKind::kNode) {
232-
auto child = reinterpret_cast<AST*>(childInfo.handle);
233-
if (child) preVisit(child);
234-
} else if (childInfo.kind == ASTSlotKind::kNodeList) {
235-
auto list = reinterpret_cast<List<AST*>*>(childInfo.handle);
236-
for (auto node : ListView{list}) {
237-
preVisit(node);
238-
}
239-
}
240-
}
219+
if (startToken.fileId() != endToken.fileId()) {
220+
return std::nullopt;
241221
}
242-
};
243222

244-
} // namespace
223+
std::string_view source = preprocessor->source(startToken.fileId());
224+
225+
const auto offset = startToken.offset();
226+
const auto length = endToken.offset() + endToken.length() - offset;
245227

246-
void CxxDocument::preVisit(std::function<bool(AST*)> visitor) {
247-
auto ast = d->unit.ast();
248-
Visit{this, std::move(visitor)}.preVisit(ast);
228+
return source.substr(offset, length);
249229
}
250230

251231
} // namespace cxx::lsp

src/frontend/cxx/cxx_document.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ class CxxDocument {
4343

4444
[[nodiscard]] auto translationUnit() const -> TranslationUnit*;
4545

46-
void preVisit(std::function<bool(AST*)> visitor);
46+
[[nodiscard]] auto textOf(AST* ast) -> std::optional<std::string_view>;
47+
48+
[[nodiscard]] auto textInRange(SourceLocation start, SourceLocation end)
49+
-> std::optional<std::string_view>;
4750

4851
private:
4952
struct Private;

src/frontend/cxx/lsp_server.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@
2020

2121
#include "lsp_server.h"
2222

23+
#include <cxx/ast.h>
2324
#include <cxx/lsp/enums.h>
2425
#include <cxx/lsp/requests.h>
2526
#include <cxx/lsp/types.h>
27+
#include <cxx/name_printer.h>
28+
#include <cxx/preprocessor.h>
29+
#include <cxx/symbols.h>
30+
#include <cxx/type_printer.h>
2631
#include <utf8/unchecked.h>
2732

2833
#include <format>
@@ -433,12 +438,15 @@ void Server::operator()(DocumentSymbolRequest request) {
433438

434439
auto uri = request.params().textDocument().uri();
435440
auto doc = latestDocument(uri);
441+
auto id = request.id();
436442

437-
withUnsafeJson([&](json storage) {
438-
DocumentSymbolResponse response(storage);
439-
response.id(request.id());
440-
(void)response.result();
441-
sendToClient(response);
443+
run([=, this] {
444+
withUnsafeJson([&](json storage) {
445+
DocumentSymbolResponse response(storage);
446+
response.id(id);
447+
(void)response.result();
448+
sendToClient(response);
449+
});
442450
});
443451
}
444452

@@ -462,7 +470,7 @@ void Server::operator()(SetTraceNotification notification) {
462470
trace_ = notification.params().value();
463471

464472
if (trace_ != TraceValue::kOff) {
465-
logTrace("Trace level set to {}", to_string(trace_));
473+
logTrace(std::format("Trace level set to {}", to_string(trace_)));
466474
return;
467475
}
468476
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# RUN: %cxx -lsp-test < %s | %filecheck %s
2+
3+
{ "method": "initialize", "id": 0 }
4+
5+
# CHECK: "id": 0
6+
7+
{ "method": "textDocument/didOpen", "id": 1, "params": { "textDocument": { "uri": "test:///source.cc", "version": 0, "text": "#include <cstdio>\nauto main() -> int;" } } }
8+
9+
{ "method": "$/setTrace", "id": 2, "params": { "value": "verbose" } }
10+
11+
{ "method": "textDocument/documentSymbol", "id": 3, "params": { "textDocument": { "uri": "test:///source.cc" } } }
12+
13+
# CHECK: "message": "Did receive DocumentSymbolRequest"
14+
# CHECK: "id": 3
15+
16+
{ "method": "shutdown", "id": 4 }
17+
18+
{ "method": "exit" }
19+
20+
21+

0 commit comments

Comments
 (0)