Author: sammccall
Date: Mon Jul 22 08:55:53 2019
New Revision: 366698
URL: http://llvm.org/viewvc/llvm-project?rev=366698=rev
Log:
[clangd] Add dlog()s for SelectionTree, enabling -debug-only=SelectionTree.cpp
Summary:
SelectionTree is a RecursiveASTVisitor which processes getSourceRange() for
every node. This is a lot of surface area with the AST, as getSourceRange()
is specialized for *many* node types.
And the resulting SelectionTree depends on the source ranges of many
visited nodes, and the order of traversal.
Put together, this means we really need a traversal log to debug when we
get an unexpected SelectionTree. I've built this ad-hoc a few times, now
it's time to check it in.
Example output:
```
D[14:07:44.184] Computing selection for
D[14:07:44.184] push: VarDecl const auto x = 42
D[14:07:44.184] claimRange:
D[14:07:44.184] push: NestedNameSpecifierLoc (empty NestedNameSpecifierLoc)
D[14:07:44.184] pop: NestedNameSpecifierLoc (empty NestedNameSpecifierLoc)
D[14:07:44.184] push: QualifiedTypeLoc const auto
D[14:07:44.184] pop: QualifiedTypeLoc const auto
D[14:07:44.184]claimRange:
D[14:07:44.184]hit selection:
D[14:07:44.184] skip: IntegerLiteral 42
D[14:07:44.184]skipped range =
D[14:07:44.184] pop: VarDecl const auto x = 42
D[14:07:44.184] claimRange:
D[14:07:44.184] skip: VarDecl int y = 43
D[14:07:44.184] skipped range =
D[14:07:44.184] Built selection tree
TranslationUnitDecl
VarDecl const auto x = 42
.QualifiedTypeLoc const auto
```
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65073
Modified:
clang-tools-extra/trunk/clangd/Selection.cpp
clang-tools-extra/trunk/clangd/Selection.h
Modified: clang-tools-extra/trunk/clangd/Selection.cpp
URL:
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Selection.cpp?rev=366698=366697=366698=diff
==
--- clang-tools-extra/trunk/clangd/Selection.cpp (original)
+++ clang-tools-extra/trunk/clangd/Selection.cpp Mon Jul 22 08:55:53 2019
@@ -8,15 +8,19 @@
#include "Selection.h"
#include "ClangdUnit.h"
+#include "Logger.h"
#include "SourceCode.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include
+#include
namespace clang {
namespace clangd {
@@ -59,6 +63,31 @@ private:
std::vector> Ranges; // Always sorted.
};
+// Dump a node for debugging.
+// DynTypedNode::print() doesn't include the kind of node, which is useful.
+void printNode(llvm::raw_ostream , const DynTypedNode ,
+ const PrintingPolicy ) {
+ if (const TypeLoc *TL = N.get()) {
+// TypeLoc is a hierarchy, but has only a single ASTNodeKind.
+// Synthesize the name from the Type subclass (except for
QualifiedTypeLoc).
+if (TL->getTypeLocClass() == TypeLoc::Qualified)
+ OS << "QualifiedTypeLoc";
+else
+ OS << TL->getType()->getTypeClassName() << "TypeLoc";
+ } else {
+OS << N.getNodeKind().asStringRef();
+ }
+ OS << " ";
+ N.print(OS, PP);
+}
+
+std::string printNodeToString(const DynTypedNode , const PrintingPolicy )
{
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ printNode(OS, N, PP);
+ return std::move(OS.str());
+}
+
// We find the selection by visiting written nodes in the AST, looking for
nodes
// that intersect with the selected character range.
//
@@ -71,9 +100,9 @@ class SelectionVisitor : public Recursiv
public:
// Runs the visitor to gather selected nodes and their ancestors.
// If there is any selection, the root (TUDecl) is the first node.
- static std::deque collect(ASTContext , unsigned Begin,
- unsigned End, FileID File) {
-SelectionVisitor V(AST, Begin, End, File);
+ static std::deque collect(ASTContext , const PrintingPolicy ,
+ unsigned Begin, unsigned End, FileID File) {
+SelectionVisitor V(AST, PP, Begin, End, File);
V.TraverseAST(AST);
assert(V.Stack.size() == 1 && "Unpaired push/pop?");
assert(V.Stack.top() == ());
@@ -114,9 +143,12 @@ public:
}
// Stmt is the same, but this form allows the data recursion optimization.
bool dataTraverseStmtPre(Stmt *X) {
-if (!X || canSafelySkipNode(X->getSourceRange()))
+if (!X)
+ return false;
+auto N = DynTypedNode::create(*X);
+if (canSafelySkipNode(N))
return false;
-push(DynTypedNode::create(*X));
+push(std::move(N));
return true;
}
bool dataTraverseStmtPost(Stmt *X) {
@@ -130,10 +162,10 @@ public:
private:
using Base = RecursiveASTVisitor;
-