1/****************************************************************************
2 * Copyright (C) 2012-2016 Woboq GmbH
3 * Olivier Goffart <contact at woboq.com>
4 * https://woboq.com/codebrowser.html
5 *
6 * This file is part of the Woboq Code Browser.
7 *
8 * Commercial License Usage:
9 * Licensees holding valid commercial licenses provided by Woboq may use
10 * this file in accordance with the terms contained in a written agreement
11 * between the licensee and Woboq.
12 * For further information see https://woboq.com/codebrowser.html
13 *
14 * Alternatively, this work may be used under a Creative Commons
15 * Attribution-NonCommercial-ShareAlike 3.0 (CC-BY-NC-SA 3.0) License.
16 * http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US
17 * This license does not allow you to use the code browser to assist the
18 * development of your commercial software. If you intent to do so, consider
19 * purchasing a commercial licence.
20 ****************************************************************************/
21
22#pragma once
23
24#include "commenthandler.h"
25#include "generator.h"
26#include <clang/AST/Mangle.h>
27#include <clang/Basic/SourceLocation.h>
28#include <map>
29#include <set>
30#include <string>
31#include <unordered_map>
32#include <vector>
33
34struct ProjectManager;
35struct ProjectInfo;
36class PreprocessorCallback;
37
38namespace clang {
39class Preprocessor;
40class NamedDecl;
41class MangleContext;
42class Type;
43class QualType;
44class Decl;
45class FileEntry;
46}
47
48/* Wrapper for the change in the name in clang 3.5 */
49template<typename T>
50auto getResultType(T *decl) -> decltype(decl->getResultType())
51{
52 return decl->getResultType();
53}
54template<typename T>
55auto getResultType(T *decl) -> decltype(decl->getReturnType())
56{
57 return decl->getReturnType();
58}
59
60typedef std::pair<unsigned, unsigned> pathTo_cache_key_t;
61namespace std {
62template<>
63struct hash<pathTo_cache_key_t>
64{
65 size_t operator()(const pathTo_cache_key_t &k) const noexcept
66 {
67 return k.first ^ k.second;
68 }
69};
70}
71
72class Annotator
73{
74public:
75 enum DeclType {
76 Declaration,
77 Definition,
78 Use,
79 Use_Read,
80 Use_Write,
81 Use_Address,
82 Use_Call,
83 Use_MemberAccess,
84 Use_NestedName,
85 Override,
86 Inherit
87 };
88 enum TokenType {
89 Ref,
90 Member,
91 Type,
92 Decl,
93 Call,
94 Namespace,
95 Typedef,
96 Enum,
97 EnumDecl,
98 Label
99 };
100
101private:
102 enum class Visibility {
103 Local, // Local to a Function
104 Static, // If it is only visible to this file
105 Global // Globaly visible.
106 };
107
108 Visibility getVisibility(const clang::NamedDecl *);
109
110 std::map<clang::FileID, std::pair<bool, std::string>> cache;
111 std::map<clang::FileID, ProjectInfo *> project_cache;
112 std::map<clang::FileID, Generator> generators;
113
114 std::string htmlNameForFile(clang::FileID id); // keep a cache;
115
116 void addReference(const std::string &ref, clang::SourceRange refLoc, Annotator::TokenType type,
117 Annotator::DeclType dt, const std::string &typeRef, clang::Decl *decl);
118
119 struct Reference
120 {
121 DeclType what;
122 clang::SourceRange loc;
123 std::string typeOrContext;
124 };
125 std::map<std::string, std::vector<Reference>> references;
126 std::map<std::string, ssize_t> structure_sizes;
127 std::map<std::string, ssize_t> field_offsets;
128 struct SubRef
129 {
130 std::string ref;
131 std::string type;
132 enum Type {
133 None,
134 Function,
135 Member,
136 Static
137 } what = None;
138 };
139 std::map<std::string, std::vector<SubRef>> sub_refs;
140 std::unordered_map<pathTo_cache_key_t, std::string> pathTo_cache;
141 CommentHandler commentHandler;
142
143 std::unique_ptr<clang::MangleContext> mangle;
144 std::unordered_map<void *, std::pair<std::string, std::string>> mangle_cache; // canonical Decl*
145 // -> ref,
146 // escapred_title
147 std::pair<std::string, std::string> getReferenceAndTitle(clang::NamedDecl *decl);
148 // project -> { pretty name, ref }
149 std::map<std::string, std::string> functionIndex;
150
151 std::unordered_map<unsigned, int> localeNumbers;
152
153 std::map<clang::FileID, std::set<std::string>> interestingDefinitionsInFile;
154
155 std::string args;
156 clang::SourceManager *sourceManager = nullptr;
157 const clang::LangOptions *langOption = nullptr;
158
159 void syntaxHighlight(Generator &generator, clang::FileID FID, clang::Sema &);
160
161public:
162 explicit Annotator(ProjectManager &pm)
163 : projectManager(pm)
164 {
165 }
166 ~Annotator();
167
168 ProjectManager &projectManager;
169
170 void setSourceMgr(clang::SourceManager &sm, const clang::LangOptions &lo)
171 {
172 sourceManager = &sm;
173 langOption = &lo;
174 }
175 void setMangleContext(clang::MangleContext *m)
176 {
177 mangle.reset(p: m);
178 }
179 clang::SourceManager &getSourceMgr()
180 {
181 return *sourceManager;
182 }
183 const clang::LangOptions &getLangOpts() const
184 {
185 return *langOption;
186 }
187 void setArgs(std::string a)
188 {
189 args = std::move(a);
190 }
191
192 bool generate(clang::Sema &, bool WasInDatabase);
193
194 /**
195 * Returns a string with the URL to go from one file to an other.
196 * In case the file is in an external project that needs a data-proj tag, the proj
197 * string is set to the project name.
198 **/
199 std::string pathTo(clang::FileID From, clang::FileID To, std::string *proj = nullptr);
200 std::string pathTo(clang::FileID From, const clang::FileEntry *To);
201
202 /**
203 * Registers that the code in the given \a range refers to the specified declaration.
204 * This will highlight the rights portion of the code and registers it in the database.
205 *
206 * When the range.getEndLocation refers to an invalid location, this means this is a
207 * virtual range with no associated token (e.g. implicit conversions) which will be handled
208 * with an empty <span>.
209 *
210 * Only use typeRef for declarations (or definition), only use usedContext for uses
211 */
212 void registerReference(clang::NamedDecl *decl, clang::SourceRange range, TokenType type,
213 DeclType declType = Annotator::Use, std::string typeRef = std::string(),
214 clang::NamedDecl *usedContext = nullptr);
215 void registerUse(clang::NamedDecl *decl, clang::SourceRange range, TokenType tt,
216 clang::NamedDecl *currentContext, DeclType useType = Use)
217 {
218 return registerReference(decl, range, type: tt, declType: useType, typeRef: {}, usedContext: currentContext);
219 }
220 void registerOverride(clang::NamedDecl *decl, clang::NamedDecl *overrided,
221 clang::SourceLocation loc);
222 // same, but for macro
223 void registerMacro(const std::string &ref, clang::SourceLocation refLoc, DeclType declType);
224
225 // Class names, structs, objective C identifiers, main function
226 void registerInterestingDefinition(clang::SourceRange range, clang::NamedDecl *decl);
227
228 /**
229 * Wrap the source range in an HTML tag
230 */
231 void annotateSourceRange(clang::SourceRange range, std::string tag, std::string attributes);
232
233 void reportDiagnostic(clang::SourceRange range, const std::string &msg,
234 const std::string &clas);
235
236 void addInlayHint(clang::SourceLocation range, std::string inlayHint);
237
238 bool shouldProcess(clang::FileID);
239 Generator &generator(clang::FileID fid)
240 {
241 return generators[fid];
242 }
243
244 std::string getTypeRef(clang::QualType type);
245 std::string computeClas(clang::NamedDecl *decl);
246 std::string getContextStr(clang::NamedDecl *usedContext);
247 /**
248 * returns the reference of a class iff this class is visible
249 * (that is, if a tooltip file should be generated for it)
250 */
251 std::string getVisibleRef(clang::NamedDecl *Decl);
252
253 std::string externalProjectForFile(clang::FileID fid);
254
255 /**
256 * Returns the param name in function decl for the arg @p arg
257 * Will be empty if arg->name == paramDecl->name
258 */
259 std::string getParamNameForArg(clang::CallExpr *callExpr, clang::ParmVarDecl *paramDecl,
260 clang::Expr *arg);
261
262 llvm::DenseMap<clang::SourceLocation, std::string>
263 getDesignatorInlayHints(clang::InitListExpr *Syn);
264};
265

source code of codebrowser/generator/annotator.h