clang-tools  10.0.0
FindTarget.h
Go to the documentation of this file.
1 //===--- FindTarget.h - What does an AST node refer to? ---------*- 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 //
9 // Many clangd features are concerned with references in the AST:
10 // - xrefs, go-to-definition, explicitly talk about references
11 // - hover and code actions relate to things you "target" in the editor
12 // - refactoring actions need to know about entities that are referenced
13 // to determine whether/how the edit can be applied.
14 //
15 // Historically, we have used libIndex (IndexDataConsumer) to tie source
16 // locations to referenced declarations. This file defines a more decoupled
17 // approach based around AST nodes (DynTypedNode), and can be combined with
18 // SelectionTree or other traversals.
19 //
20 //===----------------------------------------------------------------------===//
21 
22 #ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
23 #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
24 
25 #include "clang/AST/ASTContext.h"
26 #include "clang/AST/ASTTypeTraits.h"
27 #include "clang/AST/NestedNameSpecifier.h"
28 #include "clang/AST/Stmt.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "llvm/ADT/Optional.h"
31 #include "llvm/ADT/STLExtras.h"
32 #include "llvm/ADT/SmallPtrSet.h"
33 #include "llvm/ADT/SmallVector.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 #include <bitset>
37 
38 namespace clang {
39 namespace clangd {
40 /// Describes the link between an AST node and a Decl it refers to.
41 enum class DeclRelation : unsigned;
42 /// A bitfield of DeclRelations.
43 class DeclRelationSet;
44 
45 /// targetDecl() finds the declaration referred to by an AST node.
46 /// For example a RecordTypeLoc refers to the RecordDecl for the type.
47 ///
48 /// In some cases there are multiple results, e.g. a dependent unresolved
49 /// OverloadExpr may have several candidates. All will be returned:
50 ///
51 /// void foo(int); <-- candidate
52 /// void foo(double); <-- candidate
53 /// template <typename T> callFoo() { foo(T()); }
54 /// ^ OverloadExpr
55 ///
56 /// In other cases, there may be choices about what "referred to" means.
57 /// e.g. does naming a typedef refer to the underlying type?
58 /// The results are marked with a set of DeclRelations, and can be filtered.
59 ///
60 /// struct S{}; <-- candidate (underlying)
61 /// using T = S{}; <-- candidate (alias)
62 /// T x;
63 /// ^ TypedefTypeLoc
64 ///
65 /// Formally, we walk a graph starting at the provided node, and return the
66 /// decls that were found. Certain edges in the graph have labels, and for each
67 /// decl we return the set of labels seen on a path to the decl.
68 /// For the previous example:
69 ///
70 /// TypedefTypeLoc T
71 /// |
72 /// TypedefType T
73 /// / \
74 /// [underlying] [alias]
75 /// / \
76 /// RecordDecl S TypeAliasDecl T
77 ///
78 /// Note that this function only returns NamedDecls. Generally other decls
79 /// don't have references in this sense, just the node itself.
80 /// If callers want to support such decls, they should cast the node directly.
81 ///
82 /// FIXME: some AST nodes cannot be DynTypedNodes, these cannot be specified.
83 llvm::SmallVector<const NamedDecl *, 1>
84 targetDecl(const ast_type_traits::DynTypedNode &, DeclRelationSet Mask);
85 
86 /// Similar to targetDecl(), however instead of applying a filter, all possible
87 /// decls are returned along with their DeclRelationSets.
88 /// This is suitable for indexing, where everything is recorded and filtering
89 /// is applied later.
90 llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1>
91 allTargetDecls(const ast_type_traits::DynTypedNode &);
92 
93 enum class DeclRelation : unsigned {
94  // Template options apply when the declaration is an instantiated template.
95  // e.g. [[vector<int>]] vec;
96 
97  /// This is the template instantiation that was referred to.
98  /// e.g. template<> class vector<int> (the implicit specialization)
100  /// This is the pattern the template specialization was instantiated from.
101  /// e.g. class vector<T> (the pattern within the primary template)
103 
104  // Alias options apply when the declaration is an alias.
105  // e.g. namespace clang { [[StringRef]] S; }
106 
107  /// This declaration is an alias that was referred to.
108  /// e.g. using llvm::StringRef (the UsingDecl directly referenced).
109  Alias,
110  /// This is the underlying declaration for an alias, decltype etc.
111  /// e.g. class llvm::StringRef (the underlying declaration referenced).
112  Underlying,
113 };
114 llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelation);
115 
116 /// Information about a reference written in the source code, independent of the
117 /// actual AST node that this reference lives in.
118 /// Useful for tools that are source-aware, e.g. refactorings.
119 struct ReferenceLoc {
120  /// Contains qualifier written in the code, if any, e.g. 'ns::' for 'ns::foo'.
121  NestedNameSpecifierLoc Qualifier;
122  /// Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
123  SourceLocation NameLoc;
124  /// True if the reference is a declaration or definition;
125  bool IsDecl = false;
126  // FIXME: add info about template arguments.
127  /// A list of targets referenced by this name. Normally this has a single
128  /// element, but multiple is also possible, e.g. in case of using declarations
129  /// or unresolved overloaded functions.
130  /// For dependent and unresolved references, Targets can also be empty.
131  llvm::SmallVector<const NamedDecl *, 1> Targets;
132 };
133 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R);
134 
135 /// Recursively traverse \p S and report all references explicitly written in
136 /// the code. The main use-case is refactorings that need to process all
137 /// references in some subrange of the file and apply simple edits, e.g. add
138 /// qualifiers.
139 /// FIXME: currently this does not report references to overloaded operators.
140 /// FIXME: extend to report location information about declaration names too.
141 void findExplicitReferences(const Stmt *S,
142  llvm::function_ref<void(ReferenceLoc)> Out);
143 void findExplicitReferences(const Decl *D,
144  llvm::function_ref<void(ReferenceLoc)> Out);
145 void findExplicitReferences(const ASTContext &AST,
146  llvm::function_ref<void(ReferenceLoc)> Out);
147 
148 /// Find declarations explicitly referenced in the source code defined by \p N.
149 /// For templates, will prefer to return a template instantiation whenever
150 /// possible. However, can also return a template pattern if the specialization
151 /// cannot be picked, e.g. in dependent code or when there is no corresponding
152 /// Decl for a template instantitation, e.g. for templated using decls:
153 /// template <class T> using Ptr = T*;
154 /// Ptr<int> x;
155 /// ^~~ there is no Decl for 'Ptr<int>', so we return the template pattern.
156 /// \p Mask should not contain TemplatePattern or TemplateInstantiation.
157 llvm::SmallVector<const NamedDecl *, 1>
158 explicitReferenceTargets(ast_type_traits::DynTypedNode N,
159  DeclRelationSet Mask);
160 
161 // Boring implementation details of bitfield.
162 
164  using Set = std::bitset<static_cast<unsigned>(DeclRelation::Underlying) + 1>;
165  Set S;
166  DeclRelationSet(Set S) : S(S) {}
167 
168 public:
169  DeclRelationSet() = default;
170  DeclRelationSet(DeclRelation R) { S.set(static_cast<unsigned>(R)); }
171 
172  explicit operator bool() const { return S.any(); }
174  return L.S & R.S;
175  }
177  return L.S | R.S;
178  }
180  return L.S == R.S;
181  }
182  friend DeclRelationSet operator~(DeclRelationSet R) { return ~R.S; }
184  S |= Other.S;
185  return *this;
186  }
187  DeclRelationSet &operator&=(DeclRelationSet Other) {
188  S &= Other.S;
189  return *this;
190  }
191  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
192 };
193 // The above operators can't be looked up if both sides are enums.
194 // over.match.oper.html#3.2
196  return DeclRelationSet(L) | DeclRelationSet(R);
197 }
199  return DeclRelationSet(L) & DeclRelationSet(R);
200 }
202 llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
203 
204 } // namespace clangd
205 } // namespace clang
206 
207 #endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
const FunctionDecl * Decl
friend bool operator==(DeclRelationSet L, DeclRelationSet R)
Definition: FindTarget.h:179
Information about a reference written in the source code, independent of the actual AST node that thi...
Definition: FindTarget.h:119
llvm::SmallVector< std::pair< const NamedDecl *, DeclRelationSet >, 1 > allTargetDecls(const ast_type_traits::DynTypedNode &N)
Similar to targetDecl(), however instead of applying a filter, all possible decls are returned along ...
Definition: FindTarget.cpp:486
DeclRelationSet operator~(DeclRelation R)
Definition: FindTarget.h:201
This is the pattern the template specialization was instantiated from.
DeclRelationSet(DeclRelation R)
Definition: FindTarget.h:170
This declaration is an alias that was referred to.
DeclRelationSet operator &(DeclRelation L, DeclRelation R)
Definition: FindTarget.h:198
DeclRelationSet operator|(DeclRelation L, DeclRelation R)
Definition: FindTarget.h:195
SourceLocation NameLoc
Start location of the last name part, i.e. &#39;foo&#39; in &#39;ns::foo<int>&#39;.
Definition: FindTarget.h:123
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask)
Definition: FindTarget.cpp:519
This is the template instantiation that was referred to.
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Definition: FindTarget.h:131
llvm::SmallVector< const NamedDecl *, 1 > targetDecl(const ast_type_traits::DynTypedNode &N, DeclRelationSet Mask)
targetDecl() finds the declaration referred to by an AST node.
Definition: FindTarget.cpp:509
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:867
This is the underlying declaration for an alias, decltype etc.
friend DeclRelationSet operator~(DeclRelationSet R)
Definition: FindTarget.h:182
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
NestedNameSpecifierLoc Qualifier
Contains qualifier written in the code, if any, e.g. &#39;ns::&#39; for &#39;ns::foo&#39;.
Definition: FindTarget.h:121
DeclRelationSet & operator|=(DeclRelationSet Other)
Definition: FindTarget.h:183
friend DeclRelationSet operator|(DeclRelationSet L, DeclRelationSet R)
Definition: FindTarget.h:176