ckandeler updated this revision to Diff 339994.
ckandeler added a comment.
Fixed TU traversal
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D101057/new/
https://reviews.llvm.org/D101057
Files:
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/DumpAST.cpp
clang-tools-extra/clangd/Protocol.h
clang-tools-extra/clangd/test/ast-no-range.test
clang-tools-extra/clangd/unittests/DumpASTTests.cpp
Index: clang-tools-extra/clangd/unittests/DumpASTTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/DumpASTTests.cpp
+++ clang-tools-extra/clangd/unittests/DumpASTTests.cpp
@@ -16,8 +16,12 @@
namespace clang {
namespace clangd {
namespace {
+using testing::Contains;
+using testing::Not;
using testing::SizeIs;
+MATCHER_P(WithDetail, str, "") { return arg.detail == str; }
+
TEST(DumpASTTests, BasicInfo) {
std::pair</*Code=*/std::string, /*Expected=*/std::string> Cases[] = {
{R"cpp(
@@ -157,6 +161,20 @@
EXPECT_EQ(Node.children.front().range, Case.range("type"));
}
+TEST(DumpASTTests, NoRange) {
+ auto TU = TestTU::withHeaderCode("void funcFromHeader();");
+ TU.Code = "int varFromSource;";
+ ParsedAST AST = TU.build();
+ auto Node = dumpAST(
+ DynTypedNode::create(*AST.getASTContext().getTranslationUnitDecl()),
+ AST.getTokens(), AST.getASTContext());
+ ASSERT_THAT(Node.children, Contains(WithDetail("varFromSource")));
+ ASSERT_THAT(Node.children, Not(Contains(WithDetail("funcFromHeader"))));
+ EXPECT_THAT(Node.arcana, testing::StartsWith("TranslationUnitDecl "));
+ ASSERT_FALSE(Node.range.hasValue())
+ << "Expected no range for translation unit";
+}
+
TEST(DumpASTTests, Arcana) {
ParsedAST AST = TestTU::withCode("int x;").build();
auto Node = dumpAST(DynTypedNode::create(findDecl(AST, "x")), AST.getTokens(),
Index: clang-tools-extra/clangd/test/ast-no-range.test
===================================================================
--- /dev/null
+++ clang-tools-extra/clangd/test/ast-no-range.test
@@ -0,0 +1,53 @@
+# RUN: clangd -lit-test < %s | FileCheck %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///simple.cpp","languageId":"cpp","version":1,"text":"int x;"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/ast","params":{"textDocument":{"uri":"test:///simple.cpp"}}}
+# CHECK: "id": 1,
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": {
+# CHECK-NEXT: "arcana": "{{TranslationUnitDecl.*}}"
+# CHECK-NEXT: "children": [
+# CHECK-NEXT: {
+# CHECK: "arcana": "VarDecl {{.*}} x 'int'",
+# CHECK-NEXT: "children": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "arcana": "QualType {{.*}} 'int' ",
+# CHECK-NEXT: "detail": "int",
+# CHECK-NEXT: "kind": "Builtin",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 3,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "role": "type"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "detail": "x",
+# CHECK-NEXT: "kind": "Var",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 5,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "role": "declaration"
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "kind": "TranslationUnit",
+# CHECK-NEXT: "role": "declaration"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":2,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1725,7 +1725,9 @@
/// The position of the node to be dumped.
/// The highest-level node that entirely contains the range will be returned.
- Range range;
+ /// If no range is given, the top-level translation unit node will be
+ /// returned.
+ llvm::Optional<Range> range;
};
bool fromJSON(const llvm::json::Value &, ASTParams &, llvm::json::Path);
Index: clang-tools-extra/clangd/DumpAST.cpp
===================================================================
--- clang-tools-extra/clangd/DumpAST.cpp
+++ clang-tools-extra/clangd/DumpAST.cpp
@@ -335,6 +335,11 @@
// Override traversal to record the nodes we care about.
// Generally, these are nodes with position information (TypeLoc, not Type).
+
+ bool TraverseTUDecl(TranslationUnitDecl *TU) {
+ return traverseNode("declaration", TU, [&] {
+ Base::TraverseAST(const_cast<ASTContext &>(Ctx)); });
+ }
bool TraverseDecl(Decl *D) {
return !D || isInjectedClassName(D) ||
traverseNode("declaration", D, [&] { Base::TraverseDecl(D); });
@@ -397,11 +402,15 @@
} // namespace
+// Note: It's safe for N to be a TranslationUnitDecl, as this function
+// does not deserialize the preamble.
ASTNode dumpAST(const DynTypedNode &N, const syntax::TokenBuffer &Tokens,
const ASTContext &Ctx) {
DumpVisitor V(Tokens, Ctx);
// DynTypedNode only works with const, RecursiveASTVisitor only non-const :-(
- if (const auto *D = N.get<Decl>())
+ if (const auto *TU = N.get<TranslationUnitDecl>())
+ V.TraverseTUDecl(const_cast<TranslationUnitDecl *>(TU));
+ else if (const auto *D = N.get<Decl>())
V.TraverseDecl(const_cast<Decl *>(D));
else if (const auto *S = N.get<Stmt>())
V.TraverseStmt(const_cast<Stmt *>(S));
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -344,7 +344,8 @@
Callback<std::vector<HighlightingToken>>);
/// Describe the AST subtree for a piece of code.
- void getAST(PathRef File, Range R, Callback<llvm::Optional<ASTNode>> CB);
+ void getAST(PathRef File, llvm::Optional<Range> R,
+ Callback<llvm::Optional<ASTNode>> CB);
/// Runs an arbitrary action that has access to the AST of the specified file.
/// The action will execute on one of ClangdServer's internal threads.
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -884,22 +884,29 @@
Transient);
}
-void ClangdServer::getAST(PathRef File, Range R,
+void ClangdServer::getAST(PathRef File, llvm::Optional<Range> R,
Callback<llvm::Optional<ASTNode>> CB) {
auto Action =
[R, CB(std::move(CB))](llvm::Expected<InputsAndAST> Inputs) mutable {
if (!Inputs)
return CB(Inputs.takeError());
+ if (!R) {
+ // It's safe to pass in the TU, as dumpAST() does not
+ // deserialize the preamble.
+ auto Node = DynTypedNode::create(
+ *Inputs->AST.getASTContext().getTranslationUnitDecl());
+ return CB(dumpAST(Node, Inputs->AST.getTokens(),
+ Inputs->AST.getASTContext()));
+ }
unsigned Start, End;
- if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R.start))
+ if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R->start))
Start = *Offset;
else
return CB(Offset.takeError());
- if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R.end))
+ if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R->end))
End = *Offset;
else
return CB(Offset.takeError());
-
bool Success = SelectionTree::createEach(
Inputs->AST.getASTContext(), Inputs->AST.getTokens(), Start, End,
[&](SelectionTree T) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits