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 <clang/Basic/SourceLocation.h> |
25 | #include <string> |
26 | #include <map> |
27 | #include <unordered_map> |
28 | #include <set> |
29 | #include <vector> |
30 | #include <clang/AST/Mangle.h> |
31 | #include "commenthandler.h" |
32 | #include "generator.h" |
33 | |
34 | struct ProjectManager; |
35 | struct ProjectInfo; |
36 | class PreprocessorCallback; |
37 | |
38 | namespace clang { |
39 | class Preprocessor; |
40 | class NamedDecl; |
41 | class MangleContext; |
42 | class Type; |
43 | class QualType; |
44 | class Decl; |
45 | class FileEntry; |
46 | } |
47 | |
48 | /* Wrapper for the change in the name in clang 3.5 */ |
49 | template <typename T> auto getResultType(T *decl) -> decltype(decl->getResultType()) |
50 | { return decl->getResultType(); } |
51 | template <typename T> auto getResultType(T *decl) -> decltype(decl->getReturnType()) |
52 | { return decl->getReturnType(); } |
53 | |
54 | typedef std::pair<unsigned, unsigned> pathTo_cache_key_t; |
55 | namespace std { |
56 | template <> |
57 | struct hash<pathTo_cache_key_t> |
58 | { |
59 | size_t operator()(const pathTo_cache_key_t& k) const noexcept { |
60 | return k.first ^ k.second; |
61 | } |
62 | }; |
63 | } |
64 | |
65 | class Annotator { |
66 | public: |
67 | enum DeclType { Declaration, Definition, Use, Use_Read, Use_Write, Use_Address, Use_Call, Use_MemberAccess, Use_NestedName, Override, Inherit }; |
68 | enum TokenType { Ref, Member, Type, Decl, Call, Namespace, Typedef, Enum, EnumDecl, Label }; |
69 | private: |
70 | enum class Visibility { |
71 | Local, // Local to a Function |
72 | Static, // If it is only visible to this file |
73 | Global // Globaly visible. |
74 | }; |
75 | |
76 | Visibility getVisibility(const clang::NamedDecl *); |
77 | |
78 | std::map<clang::FileID, std::pair<bool, std::string> > cache; |
79 | std::map<clang::FileID, ProjectInfo* > project_cache; |
80 | std::map<clang::FileID, Generator> generators; |
81 | |
82 | std::string htmlNameForFile(clang::FileID id); // keep a cache; |
83 | |
84 | void addReference(const std::string& ref, clang::SourceRange refLoc, Annotator::TokenType type, |
85 | Annotator::DeclType dt, const std::string &typeRef, clang::Decl *decl); |
86 | |
87 | struct Reference { |
88 | DeclType what; |
89 | clang::SourceRange loc; |
90 | std::string typeOrContext; |
91 | }; |
92 | std::map<std::string, std::vector<Reference>> references; |
93 | std::map<std::string, ssize_t> structure_sizes; |
94 | std::map<std::string, ssize_t> field_offsets; |
95 | struct SubRef { |
96 | std::string ref; |
97 | std::string type; |
98 | enum Type { None, Function, Member, Static } what = None; |
99 | }; |
100 | std::map<std::string, std::vector<SubRef>> sub_refs; |
101 | std::unordered_map<pathTo_cache_key_t, std::string> pathTo_cache; |
102 | CommentHandler commentHandler; |
103 | |
104 | std::unique_ptr<clang::MangleContext> mangle; |
105 | std::unordered_map<void *, std::pair<std::string, std::string> > mangle_cache; // canonical Decl* -> ref, escapred_title |
106 | std::pair<std::string, std::string> getReferenceAndTitle(clang::NamedDecl* decl); |
107 | // project -> { pretty name, ref } |
108 | std::map<std::string, std::string> functionIndex; |
109 | |
110 | std::unordered_map<unsigned, int> localeNumbers; |
111 | |
112 | std::map<clang::FileID, std::set<std::string> > interestingDefinitionsInFile; |
113 | |
114 | std::string args; |
115 | clang::SourceManager *sourceManager = nullptr; |
116 | const clang::LangOptions *langOption = nullptr; |
117 | |
118 | void syntaxHighlight(Generator& generator, clang::FileID FID, clang::Sema&); |
119 | public: |
120 | explicit Annotator(ProjectManager &pm) : projectManager(pm) {} |
121 | ~Annotator(); |
122 | |
123 | ProjectManager &projectManager; |
124 | |
125 | void setSourceMgr(clang::SourceManager &sm, const clang::LangOptions &lo) |
126 | { sourceManager = &sm; langOption = &lo; } |
127 | void setMangleContext(clang::MangleContext *m) { mangle.reset(m); } |
128 | clang::SourceManager &getSourceMgr() { return *sourceManager; } |
129 | const clang::LangOptions &getLangOpts() const { return *langOption; } |
130 | void setArgs(std::string a) { args = std::move(a); } |
131 | |
132 | bool generate(clang::Sema&, bool WasInDatabase); |
133 | |
134 | /** |
135 | * Returns a string with the URL to go from one file to an other. |
136 | * In case the file is in an external project that needs a data-proj tag, the proj |
137 | * string is set to the project name. |
138 | **/ |
139 | std::string pathTo(clang::FileID From, clang::FileID To, std::string *proj = nullptr); |
140 | std::string pathTo(clang::FileID From, const clang::FileEntry* To); |
141 | |
142 | /** |
143 | * Registers that the code in the given \a range refers to the specified declaration. |
144 | * This will highlight the rights portion of the code and registers it in the database. |
145 | * |
146 | * When the range.getEndLocation refers to an invalid location, this means this is a |
147 | * virtual range with no associated token (e.g. implicit conversions) which will be handled |
148 | * with an empty <span>. |
149 | * |
150 | * Only use typeRef for declarations (or definition), only use usedContext for uses |
151 | */ |
152 | void registerReference(clang::NamedDecl *decl, clang::SourceRange range, |
153 | TokenType type, DeclType declType = Annotator::Use, |
154 | std::string typeRef = std::string(), |
155 | clang::NamedDecl *usedContext = nullptr); |
156 | void registerUse(clang::NamedDecl* decl, clang::SourceRange range, TokenType tt, |
157 | clang::NamedDecl* currentContext, DeclType useType = Use) { |
158 | return registerReference(decl, range, tt, useType, {}, currentContext); |
159 | } |
160 | void registerOverride(clang::NamedDecl* decl, clang::NamedDecl* overrided, clang::SourceLocation loc); |
161 | // same, but for macro |
162 | void registerMacro(const std::string &ref, clang::SourceLocation refLoc, DeclType declType); |
163 | |
164 | // Class names, structs, objective C identifiers, main function |
165 | void registerInterestingDefinition(clang::SourceRange range, clang::NamedDecl *decl); |
166 | |
167 | /** |
168 | * Wrap the source range in an HTML tag |
169 | */ |
170 | void annotateSourceRange(clang::SourceRange range, std::string tag, std::string attributes); |
171 | |
172 | void reportDiagnostic(clang::SourceRange range, const std::string& msg, const std::string& clas); |
173 | |
174 | bool shouldProcess(clang::FileID); |
175 | Generator &generator(clang::FileID fid) { return generators[fid]; } |
176 | |
177 | std::string getTypeRef(clang::QualType type); |
178 | std::string computeClas(clang::NamedDecl* decl); |
179 | std::string getContextStr(clang::NamedDecl* usedContext); |
180 | /** |
181 | * returns the reference of a class iff this class is visible |
182 | * (that is, if a tooltip file should be generated for it) |
183 | */ |
184 | std::string getVisibleRef(clang::NamedDecl* Decl); |
185 | |
186 | std::string externalProjectForFile(clang::FileID fid); |
187 | }; |
188 | |