blob: 80a8e787d625034294fed4307c61fb0c7935ba67 [file] [log] [blame]
Sam McCall489cc582019-09-03 11:35:50 +00001//===--- 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
Haojian Wuc00627f2019-09-25 12:54:53 +000022#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
23#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H
24
Sam McCall489cc582019-09-03 11:35:50 +000025#include "clang/AST/ASTTypeTraits.h"
Ilya Biryukovf96d2e12019-09-25 12:40:22 +000026#include "clang/AST/NestedNameSpecifier.h"
27#include "clang/AST/Stmt.h"
Sam McCall489cc582019-09-03 11:35:50 +000028#include "clang/Basic/SourceLocation.h"
Ilya Biryukovf96d2e12019-09-25 12:40:22 +000029#include "llvm/ADT/Optional.h"
30#include "llvm/ADT/STLExtras.h"
Sam McCall489cc582019-09-03 11:35:50 +000031#include "llvm/ADT/SmallPtrSet.h"
Ilya Biryukovf96d2e12019-09-25 12:40:22 +000032#include "llvm/ADT/SmallVector.h"
33#include "llvm/Support/raw_ostream.h"
Sam McCall489cc582019-09-03 11:35:50 +000034
35#include <bitset>
36
37namespace clang {
38namespace clangd {
39/// Describes the link between an AST node and a Decl it refers to.
40enum class DeclRelation : unsigned;
41/// A bitfield of DeclRelations.
42class DeclRelationSet;
43
44/// targetDecl() finds the declaration referred to by an AST node.
45/// For example a RecordTypeLoc refers to the RecordDecl for the type.
46///
47/// In some cases there are multiple results, e.g. a dependent unresolved
48/// OverloadExpr may have several candidates. All will be returned:
49///
50/// void foo(int); <-- candidate
51/// void foo(double); <-- candidate
52/// template <typename T> callFoo() { foo(T()); }
53/// ^ OverloadExpr
54///
55/// In other cases, there may be choices about what "referred to" means.
56/// e.g. does naming a typedef refer to the underlying type?
57/// The results are marked with a set of DeclRelations, and can be filtered.
58///
59/// struct S{}; <-- candidate (underlying)
60/// using T = S{}; <-- candidate (alias)
61/// T x;
62/// ^ TypedefTypeLoc
63///
64/// Formally, we walk a graph starting at the provided node, and return the
65/// decls that were found. Certain edges in the graph have labels, and for each
66/// decl we return the set of labels seen on a path to the decl.
67/// For the previous example:
68///
69/// TypedefTypeLoc T
70/// |
71/// TypedefType T
72/// / \
73/// [underlying] [alias]
74/// / \
75/// RecordDecl S TypeAliasDecl T
76///
77/// FIXME: some AST nodes cannot be DynTypedNodes, these cannot be specified.
78llvm::SmallVector<const Decl *, 1>
79targetDecl(const ast_type_traits::DynTypedNode &, DeclRelationSet Mask);
80
Ilya Biryukovf96d2e12019-09-25 12:40:22 +000081/// Information about a reference written in the source code, independent of the
82/// actual AST node that this reference lives in.
83/// Useful for tools that are source-aware, e.g. refactorings.
84struct ReferenceLoc {
85 /// Contains qualifier written in the code, if any, e.g. 'ns::' for 'ns::foo'.
86 NestedNameSpecifierLoc Qualifier;
87 /// Start location of the last name part, i.e. 'foo' in 'ns::foo<int>'.
88 SourceLocation NameLoc;
89 // FIXME: add info about template arguments.
90 /// A list of targets referenced by this name. Normally this has a single
91 /// element, but multiple is also possible, e.g. in case of using declarations
92 /// or unresolved overloaded functions.
93 /// For dependent and unresolved references, Targets can also be empty.
94 llvm::SmallVector<const NamedDecl *, 1> Targets;
95};
96llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R);
97
98/// Recursively traverse \p S and report all references explicitly written in
99/// the code. The main use-case is refactorings that need to process all
100/// references in some subrange of the file and apply simple edits, e.g. add
101/// qualifiers.
102/// FIXME: currently this does not report references to overloaded operators.
103/// FIXME: extend to report location information about declaration names too.
Kadir Cetinkaya007e4fe2019-09-25 15:44:26 +0000104void findExplicitReferences(const Stmt *S,
Ilya Biryukovf96d2e12019-09-25 12:40:22 +0000105 llvm::function_ref<void(ReferenceLoc)> Out);
Kadir Cetinkaya007e4fe2019-09-25 15:44:26 +0000106void findExplicitReferences(const Decl *D,
Ilya Biryukovf96d2e12019-09-25 12:40:22 +0000107 llvm::function_ref<void(ReferenceLoc)> Out);
108
Sam McCall489cc582019-09-03 11:35:50 +0000109/// Similar to targetDecl(), however instead of applying a filter, all possible
110/// decls are returned along with their DeclRelationSets.
111/// This is suitable for indexing, where everything is recorded and filtering
112/// is applied later.
113llvm::SmallVector<std::pair<const Decl *, DeclRelationSet>, 1>
114allTargetDecls(const ast_type_traits::DynTypedNode &);
115
116enum class DeclRelation : unsigned {
117 // Template options apply when the declaration is an instantiated template.
118 // e.g. [[vector<int>]] vec;
119
120 /// This is the template instantiation that was referred to.
121 /// e.g. template<> class vector<int> (the implicit specialization)
122 TemplateInstantiation,
123 /// This is the pattern the template specialization was instantiated from.
124 /// e.g. class vector<T> (the pattern within the primary template)
125 TemplatePattern,
126
127 // Alias options apply when the declaration is an alias.
128 // e.g. namespace clang { [[StringRef]] S; }
129
130 /// This declaration is an alias that was referred to.
131 /// e.g. using llvm::StringRef (the UsingDecl directly referenced).
132 Alias,
133 /// This is the underlying declaration for an alias, decltype etc.
134 /// e.g. class llvm::StringRef (the underlying declaration referenced).
135 Underlying,
136};
137llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelation);
138
139class DeclRelationSet {
140 using Set = std::bitset<static_cast<unsigned>(DeclRelation::Underlying) + 1>;
141 Set S;
142 DeclRelationSet(Set S) : S(S) {}
143
144public:
145 DeclRelationSet() = default;
146 DeclRelationSet(DeclRelation R) { S.set(static_cast<unsigned>(R)); }
147
148 explicit operator bool() const { return S.any(); }
149 friend DeclRelationSet operator&(DeclRelationSet L, DeclRelationSet R) {
150 return L.S & R.S;
151 }
152 friend DeclRelationSet operator|(DeclRelationSet L, DeclRelationSet R) {
153 return L.S | R.S;
154 }
155 friend bool operator==(DeclRelationSet L, DeclRelationSet R) {
156 return L.S == R.S;
157 }
158 friend DeclRelationSet operator~(DeclRelationSet R) { return ~R.S; }
159 DeclRelationSet &operator|=(DeclRelationSet Other) {
160 S |= Other.S;
161 return *this;
162 }
163 DeclRelationSet &operator&=(DeclRelationSet Other) {
164 S &= Other.S;
165 return *this;
166 }
167 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
168};
169// The above operators can't be looked up if both sides are enums.
170// over.match.oper.html#3.2
171inline DeclRelationSet operator|(DeclRelation L, DeclRelation R) {
172 return DeclRelationSet(L) | DeclRelationSet(R);
173}
174inline DeclRelationSet operator&(DeclRelation L, DeclRelation R) {
175 return DeclRelationSet(L) & DeclRelationSet(R);
176}
177inline DeclRelationSet operator~(DeclRelation R) { return ~DeclRelationSet(R); }
178llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelationSet);
179
180} // namespace clangd
181} // namespace clang
Haojian Wuc00627f2019-09-25 12:54:53 +0000182
183#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_FINDTARGET_H