clang-tools  9.0.0
Selection.cpp
Go to the documentation of this file.
1 //===--- Selection.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Selection.h"
10 #include "ClangdUnit.h"
11 #include "clang/AST/ASTTypeTraits.h"
12 #include "clang/AST/PrettyPrinter.h"
13 #include "clang/AST/RecursiveASTVisitor.h"
14 #include "clang/AST/TypeLoc.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include <algorithm>
17 
18 namespace clang {
19 namespace clangd {
20 namespace {
21 using Node = SelectionTree::Node;
22 using ast_type_traits::DynTypedNode;
23 
24 // Stores a collection of (possibly-overlapping) integer ranges.
25 // When new ranges are added, hit-tests them against existing ones.
26 class RangeSet {
27 public:
28  // Returns true if any new offsets are covered.
29  // This is naive (linear in number of successful add() calls), but ok for now.
30  bool add(unsigned Begin, unsigned End) {
31  assert(std::is_sorted(Ranges.begin(), Ranges.end()));
32  assert(Begin < End);
33 
34  if (covered(Begin, End))
35  return false;
36  auto Pair = std::make_pair(Begin, End);
37  Ranges.insert(llvm::upper_bound(Ranges, Pair), Pair);
38  return true;
39  }
40 
41 private:
42  bool covered(unsigned Begin, unsigned End) {
43  assert(Begin < End);
44  for (const auto &R : Ranges) {
45  if (Begin < R.first)
46  return false; // The prefix [Begin, R.first) is not covered.
47  if (Begin < R.second) {
48  Begin = R.second; // Prefix is covered, truncate the range.
49  if (Begin >= End)
50  return true;
51  }
52  }
53  return false;
54  }
55 
56  std::vector<std::pair<unsigned, unsigned>> Ranges; // Always sorted.
57 };
58 
59 // We find the selection by visiting written nodes in the AST, looking for nodes
60 // that intersect with the selected character range.
61 //
62 // While traversing, we maintain a parent stack. As nodes pop off the stack,
63 // we decide whether to keep them or not. To be kept, they must either be
64 // selected or contain some nodes that are.
65 //
66 // For simple cases (not inside macros) we prune subtrees that don't intersect.
67 class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
68 public:
69  // Runs the visitor to gather selected nodes and their ancestors.
70  // If there is any selection, the root (TUDecl) is the first node.
71  static std::deque<Node> collect(ASTContext &AST, unsigned Begin,
72  unsigned End, FileID File) {
73  SelectionVisitor V(AST, Begin, End, File);
74  V.TraverseAST(AST);
75  assert(V.Stack.size() == 1 && "Unpaired push/pop?");
76  assert(V.Stack.top() == &V.Nodes.front());
77  if (V.Nodes.size() == 1) // TUDecl, but no nodes under it.
78  V.Nodes.clear();
79  return std::move(V.Nodes);
80  }
81 
82  // We traverse all "well-behaved" nodes the same way:
83  // - push the node onto the stack
84  // - traverse its children recursively
85  // - pop it from the stack
86  // - hit testing: is intersection(node, selection) - union(children) empty?
87  // - attach it to the tree if it or any children hit the selection
88  //
89  // Two categories of nodes are not "well-behaved":
90  // - those without source range information, we don't record those
91  // - those that can't be stored in DynTypedNode.
92  // We're missing some interesting things like Attr due to the latter.
93  bool TraverseDecl(Decl *X) {
94  if (X && isa<TranslationUnitDecl>(X))
95  return Base::TraverseDecl(X); // Already pushed by constructor.
96  // Base::TraverseDecl will suppress children, but not this node itself.
97  if (X && X->isImplicit())
98  return true;
99  return traverseNode(X, [&] { return Base::TraverseDecl(X); });
100  }
101  bool TraverseTypeLoc(TypeLoc X) {
102  return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); });
103  }
104  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc X) {
105  return traverseNode(
106  &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); });
107  }
108  bool TraverseConstructorInitializer(CXXCtorInitializer *X) {
109  return traverseNode(
110  X, [&] { return Base::TraverseConstructorInitializer(X); });
111  }
112  // Stmt is the same, but this form allows the data recursion optimization.
113  bool dataTraverseStmtPre(Stmt *X) {
114  if (!X || canSafelySkipNode(X->getSourceRange()))
115  return false;
116  push(DynTypedNode::create(*X));
117  return true;
118  }
119  bool dataTraverseStmtPost(Stmt *X) {
120  pop();
121  return true;
122  }
123  // Uninteresting parts of the AST that don't have locations within them.
124  bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
125  bool TraverseType(QualType) { return true; }
126 
127 private:
128  using Base = RecursiveASTVisitor<SelectionVisitor>;
129 
130  SelectionVisitor(ASTContext &AST, unsigned SelBegin, unsigned SelEnd,
131  FileID SelFile)
132  : SM(AST.getSourceManager()), LangOpts(AST.getLangOpts()),
133  SelBegin(SelBegin), SelEnd(SelEnd), SelFile(SelFile),
134  SelBeginTokenStart(SM.getFileOffset(Lexer::GetBeginningOfToken(
135  SM.getComposedLoc(SelFile, SelBegin), SM, LangOpts))) {
136  // Ensure we have a node for the TU decl, regardless of traversal scope.
137  Nodes.emplace_back();
138  Nodes.back().ASTNode = DynTypedNode::create(*AST.getTranslationUnitDecl());
139  Nodes.back().Parent = nullptr;
140  Nodes.back().Selected = SelectionTree::Unselected;
141  Stack.push(&Nodes.back());
142  }
143 
144  // Generic case of TraverseFoo. Func should be the call to Base::TraverseFoo.
145  // Node is always a pointer so the generic code can handle any null checks.
146  template <typename T, typename Func>
147  bool traverseNode(T *Node, const Func &Body) {
148  if (Node == nullptr || canSafelySkipNode(Node->getSourceRange()))
149  return true;
150  push(DynTypedNode::create(*Node));
151  bool Ret = Body();
152  pop();
153  return Ret;
154  }
155 
156  // HIT TESTING
157  //
158  // We do rough hit testing on the way down the tree to avoid traversing
159  // subtrees that don't touch the selection (canSafelySkipNode), but
160  // fine-grained hit-testing is mostly done on the way back up (in pop()).
161  // This means children get to claim parts of the selection first, and parents
162  // are only selected if they own tokens that no child owned.
163  //
164  // Nodes *usually* nest nicely: a child's getSourceRange() lies within the
165  // parent's, and a node (transitively) owns all tokens in its range.
166  //
167  // Exception 1: child range claims tokens that should be owned by the parent.
168  // e.g. in `void foo(int);`, the FunctionTypeLoc should own
169  // `void (int)` but the parent FunctionDecl should own `foo`.
170  // To handle this case, certain nodes claim small token ranges *before*
171  // their children are traversed. (see earlySourceRange).
172  //
173  // Exception 2: siblings both claim the same node.
174  // e.g. `int x, y;` produces two sibling VarDecls.
175  // ~~~~~ x
176  // ~~~~~~~~ y
177  // Here the first ("leftmost") sibling claims the tokens it wants, and the
178  // other sibling gets what's left. So selecting "int" only includes the left
179  // VarDecl in the selection tree.
180 
181  // An optimization for a common case: nodes outside macro expansions that
182  // don't intersect the selection may be recursively skipped.
183  bool canSafelySkipNode(SourceRange S) {
184  auto B = SM.getDecomposedLoc(S.getBegin());
185  auto E = SM.getDecomposedLoc(S.getEnd());
186  if (B.first != SelFile || E.first != SelFile)
187  return false;
188  return B.second >= SelEnd || E.second < SelBeginTokenStart;
189  }
190 
191  // Pushes a node onto the ancestor stack. Pairs with pop().
192  // Performs early hit detection for some nodes (on the earlySourceRange).
193  void push(DynTypedNode Node) {
194  bool SelectedEarly = claimRange(earlySourceRange(Node));
195  Nodes.emplace_back();
196  Nodes.back().ASTNode = std::move(Node);
197  Nodes.back().Parent = Stack.top();
198  // Early hit detection never selects the whole node.
199  Nodes.back().Selected =
201  Stack.push(&Nodes.back());
202  }
203 
204  // Pops a node off the ancestor stack, and finalizes it. Pairs with push().
205  // Performs primary hit detection.
206  void pop() {
207  Node &N = *Stack.top();
208  if (auto Sel = claimRange(N.ASTNode.getSourceRange()))
209  N.Selected = Sel;
210  if (N.Selected || !N.Children.empty()) {
211  // Attach to the tree.
212  N.Parent->Children.push_back(&N);
213  } else {
214  // Neither N any children are selected, it doesn't belong in the tree.
215  assert(&N == &Nodes.back());
216  Nodes.pop_back();
217  }
218  Stack.pop();
219  }
220 
221  // Returns the range of tokens that this node will claim directly, and
222  // is not available to the node's children.
223  // Usually empty, but sometimes children cover tokens but shouldn't own them.
224  SourceRange earlySourceRange(const DynTypedNode &N) {
225  if (const Decl *D = N.get<Decl>()) {
226  // void [[foo]]();
227  if (auto *FD = llvm::dyn_cast<FunctionDecl>(D))
228  return FD->getNameInfo().getSourceRange();
229  // int (*[[s]])();
230  else if (auto *VD = llvm::dyn_cast<VarDecl>(D))
231  return VD->getLocation();
232  }
233  return SourceRange();
234  }
235 
236  // Perform hit-testing of a complete Node against the selection.
237  // This runs for every node in the AST, and must be fast in common cases.
238  // This is usually called from pop(), so we can take children into account.
239  SelectionTree::Selection claimRange(SourceRange S) {
240  if (!S.isValid())
242  // getTopMacroCallerLoc() allows selection of constructs in macro args. e.g:
243  // #define LOOP_FOREVER(Body) for(;;) { Body }
244  // void IncrementLots(int &x) {
245  // LOOP_FOREVER( ++x; )
246  // }
247  // Selecting "++x" or "x" will do the right thing.
248  auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
249  auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
250  // Otherwise, nodes in macro expansions can't be selected.
251  if (B.first != SelFile || E.first != SelFile)
253  // Cheap test: is there any overlap at all between the selection and range?
254  // Note that E.second is the *start* of the last token, which is why we
255  // compare against the "rounded-down" SelBegin.
256  if (B.second >= SelEnd || E.second < SelBeginTokenStart)
258 
259  // We may have hit something, need some more precise checks.
260  // Adjust [B, E) to be a half-open character range.
261  E.second += Lexer::MeasureTokenLength(S.getEnd(), SM, LangOpts);
262  auto PreciseBounds = std::make_pair(B.second, E.second);
263  // Trim range using the selection, drop it if empty.
264  B.second = std::max(B.second, SelBegin);
265  E.second = std::min(E.second, SelEnd);
266  if (B.second >= E.second)
268  // Attempt to claim the remaining range. If there's nothing to claim, only
269  // children were selected.
270  if (!Claimed.add(B.second, E.second))
272  // Some of our own characters are covered, this is a true hit.
273  // Determine whether the node was completely covered.
274  return (PreciseBounds.first >= SelBegin && PreciseBounds.second <= SelEnd)
277  }
278 
279  SourceManager &SM;
280  const LangOptions &LangOpts;
281  std::stack<Node *> Stack;
282  RangeSet Claimed;
283  std::deque<Node> Nodes; // Stable pointers as we add more nodes.
284  // Half-open selection range.
285  unsigned SelBegin;
286  unsigned SelEnd;
287  FileID SelFile;
288  // If the selection start slices a token in half, the beginning of that token.
289  // This is useful for checking whether the end of a token range overlaps
290  // the selection: range.end < SelBeginTokenStart is equivalent to
291  // range.end + measureToken(range.end) < SelBegin (assuming range.end points
292  // to a token), and it saves a lex every time.
293  unsigned SelBeginTokenStart;
294 };
295 
296 } // namespace
297 
298 void SelectionTree::print(llvm::raw_ostream &OS, const SelectionTree::Node &N,
299  int Indent) const {
300  if (N.Selected)
301  OS.indent(Indent - 1) << (N.Selected == SelectionTree::Complete ? '*'
302  : '.');
303  else
304  OS.indent(Indent);
305  if (const TypeLoc *TL = N.ASTNode.get<TypeLoc>()) {
306  // TypeLoc is a hierarchy, but has only a single ASTNodeKind.
307  // Synthesize the name from the Type subclass (except for QualifiedTypeLoc).
308  if (TL->getTypeLocClass() == TypeLoc::Qualified)
309  OS << "QualifiedTypeLoc";
310  else
311  OS << TL->getType()->getTypeClassName() << "TypeLoc";
312  } else {
313  OS << N.ASTNode.getNodeKind().asStringRef();
314  }
315  OS << " ";
316  N.ASTNode.print(OS, PrintPolicy);
317  OS << "\n";
318  for (const Node *Child : N.Children)
319  print(OS, *Child, Indent + 2);
320 }
321 
322 // Decide which selection emulates a "point" query in between characters.
323 static std::pair<unsigned, unsigned> pointBounds(unsigned Offset, FileID FID,
324  ASTContext &AST) {
325  StringRef Buf = AST.getSourceManager().getBufferData(FID);
326  // Edge-cases where the choice is forced.
327  if (Buf.size() == 0)
328  return {0, 0};
329  if (Offset == 0)
330  return {0, 1};
331  if (Offset == Buf.size())
332  return {Offset - 1, Offset};
333  // We could choose either this byte or the previous. Usually we prefer the
334  // character on the right of the cursor (or under a block cursor).
335  // But if that's whitespace, we likely want the token on the left.
336  if (isWhitespace(Buf[Offset]) && !isWhitespace(Buf[Offset - 1]))
337  return {Offset - 1, Offset};
338  return {Offset, Offset + 1};
339 }
340 
341 SelectionTree::SelectionTree(ASTContext &AST, unsigned Begin, unsigned End)
342  : PrintPolicy(AST.getLangOpts()) {
343  // No fundamental reason the selection needs to be in the main file,
344  // but that's all clangd has needed so far.
345  FileID FID = AST.getSourceManager().getMainFileID();
346  if (Begin == End)
347  std::tie(Begin, End) = pointBounds(Begin, FID, AST);
348  PrintPolicy.TerseOutput = true;
349  PrintPolicy.IncludeNewlines = false;
350 
351  Nodes = SelectionVisitor::collect(AST, Begin, End, FID);
352  Root = Nodes.empty() ? nullptr : &Nodes.front();
353 }
354 
355 SelectionTree::SelectionTree(ASTContext &AST, unsigned Offset)
356  : SelectionTree(AST, Offset, Offset) {}
357 
358 const Node *SelectionTree::commonAncestor() const {
359  if (!Root)
360  return nullptr;
361  const Node *Ancestor = Root;
362  while (Ancestor->Children.size() == 1 && !Ancestor->Selected)
363  Ancestor = Ancestor->Children.front();
364  return Ancestor;
365 }
366 
367 const DeclContext& SelectionTree::Node::getDeclContext() const {
368  for (const Node* CurrentNode = this; CurrentNode != nullptr;
369  CurrentNode = CurrentNode->Parent) {
370  if (const Decl* Current = CurrentNode->ASTNode.get<Decl>()) {
371  if (CurrentNode != this)
372  if (auto *DC = dyn_cast<DeclContext>(Current))
373  return *DC;
374  return *Current->getDeclContext();
375  }
376  }
377  llvm_unreachable("A tree must always be rooted at TranslationUnitDecl.");
378 }
379 
380 } // namespace clangd
381 } // namespace clang
llvm::SmallVector< const Node *, 8 > Children
Definition: Selection.h:91
static std::pair< unsigned, unsigned > pointBounds(unsigned Offset, FileID FID, ASTContext &AST)
Definition: Selection.cpp:323
const Decl * D
Definition: XRefs.cpp:868
size_t Offset
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static URISchemeRegistry::Add< TestScheme > X(TestScheme::Scheme, "Test schema")
SelectionTree(ASTContext &AST, unsigned Offset)
Definition: Selection.cpp:355
const Node * commonAncestor() const
Definition: Selection.cpp:358
std::unique_ptr< GlobalCompilationDatabase > Base
const DeclContext & getDeclContext() const
Definition: Selection.cpp:367