clang-tools  14.0.0git
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 class HeuristicResolver;
41 
42 /// Describes the link between an AST node and a Decl it refers to.
43 enum class DeclRelation : unsigned;
44 /// A bitfield of DeclRelations.
45 class DeclRelationSet;
46 
47 /// targetDecl() finds the declaration referred to by an AST node.
48 /// For example a RecordTypeLoc refers to the RecordDecl for the type.
49 ///
50 /// In some cases there are multiple results, e.g. a dependent unresolved
51 /// OverloadExpr may have several candidates. All will be returned:
52 ///
53 /// void foo(int); <-- candidate
54 /// void foo(double); <-- candidate
55 /// template <typename T> callFoo() { foo(T()); }
56 /// ^ OverloadExpr
57 ///
58 /// In other cases, there may be choices about what "referred to" means.
59 /// e.g. does naming a typedef refer to the underlying type?
60 /// The results are marked with a set of DeclRelations, and can be filtered.
61 ///
62 /// struct S{}; <-- candidate (underlying)
63 /// using T = S{}; <-- candidate (alias)
64 /// T x;
65 /// ^ TypedefTypeLoc
66 ///
67 /// Formally, we walk a graph starting at the provided node, and return the
68 /// decls that were found. Certain edges in the graph have labels, and for each
69 /// decl we return the set of labels seen on a path to the decl.
70 /// For the previous example:
71 ///
72 /// TypedefTypeLoc T
73 /// |
74 /// TypedefType T
75 /// / \
76 /// [underlying] [alias]
77 /// / \
78 /// RecordDecl S TypeAliasDecl T
79 ///
80 /// Note that this function only returns NamedDecls. Generally other decls
81 /// don't have references in this sense, just the node itself.
82 /// If callers want to support such decls, they should cast the node directly.
83 ///
84 /// FIXME: some AST nodes cannot be DynTypedNodes, these cannot be specified.
85 llvm::SmallVector<const NamedDecl *, 1>
86 targetDecl(const DynTypedNode &, DeclRelationSet Mask,
87  const HeuristicResolver *Resolver);
88 
89 /// Similar to targetDecl(), however instead of applying a filter, all possible
90 /// decls are returned along with their DeclRelationSets.
91 /// This is suitable for indexing, where everything is recorded and filtering
92 /// is applied later.
93 llvm::SmallVector<std::pair<const NamedDecl *, DeclRelationSet>, 1>
94 allTargetDecls(const DynTypedNode &, const HeuristicResolver *);
95 
96 enum class DeclRelation : unsigned {
97  // Template options apply when the declaration is an instantiated template.
98  // e.g. [[vector<int>]] vec;
99 
100  /// This is the template instantiation that was referred to.
101  /// e.g. template<> class vector<int> (the implicit specialization)
103  /// This is the pattern the template specialization was instantiated from.
104  /// e.g. class vector<T> (the pattern within the primary template)
106 
107  // Alias options apply when the declaration is an alias.
108  // e.g. namespace client { [[X]] x; }
109 
110  /// This declaration is an alias that was referred to.
111  /// e.g. using ns::X (the UsingDecl directly referenced),
112  /// using Z = ns::Y (the TypeAliasDecl directly referenced)
113  Alias,
114  /// This is the underlying declaration for a renaming-alias, decltype etc.
115  /// e.g. class ns::Y (the underlying declaration referenced).
116  ///
117  /// Note that we don't treat `using ns::X` as a first-class declaration like
118  /// `using Z = ns::Y`. Therefore reference to X that goes through this
119  /// using-decl is considered a direct reference (without the Underlying bit).
120  /// Nevertheless, we report `using ns::X` as an Alias, so that some features
121  /// like go-to-definition can still target it.
122  Underlying,
123 };
124 llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelation);
125 
126 /// Information about a reference written in the source code, independent of the
127 /// actual AST node that this reference lives in.
128 /// Useful for tools that are source-aware, e.g. refactorings.
129 struct ReferenceLoc {
130  /// Contains qualifier written in the code, if any, e.g. 'ns::' for 'ns::foo'.
131  NestedNameSpecifierLoc Qualifier;
132  /// Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
133  SourceLocation NameLoc;
134  /// True if the reference is a declaration or definition;
135  bool IsDecl = false;
136  // FIXME: add info about template arguments.
137  /// A list of targets referenced by this name. Normally this has a single
138  /// element, but multiple is also possible, e.g. in case of using declarations
139  /// or unresolved overloaded functions.
140  /// For dependent and unresolved references, Targets can also be empty.
141  llvm::SmallVector<const NamedDecl *, 1> Targets;
142 };
143 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R);
144 
145 /// Recursively traverse \p S and report all references explicitly written in
146 /// the code. The main use-case is refactorings that need to process all
147 /// references in some subrange of the file and apply simple edits, e.g. add
148 /// qualifiers.
149 /// FIXME: currently this does not report references to overloaded operators.
150 /// FIXME: extend to report location information about declaration names too.
151 void findExplicitReferences(const Stmt *S,
152  llvm::function_ref<void(ReferenceLoc)> Out,
153  const HeuristicResolver *Resolver);
154 void findExplicitReferences(const Decl *D,
155  llvm::function_ref<void(ReferenceLoc)> Out,
156  const HeuristicResolver *Resolver);
157 void findExplicitReferences(const ASTContext &AST,
158  llvm::function_ref<void(ReferenceLoc)> Out,
159  const HeuristicResolver *Resolver);
160 
161 /// Find declarations explicitly referenced in the source code defined by \p N.
162 /// For templates, will prefer to return a template instantiation whenever
163 /// possible. However, can also return a template pattern if the specialization
164 /// cannot be picked, e.g. in dependent code or when there is no corresponding
165 /// Decl for a template instantiation, e.g. for templated using decls:
166 /// template <class T> using Ptr = T*;
167 /// Ptr<int> x;
168 /// ^~~ there is no Decl for 'Ptr<int>', so we return the template pattern.
169 /// \p Mask should not contain TemplatePattern or TemplateInstantiation.
170 llvm::SmallVector<const NamedDecl *, 1>
171 explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask,
172  const HeuristicResolver *Resolver);
173 
174 // Boring implementation details of bitfield.
175 
177  using Set = std::bitset<static_cast<unsigned>(DeclRelation::Underlying) + 1>;
178  Set S;
179  DeclRelationSet(Set S) : S(S) {}
180 
181 public:
182  DeclRelationSet() = default;
183  DeclRelationSet(DeclRelation R) { S.set(static_cast<unsigned>(R)); }
184 
185  explicit operator bool() const { return S.any(); }
187  return L.S & R.S;
188  }
190  return L.S | R.S;
191  }
193  return L.S == R.S;
194  }
195  friend DeclRelationSet operator~(DeclRelationSet R) { return ~R.S; }
197  S |= Other.S;
198  return *this;
199  }
201  S &= Other.S;
202  return *this;
203  }
204  bool contains(DeclRelationSet Other) const {
205  return (S & Other.S) == Other.S;
206  }
207  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
208 };
209 // The above operators can't be looked up if both sides are enums.
210 // over.match.oper.html#3.2
212  return DeclRelationSet(L) | DeclRelationSet(R);
213 }
215  return DeclRelationSet(L) & DeclRelationSet(R);
216 }
218 llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
219 
220 } // namespace clangd
221 } // namespace clang
222 
223 #endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
clang::clangd::ReferenceLoc::NameLoc
SourceLocation NameLoc
Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
Definition: FindTarget.h:133
clang::clangd::operator~
DeclRelationSet operator~(DeclRelation R)
Definition: FindTarget.h:217
clang::clangd::DeclRelationSet::operator|
friend DeclRelationSet operator|(DeclRelationSet L, DeclRelationSet R)
Definition: FindTarget.h:189
clang::clangd::DeclRelation
DeclRelation
Definition: FindTarget.h:96
clang::clangd::HeuristicResolver
Definition: HeuristicResolver.h:46
clang::clangd::DeclRelationSet
Definition: FindTarget.h:176
clang::clangd::operator&
DeclRelationSet operator&(DeclRelation L, DeclRelation R)
Definition: FindTarget.h:214
clang::clangd::ReferenceLoc::Qualifier
NestedNameSpecifierLoc Qualifier
Contains qualifier written in the code, if any, e.g. 'ns::' for 'ns::foo'.
Definition: FindTarget.h:131
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
clang::clangd::DeclRelationSet::DeclRelationSet
DeclRelationSet(DeclRelation R)
Definition: FindTarget.h:183
clang::clangd::DeclRelationSet::operator==
friend bool operator==(DeclRelationSet L, DeclRelationSet R)
Definition: FindTarget.h:192
clang::clangd::DeclRelationSet::operator&
friend DeclRelationSet operator&(DeclRelationSet L, DeclRelationSet R)
Definition: FindTarget.h:186
clang::clangd::DeclRelationSet::operator&=
DeclRelationSet & operator&=(DeclRelationSet Other)
Definition: FindTarget.h:200
clang::clangd::explicitReferenceTargets
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask, const HeuristicResolver *Resolver)
Find declarations explicitly referenced in the source code defined by N.
Definition: FindTarget.cpp:557
clang::clangd::DeclRelation::Underlying
@ Underlying
This is the underlying declaration for a renaming-alias, decltype etc.
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:2013
clang::clangd::ReferenceLoc
Information about a reference written in the source code, independent of the actual AST node that thi...
Definition: FindTarget.h:129
clang::clangd::DeclRelationSet::DeclRelationSet
DeclRelationSet()=default
clang::clangd::DeclRelationSet::contains
bool contains(DeclRelationSet Other) const
Definition: FindTarget.h:204
clang::clangd::operator|
DeclRelationSet operator|(DeclRelation L, DeclRelation R)
Definition: FindTarget.h:211
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:163
clang::clangd::DeclRelationSet::operator~
friend DeclRelationSet operator~(DeclRelationSet R)
Definition: FindTarget.h:195
clang::clangd::allTargetDecls
llvm::SmallVector< std::pair< const NamedDecl *, DeclRelationSet >, 1 > allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver)
Similar to targetDecl(), however instead of applying a filter, all possible decls are returned along ...
Definition: FindTarget.cpp:520
clang::clangd::DeclRelationSet::operator|=
DeclRelationSet & operator|=(DeclRelationSet Other)
Definition: FindTarget.h:196
clang::clangd::targetDecl
llvm::SmallVector< const NamedDecl *, 1 > targetDecl(const DynTypedNode &N, DeclRelationSet Mask, const HeuristicResolver *Resolver)
targetDecl() finds the declaration referred to by an AST node.
Definition: FindTarget.cpp:546
clang::clangd::ReferenceLoc::IsDecl
bool IsDecl
True if the reference is a declaration or definition;.
Definition: FindTarget.h:135
clang::clangd::DeclRelationSet::operator<<
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &, DeclRelationSet)
Definition: FindTarget.cpp:1146
clang::clangd::DeclRelation::TemplateInstantiation
@ TemplateInstantiation
This is the template instantiation that was referred to.
Out
CompiledFragmentImpl & Out
Definition: ConfigCompile.cpp:100
clang::clangd::findExplicitReferences
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out, const HeuristicResolver *Resolver)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:1114
clang::clangd::DeclRelation::TemplatePattern
@ TemplatePattern
This is the pattern the template specialization was instantiated from.
clang::clangd::ReferenceLoc::Targets
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Definition: FindTarget.h:141
clang::clangd::DeclRelation::Alias
@ Alias
This declaration is an alias that was referred to.