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.
65 class SelectionTree {
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).
87 Unselected,
88 // The AST node owns selected characters, but is not completely covered.
89 Partial,
90 // The AST node owns characters, and is covered by the selection.
91 Complete,
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.
97 Node *Parent;
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.
103 Selection Selected;
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
clang::clangd::SelectionTree::Node::kind
std::string kind() const
Definition: Selection.cpp:659
clang::clangd::SelectionTree::Node
Definition: Selection.h:95
clang::clangd::SelectionTree::Node::Children
llvm::SmallVector< const Node *, 8 > Children
Definition: Selection.h:99
clang::clangd::SelectionTree::Node::ignoreImplicit
const Node & ignoreImplicit() const
Definition: Selection.cpp:733
clang::clangd::SelectionTree::SelectionTree
SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Offset)
Definition: Selection.cpp:706
clang::clangd::SelectionTree::Node::Selected
Selection Selected
Definition: Selection.h:103
clang::clangd::SelectionTree::Node::outerImplicit
const Node & outerImplicit() const
Definition: Selection.cpp:740
clang::clangd::SelectionTree::root
const Node & root() const
Definition: Selection.h:121
clang::clangd::SymbolOrigin::AST
clang::clangd::SelectionTree::Node::Parent
Node * Parent
Definition: Selection.h:97
clang::clangd::SelectionTree::Partial
Definition: Selection.h:89
clang::clangd::SelectionTree::operator<<
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const SelectionTree &T)
Definition: Selection.h:129
clang::clangd::SelectionTree::Selection
Selection
Definition: Selection.h:79
Offset
size_t Offset
Definition: CodeComplete.cpp:1022
clang::clangd::SelectionTree::Complete
Definition: Selection.h:91
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::SelectionTree::Unselected
Definition: Selection.h:87
clang::clangd::SelectionTree
Definition: Selection.h:65
clang::clangd::SelectionTree::Node::ASTNode
ast_type_traits::DynTypedNode ASTNode
Definition: Selection.h:101
clang::clangd::SelectionTree::commonAncestor
const Node * commonAncestor() const
Definition: Selection.cpp:710
clang::clangd::SelectionTree::Node::getDeclContext
const DeclContext & getDeclContext() const
Definition: Selection.cpp:720