Skip to content

Commit ea60458

Browse files
committed
chore: Add APIs to get text from AST nodes
1 parent 5d1bb6e commit ea60458

File tree

5 files changed

+62
-52
lines changed

5 files changed

+62
-52
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: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
#include <cxx/lsp/fwd.h>
2424
#include <cxx/translation_unit.h>
2525

26-
#include <functional>
27-
#include <memory>
26+
#include <optional>
2827
#include <string>
2928

3029
#include "cli.h"
@@ -43,7 +42,10 @@ class CxxDocument {
4342

4443
[[nodiscard]] auto translationUnit() const -> TranslationUnit*;
4544

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

4850
private:
4951
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
}

src/parser/cxx/ast_cursor.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,10 @@
2222
#include <cxx/ast_cursor.h>
2323
#include <cxx/ast_slot.h>
2424

25-
#include <format>
26-
#include <iostream>
27-
2825
namespace cxx {
2926

3027
ASTCursor::ASTCursor(AST* root, std::string_view name) {
31-
stack_.emplace_back(root, name);
28+
stack_.push_back(Node{root, name});
3229
}
3330

3431
ASTCursor::~ASTCursor() {}
@@ -57,12 +54,13 @@ void ASTCursor::step() {
5754
auto name = to_string(slot.nameIndex);
5855
if (slot.kind == ASTSlotKind::kNode) {
5956
auto node = reinterpret_cast<AST*>(slot.handle);
60-
stack_.emplace_back(node, name);
57+
stack_.push_back(Node{node, name});
6158
} else if (slot.kind == ASTSlotKind::kNodeList) {
6259
auto list = reinterpret_cast<List<AST*>*>(slot.handle);
63-
stack_.emplace_back(list, name);
60+
stack_.push_back(Node{list, name});
6461
}
6562
}
63+
6664
break;
6765
} else if (auto list = std::get_if<List<AST*>*>(&node)) {
6866
if (!*list) continue;
@@ -74,8 +72,9 @@ void ASTCursor::step() {
7472
}
7573

7674
for (const auto& ast : children | std::views::reverse) {
77-
stack_.emplace_back(ast, kind);
75+
stack_.push_back(Node{ast, kind});
7876
}
77+
7978
break;
8079
}
8180
}
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)