blob: c882ccc869f415433e162cdcdee889f329b80b73 [file] [log] [blame]
Cary Clark2da9fb82018-11-01 09:29:36 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef definition_DEFINED
9#define definition_DEFINED
10
11#include "textParser.h"
12
13class RootDefinition;
14class TextParser;
15
16class Definition : public NonAssignable {
17public:
18 enum Type {
19 kNone,
20 kWord,
21 kMark,
22 kKeyWord,
23 kBracket,
24 kPunctuation,
25 kFileType,
26 };
27
28 enum class MethodType {
29 kNone,
30 kConstructor,
31 kDestructor,
32 kOperator,
33 };
34
35 enum class Operator {
36 kUnknown,
37 kAdd,
38 kAddTo,
39 kArray,
40 kCast,
41 kCopy,
42 kDelete,
43 kDereference,
44 kEqual,
45 kMinus,
46 kMove,
47 kMultiply,
48 kMultiplyBy,
49 kNew,
50 kNotEqual,
51 kSubtract,
52 kSubtractFrom,
53 };
54
55 enum class Format {
56 kIncludeReturn,
57 kOmitReturn,
58 };
59
60 enum class Details {
61 kNone,
62 kSoonToBe_Deprecated,
63 kTestingOnly_Experiment,
64 kDoNotUse_Experiment,
65 kNotReady_Experiment,
66 };
67
68 enum class DetailsType {
69 kPhrase,
70 kSentence,
71 };
72
73 Definition() {}
74
75 Definition(const char* start, const char* end, int line, Definition* parent, char mc)
76 : fStart(start)
77 , fContentStart(start)
78 , fContentEnd(end)
79 , fParent(parent)
80 , fLineCount(line)
81 , fType(Type::kWord)
82 , fMC(mc) {
83 if (parent) {
84 SkASSERT(parent->fFileName.length() > 0);
85 fFileName = parent->fFileName;
86 }
87 this->setParentIndex();
88 }
89
90 Definition(MarkType markType, const char* start, int line, Definition* parent, char mc)
91 : Definition(markType, start, nullptr, line, parent, mc) {
92 }
93
94 Definition(MarkType markType, const char* start, const char* end, int line, Definition* parent, char mc)
95 : Definition(start, end, line, parent, mc) {
96 fMarkType = markType;
97 fType = Type::kMark;
98 }
99
100 Definition(Bracket bracket, const char* start, int lineCount, Definition* parent, char mc)
101 : Definition(start, nullptr, lineCount, parent, mc) {
102 fBracket = bracket;
103 fType = Type::kBracket;
104 }
105
106 Definition(KeyWord keyWord, const char* start, const char* end, int lineCount,
107 Definition* parent, char mc)
108 : Definition(start, end, lineCount, parent, mc) {
109 fKeyWord = keyWord;
110 fType = Type::kKeyWord;
111 }
112
113 Definition(Punctuation punctuation, const char* start, int lineCount, Definition* parent, char mc)
114 : Definition(start, nullptr, lineCount, parent, mc) {
115 fPunctuation = punctuation;
116 fType = Type::kPunctuation;
117 }
118
119 virtual ~Definition() {}
120
121 virtual RootDefinition* asRoot() { SkASSERT(0); return nullptr; }
122 bool boilerplateIfDef();
123
124 bool boilerplateEndIf() {
125 return true;
126 }
127
128 bool checkMethod() const;
129 bool crossCheck2(const Definition& includeToken) const;
130 bool crossCheck(const Definition& includeToken) const;
131 bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
132
133 Definition* csParent() {
134 Definition* test = fParent;
135 while (test) {
136 if (MarkType::kStruct == test->fMarkType || MarkType::kClass == test->fMarkType) {
137 return test;
138 }
139 test = test->fParent;
140 }
141 return nullptr;
142 }
143
144 string fiddleName() const;
145 string fileName() const;
146 const Definition* findClone(string match) const;
147 string formatFunction(Format format) const;
148 const Definition* hasChild(MarkType markType) const;
149 bool hasMatch(string name) const;
150 Definition* hasParam(string ref);
Cary Clark2da9fb82018-11-01 09:29:36 -0400151 bool isClone() const { return fClone; }
152
153 const Definition* iRootParent() const {
154 const Definition* test = fParent;
155 while (test) {
156 if (KeyWord::kClass == test->fKeyWord || KeyWord::kStruct == test->fKeyWord) {
157 return test;
158 }
159 test = test->fParent;
160 }
161 return nullptr;
162 }
163
164 virtual bool isRoot() const { return false; }
165 bool isStructOrClass() const;
166
167 int length() const {
168 return (int) (fContentEnd - fContentStart);
169 }
170
171 const char* methodEnd() const;
172 bool methodHasReturn(string name, TextParser* methodParser) const;
173 string methodName() const;
174 bool nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
175 string* paramName) const;
176 static string NormalizedName(string name);
177 bool paramsMatch(string fullRef, string name) const;
178 bool parseOperator(size_t doubleColons, string& result);
179
180 string printableName() const {
181 string result(fName);
182 std::replace(result.begin(), result.end(), '_', ' ');
183 return result;
184 }
185
186 template <typename T> T reportError(const char* errorStr) const {
187 TextParser tp(this);
188 tp.reportError(errorStr);
189 return T();
190 }
191
192 virtual RootDefinition* rootParent() { SkASSERT(0); return nullptr; }
193 virtual const RootDefinition* rootParent() const { SkASSERT(0); return nullptr; }
194 void setCanonicalFiddle();
195
196 void setParentIndex() {
197 fParentIndex = fParent ? (int) fParent->fTokens.size() : -1;
198 }
199
Cary Clarkfd32e722018-11-16 14:36:02 -0500200 static bool SkipImplementationWords(TextParser& inc);
201
Cary Clark2da9fb82018-11-01 09:29:36 -0400202 string simpleName() {
203 size_t doubleColon = fName.rfind("::");
204 return string::npos == doubleColon ? fName : fName.substr(doubleColon + 2);
205 }
206
207 const Definition* subtopicParent() const {
208 Definition* test = fParent;
209 while (test) {
210 if (MarkType::kTopic == test->fMarkType || MarkType::kSubtopic == test->fMarkType) {
211 return test;
212 }
213 test = test->fParent;
214 }
215 return nullptr;
216 }
217
218 const Definition* topicParent() const {
219 Definition* test = fParent;
220 while (test) {
221 if (MarkType::kTopic == test->fMarkType) {
222 return test;
223 }
224 test = test->fParent;
225 }
226 return nullptr;
227 }
228
229 void trimEnd();
230
231 string fText; // if text is constructed instead of in a file, it's put here
232 const char* fStart = nullptr; // .. in original text file, or the start of fText
233 const char* fContentStart; // start past optional markup name
234 string fName;
235 string fFiddle; // if its a constructor or operator, fiddle name goes here
236 string fCode; // suitable for autogeneration of #Code blocks in bmh
237 const char* fContentEnd = nullptr; // the end of the contained text
238 const char* fTerminator = nullptr; // the end of the markup, normally ##\n or \n
239 Definition* fParent = nullptr;
240 list<Definition> fTokens;
241 vector<Definition*> fChildren;
242 string fHash; // generated by fiddle
243 string fFileName;
244 mutable string fWrapper; // used by Example to wrap into proper function
245 size_t fLineCount = 0;
246 int fParentIndex = 0;
247 MarkType fMarkType = MarkType::kNone;
248 KeyWord fKeyWord = KeyWord::kNone;
249 Bracket fBracket = Bracket::kNone;
250 Punctuation fPunctuation = Punctuation::kNone;
251 MethodType fMethodType = MethodType::kNone;
252 Operator fOperator = Operator::kUnknown;
253 Type fType = Type::kNone;
254 char fMC = '#';
255 bool fClone = false;
256 bool fCloned = false;
Cary Clark2da9fb82018-11-01 09:29:36 -0400257 bool fOperatorConst = false;
258 bool fPrivate = false;
259 Details fDetails = Details::kNone;
260 bool fMemberStart = false;
261 bool fAnonymous = false;
Cary Clarkabaffd82018-11-15 08:25:12 -0500262 bool fUndocumented = false; // include symbol comment has deprecated, private, experimental
Cary Clark2da9fb82018-11-01 09:29:36 -0400263 mutable bool fVisited = false;
264};
265
266class RootDefinition : public Definition {
267public:
268 enum class AllowParens {
269 kNo,
270 kYes,
271 };
272
273 struct SubtopicContents {
274 SubtopicContents()
275 : fShowClones(false) {
276 }
277
278 vector<Definition*> fMembers;
279 bool fShowClones;
280 };
281
282 RootDefinition() {
283 }
284
285 RootDefinition(MarkType markType, const char* start, int line, Definition* parent, char mc)
286 : Definition(markType, start, line, parent, mc) {
287 if (MarkType::kSubtopic != markType && MarkType::kTopic != markType) {
288 if (parent) {
289 fNames.fName = parent->fName;
290 fNames.fParent = &parent->asRoot()->fNames;
291 }
292 }
293 }
294
295 RootDefinition(MarkType markType, const char* start, const char* end, int line,
296 Definition* parent, char mc) : Definition(markType, start, end, line, parent, mc) {
297 }
298
299 ~RootDefinition() override {
300 for (auto& iter : fBranches) {
301 delete iter.second;
302 }
303 }
304
305 RootDefinition* asRoot() override { return this; }
306 void clearVisited();
307 bool dumpUnVisited();
308 Definition* find(string ref, AllowParens );
309 bool isRoot() const override { return true; }
310
311 SubtopicContents& populator(const char* key) {
312 return fPopulators[key];
313 }
314
315 RootDefinition* rootParent() override { return fRootParent; }
316 const RootDefinition* rootParent() const override { return fRootParent; }
317 void setRootParent(RootDefinition* rootParent) { fRootParent = rootParent; }
318
319 unordered_map<string, RootDefinition*> fBranches;
320 unordered_map<string, Definition> fLeaves;
321 unordered_map<string, SubtopicContents> fPopulators;
322 NameMap fNames;
323private:
324 RootDefinition* fRootParent = nullptr;
325};
326
327#endif