clang-tools  10.0.0
Selection.h
Go to the documentation of this file.
1 //===--- Selection.h - What's under the cursor? -------------------*-C++-*-===//
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 // Many features are triggered at locations/ranges and operate on AST nodes.
9 // (e.g. go-to-definition or code tweaks).
10 // At a high level, such features need to work out which node is the correct
11 // target.
12 //
13 // There are a few levels of ambiguity here:
14 //
15 // Which tokens are included:
16 // int x = one + two; // what should "go to definition" do?
17 // ^^^^^^
18 //
19 // Same token means multiple things:
20 // string("foo") // class string, or a constructor?
21 // ^
22 //
23 // Which level of the AST is interesting?
24 // if (err) { // reference to 'err', or operator bool(),
25 // ^ // or the if statement itself?
26 //
27 // Here we build and expose a data structure that allows features to resolve
28 // these ambiguities in an appropriate way:
29 // - we determine which low-level nodes are partly or completely covered
30 // by the selection.
31 // - we expose a tree of the selected nodes and their lexical parents.
32 //===----------------------------------------------------------------------===//
33 
34 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SELECTION_H
35 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SELECTION_H
36 #include "clang/AST/ASTTypeTraits.h"
37 #include "clang/AST/PrettyPrinter.h"
38 #include "clang/Tooling/Syntax/Tokens.h"
39 #include "llvm/ADT/SmallVector.h"
40 
41 namespace clang {
42 namespace clangd {
43 
44 // A selection can partially or completely cover several AST nodes.
45 // The SelectionTree contains nodes that are covered, and their parents.
46 // SelectionTree does not contain all AST nodes, rather only:
47 // Decl, Stmt, TypeLoc, NestedNamespaceSpecifierLoc, CXXCtorInitializer.
48 // (These are the nodes with source ranges that fit in DynTypedNode).
49 //
50 // Usually commonAncestor() is the place to start:
51 // - it's the simplest answer to "what node is under the cursor"
52 // - the selected Expr (for example) can be found by walking up the parent
53 // chain and checking Node->ASTNode.
54 // - if you want to traverse the selected nodes, they are all under
55 // commonAncestor() in the tree.
56 //
57 // SelectionTree tries to behave sensibly in the presence of macros, but does
58 // not model any preprocessor concepts: the output is a subset of the AST.
59 //
60 // Comments, directives and whitespace are completely ignored.
61 // Semicolons are also ignored, as the AST generally does not model them well.
62 //
63 // The SelectionTree owns the Node structures, but the ASTNode attributes
64 // point back into the AST it was constructed with.
66 public:
67  // Creates a selection tree at the given byte offset in the main file.
68  // This is approximately equivalent to a range of one character.
69  // (Usually, the character to the right of Offset, sometimes to the left).
70  SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens,
71  unsigned Offset);
72  // Creates a selection tree for the given range in the main file.
73  // The range includes bytes [Start, End).
74  // If Start == End, uses the same heuristics as SelectionTree(AST, Start).
75  SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens,
76  unsigned Start, unsigned End);
77 
78  // Describes to what extent an AST node is covered by the selection.
79  enum Selection : unsigned char {
80  // The AST node owns no characters covered by the selection.
81  // Note that characters owned by children don't count:
82  // if (x == 0) scream();
83  // ^^^^^^
84  // The IfStmt would be Unselected because all the selected characters are
85  // associated with its children.
86  // (Invisible nodes like ImplicitCastExpr are always unselected).
88  // The AST node owns selected characters, but is not completely covered.
90  // The AST node owns characters, and is covered by the selection.
92  };
93  // An AST node that is implicated in the selection.
94  // (Either selected directly, or some descendant is selected).
95  struct Node {
96  // The parent within the selection tree. nullptr for TranslationUnitDecl.
98  // Direct children within the selection tree.
99  llvm::SmallVector<const Node *, 8> Children;
100  // The corresponding node from the full AST.
101  ast_type_traits::DynTypedNode ASTNode;
102  // The extent to which this node is covered by the selection.
104  // Walk up the AST to get the DeclContext of this Node,
105  // which is not the node itself.
106  const DeclContext& getDeclContext() const;
107  // Printable node kind, like "CXXRecordDecl" or "AutoTypeLoc".
108  std::string kind() const;
109  // If this node is a wrapper with no syntax (e.g. implicit cast), return
110  // its contents. (If multiple wrappers are present, unwraps all of them).
111  const Node& ignoreImplicit() const;
112  // If this node is inside a wrapper with no syntax (e.g. implicit cast),
113  // return that wrapper. (If multiple are present, unwraps all of them).
114  const Node& outerImplicit() const;
115  };
116  // The most specific common ancestor of all the selected nodes.
117  // Returns nullptr if the common ancestor is the root.
118  // (This is to avoid accidentally traversing the TUDecl and thus preamble).
119  const Node *commonAncestor() const;
120  // The selection node corresponding to TranslationUnitDecl.
121  const Node &root() const { return *Root; }
122 
123 private:
124  std::deque<Node> Nodes; // Stable-pointer storage.
125  const Node *Root;
126  clang::PrintingPolicy PrintPolicy;
127 
128  void print(llvm::raw_ostream &OS, const Node &N, int Indent) const;
129  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
130  const SelectionTree &T) {
131  T.print(OS, T.root(), 1);
132  return OS;
133  }
134 };
135 
136 } // namespace clangd
137 } // namespace clang
138 #endif
llvm::SmallVector< const Node *, 8 > Children
Definition: Selection.h:99
const Node & ignoreImplicit() const
Definition: Selection.cpp:733
SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Offset)
Definition: Selection.cpp:706
const Node & outerImplicit() const
Definition: Selection.cpp:740
const Node & root() const
Definition: Selection.h:121
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const SelectionTree &T)
Definition: Selection.h:129
size_t Offset
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
ast_type_traits::DynTypedNode ASTNode
Definition: Selection.h:101
const Node * commonAncestor() const
Definition: Selection.cpp:710
const DeclContext & getDeclContext() const
Definition: Selection.cpp:720