blob: 34e6f61701f89302516735005c1a9374dc19c01a [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 includeParser_DEFINED
9#define includeParser_DEFINED
10
11#include "SkString.h"
12
13#include "parserCommon.h"
14
15class BmhParser;
16
17struct IClassDefinition : public Definition {
18 unordered_map<string, Definition*> fConsts;
19 unordered_map<string, Definition*> fDefines;
20 unordered_map<string, Definition*> fEnums;
21 unordered_map<string, Definition*> fMembers;
22 unordered_map<string, Definition*> fMethods;
23 unordered_map<string, Definition*> fStructs;
24 unordered_map<string, Definition*> fTypedefs;
25};
26
27class IncludeParser : public ParserCommon {
28public:
29 enum class IsStruct {
30 kNo,
31 kYes,
32 };
33
34 enum class Elided {
35 kNo,
36 kYes,
37 };
38
Cary Clarkfd32e722018-11-16 14:36:02 -050039 enum class Suggest {
40 kMethodMissing,
41 kMethodDiffers,
42 };
43
Cary Clark2da9fb82018-11-01 09:29:36 -040044 struct CheckCode {
45 enum class State {
46 kNone,
47 kClassDeclaration,
48 kConstructor,
49 kForwardDeclaration,
50 kMethod,
51 };
52
53 void reset() {
54 fInDebugCode = nullptr;
55 fPrivateBrace = 0;
56 fBraceCount = 0;
57 fIndent = 0;
58 fDoubleReturn = 0;
59 fState = State::kNone;
60 fPrivateProtected = false;
61 fTypedefReturn = false;
62 fSkipAPI = false;
63 fSkipInline = false;
64 fSkipWarnUnused = false;
65 fWriteReturn = false;
66 }
67
68 const char* fInDebugCode;
69 int fPrivateBrace;
70 int fBraceCount;
71 int fIndent;
72 int fDoubleReturn;
73 State fState;
74 bool fPrivateProtected;
75 bool fTypedefReturn;
76 bool fSkipAPI;
77 bool fSkipInline;
78 bool fSkipWarnUnused;
79 bool fWriteReturn;
80 };
81
82 IncludeParser() : ParserCommon()
83 , fMaps {
84 { &fIConstMap, MarkType::kConst }
85 , { &fIDefineMap, MarkType::kDefine }
86 , { &fIEnumMap, MarkType::kEnum }
87 , { &fIEnumMap, MarkType::kEnumClass }
88 , { &fIStructMap, MarkType::kStruct }
89 , { &fITemplateMap, MarkType::kTemplate }
90 , { &fITypedefMap, MarkType::kTypedef }
91 , { &fIUnionMap, MarkType::kUnion }
92 }
93 {
94 this->reset();
95 }
96
97 ~IncludeParser() override {}
98
99 void addKeyword(KeyWord keyWord);
100
101 void addPunctuation(Punctuation punctuation) {
102 fParent->fTokens.emplace_back(punctuation, fChar, fLineCount, fParent, '\0');
103 }
104
105 void addWord() {
106 fParent->fTokens.emplace_back(fIncludeWord, fChar, fLineCount, fParent, '\0');
107 fIncludeWord = nullptr;
108 }
109
110 bool advanceInclude(TextParser& i);
111 bool inAlignAs() const;
112 void checkForMissingParams(const vector<string>& methodParams,
113 const vector<string>& foundParams);
114 bool checkForWord();
Cary Clarkfd32e722018-11-16 14:36:02 -0500115 void checkTokens(list<Definition>& tokens, string key, string className,
116 RootDefinition* root, BmhParser& bmhParser);
Cary Clark2da9fb82018-11-01 09:29:36 -0400117 string className() const;
118
119 string codeBlock(const Definition& def, bool inProgress) const {
120 return codeBlock(def.fMarkType, def.fName, inProgress);
121 }
122
123 string codeBlock(MarkType markType, string name, bool inProgress) const {
124 if (MarkType::kClass == markType || MarkType::kStruct == markType) {
125 auto map = fIClassMap.find(name);
126 SkASSERT(fIClassMap.end() != map || inProgress);
127 return fIClassMap.end() != map ? map->second.fCode : "";
128 }
129 if (MarkType::kConst == markType) {
130 auto map = fIConstMap.find(name);
131 SkASSERT(fIConstMap.end() != map);
132 return map->second->fCode;
133 }
134 if (MarkType::kDefine == markType) {
135 auto map = fIDefineMap.find(name);
136 SkASSERT(fIDefineMap.end() != map);
137 return map->second->fCode;
138 }
139 if (MarkType::kEnum == markType || MarkType::kEnumClass == markType) {
140 auto map = fIEnumMap.find(name);
141 SkASSERT(fIEnumMap.end() != map);
142 return map->second->fCode;
143 }
144 if (MarkType::kTypedef == markType) {
145 auto map = fITypedefMap.find(name);
146 SkASSERT(fITypedefMap.end() != map);
147 return map->second->fCode;
148 }
149 SkASSERT(0);
150 return "";
151 }
152
153 void codeBlockAppend(string& result, char ch) const;
154 void codeBlockSpaces(string& result, int indent) const;
155
156 bool crossCheck(BmhParser& );
157 IClassDefinition* defineClass(const Definition& includeDef, string className);
158 void dumpClassTokens(IClassDefinition& classDef);
159 void dumpComment(const Definition& );
160 void dumpCommonTail(const Definition& );
161 void dumpConst(const Definition& , string className);
162 void dumpDefine(const Definition& );
163 void dumpEnum(const Definition& , string name);
164 bool dumpGlobals(string* globalFileName, long int* globalTell);
165 void dumpMethod(const Definition& , string className);
166 void dumpMember(const Definition& );
167 bool dumpTokens();
168 bool dumpTokens(string skClassName, string globalFileName, long int* globalTell);
169 void dumpTypedef(const Definition& , string className);
170
171 string elidedCodeBlock(const Definition& );
172 string filteredBlock(string inContents, string filterContents);
Cary Clarkabaffd82018-11-15 08:25:12 -0500173 bool findCommentAfter(const Definition& includeDef, Definition* markupDef);
Cary Clark2da9fb82018-11-01 09:29:36 -0400174 bool findComments(const Definition& includeDef, Definition* markupDef);
175 Definition* findIncludeObject(const Definition& includeDef, MarkType markType,
176 string typeName);
177 static KeyWord FindKey(const char* start, const char* end);
178 Definition* findMethod(const Definition& bmhDef);
179 Bracket grandParentBracket() const;
180 const Definition* include(string ) const;
181 bool isClone(const Definition& token);
182 bool isConstructor(const Definition& token, string className);
183 bool isInternalName(const Definition& token);
184 bool isMember(const Definition& token) const;
185 bool isOperator(const Definition& token);
Cary Clarkabaffd82018-11-15 08:25:12 -0500186 bool isUndocumentable(string filename, const char* start, const char* end, int lineCount);
Cary Clark2da9fb82018-11-01 09:29:36 -0400187 Definition* parentBracket(Definition* parent) const;
188 bool parseChar();
189 bool parseComment(string filename, const char* start, const char* end, int lineCount,
Cary Clarkabaffd82018-11-15 08:25:12 -0500190 Definition* markupDef, bool* undocumentedPtr);
Cary Clark2da9fb82018-11-01 09:29:36 -0400191 bool parseClass(Definition* def, IsStruct);
192 bool parseConst(Definition* child, Definition* markupDef);
193 bool parseDefine(Definition* child, Definition* markupDef);
194 bool parseEnum(Definition* child, Definition* markupDef);
Cary Clarkabaffd82018-11-15 08:25:12 -0500195 bool parseEnumConst(list<Definition>::iterator& tokenIter,
196 const list<Definition>::iterator& tokenEnd, Definition* markupChild);
Cary Clark2da9fb82018-11-01 09:29:36 -0400197
198 bool parseFromFile(const char* path) override {
199 this->reset();
200 if (!INHERITED::parseSetup(path)) {
201 return false;
202 }
203 string name(path);
204 return this->parseInclude(name);
205 }
206
207 bool parseInclude(string name);
208 bool parseMember(Definition* child, Definition* markupDef);
209 bool parseMethod(Definition* child, Definition* markupDef);
210 bool parseObject(Definition* child, Definition* markupDef);
211 bool parseObjects(Definition* parent, Definition* markupDef);
Cary Clarkabaffd82018-11-15 08:25:12 -0500212 bool parseOneEnumConst(list<Definition>& constList, Definition* markupChild, bool skipWord);
Cary Clark2da9fb82018-11-01 09:29:36 -0400213 bool parseTemplate(Definition* child, Definition* markupDef);
214 bool parseTypedef(Definition* child, Definition* markupDef);
215 bool parseUsing();
216 bool parseUnion();
217
218 void popBracket() {
219 if (Definition::Type::kKeyWord == fParent->fType
220 && KeyWord::kTypename == fParent->fKeyWord) {
221 this->popObject();
222 }
223 SkASSERT(Definition::Type::kBracket == fParent->fType);
224 this->popObject();
225 Bracket bracket = this->topBracket();
226 this->setBracketShortCuts(bracket);
227 }
228
229 void pushBracket(Bracket bracket) {
Cary Clarkabaffd82018-11-15 08:25:12 -0500230 if ("#else" == string(fChar, 5)) {
231 SkDebugf("");
232 }
Cary Clark2da9fb82018-11-01 09:29:36 -0400233 this->setBracketShortCuts(bracket);
234 fParent->fTokens.emplace_back(bracket, fChar, fLineCount, fParent, '\0');
235 Definition* container = &fParent->fTokens.back();
236 this->addDefinition(container);
237 }
238
239 bool references(const SkString& file) const;
240
241 static void RemoveFile(const char* docs, const char* includes);
242 static void RemoveOneFile(const char* docs, const char* includesFileOrPath);
243
244 void reset() override {
245 INHERITED::resetCommon();
246 fRootTopic = nullptr;
247 fConstExpr = nullptr;
248 fInBrace = nullptr;
249 fIncludeWord = nullptr;
250 fLastObject = nullptr;
251 fPriorEnum = nullptr;
252 fPriorObject = nullptr;
253 fPrev = '\0';
254 fInChar = false;
255 fInCharCommentString = false;
256 fInComment = false;
257 fInDefine = false;
258 fInEnum = false;
259 fInFunction = false;
260 fInString = false;
261 fFailed = false;
262 }
263
264 void setBracketShortCuts(Bracket bracket) {
265 fInComment = Bracket::kSlashSlash == bracket || Bracket::kSlashStar == bracket;
266 fInString = Bracket::kString == bracket;
267 fInChar = Bracket::kChar == bracket;
268 fInCharCommentString = fInChar || fInComment || fInString;
269 }
270
Cary Clarkfd32e722018-11-16 14:36:02 -0500271 void suggestFix(Suggest suggest, const Definition& iDef, const RootDefinition* root,
272 const Definition* bDef);
Cary Clark2da9fb82018-11-01 09:29:36 -0400273 Bracket topBracket() const;
274
275 template <typename T>
276 string uniqueName(const unordered_map<string, T>& m, string typeName) {
277 string base(typeName.size() > 0 ? typeName : "_anonymous");
278 string name(base);
279 int anonCount = 1;
280 do {
281 auto iter = m.find(name);
282 if (iter == m.end()) {
283 return name;
284 }
285 name = base + '_';
286 name += to_string(++anonCount);
287 } while (true);
288 // should never get here
289 return string();
290 }
291
292 void validate() const;
293 void writeCodeBlock();
294 string writeCodeBlock(const Definition&, MarkType );
295 string writeCodeBlock(TextParser& i, MarkType , int indent);
296
297 void writeDefinition(const Definition& def) {
298 if (def.length() > 1) {
299 this->writeBlock((int) (def.fContentEnd - def.fContentStart), def.fContentStart);
300 this->lf(1);
301 }
302 }
303
304 void writeDefinition(const Definition& def, string name, int spaces) {
305 this->writeBlock((int) (def.fContentEnd - def.fContentStart), def.fContentStart);
306 this->writeSpace(spaces);
307 this->writeString(name);
308 this->lf(1);
309 }
310
311 void writeEndTag() {
312 this->lf(1);
313 this->writeString("##");
314 this->lf(1);
315 }
316
317 void writeEndTag(const char* tagType) {
318 this->lf(1);
319 this->writeString(string("#") + tagType + " ##");
320 this->lf(1);
321 }
322
323 void writeEndTag(const char* tagType, const char* tagID, int spaces = 1) {
324 this->lf(1);
325 this->writeString(string("#") + tagType + " " + tagID);
326 this->writeSpace(spaces);
327 this->writeString("##");
328 this->lf(1);
329 }
330
331 void writeEndTag(const char* tagType, string tagID, int spaces = 1) {
332 this->writeEndTag(tagType, tagID.c_str(), spaces);
333 }
334
335 void writeIncompleteTag(const char* tagType, string tagID, int spaces = 1) {
336 this->writeString(string("#") + tagType + " " + tagID);
337 this->writeSpace(spaces);
338 this->writeString("incomplete");
339 this->writeSpace();
340 this->writeString("##");
341 this->lf(1);
342 }
343
344 void writeIncompleteTag(const char* tagType) {
345 this->writeString(string("#") + tagType + " incomplete ##");
346 this->lf(1);
347 }
348
349 void writeTableHeader(const char* col1, size_t pad, const char* col2) {
350 this->lf(1);
351 this->writeString("#Table");
352 this->lf(1);
353 this->writeString("#Legend");
354 this->lf(1);
355 string legend = "# ";
356 legend += col1;
357 if (pad > strlen(col1)) {
358 legend += string(pad - strlen(col1), ' ');
359 }
360 legend += " # ";
361 legend += col2;
362 legend += " ##";
363 this->writeString(legend);
364 this->lf(1);
365 this->writeString("#Legend ##");
366 this->lf(1);
367 }
368
369 void writeTableRow(size_t pad, string col1) {
370 this->lf(1);
371 string row = "# " + col1 + string(pad - col1.length(), ' ') + " # ##";
372 this->writeString(row);
373 this->lf(1);
374 }
375
376 void writeTableRow(size_t pad1, string col1, size_t pad2, string col2) {
377 this->lf(1);
378 string row = "# " + col1 + string(pad1 - col1.length(), ' ') + " # " +
379 col2 + string(pad2 - col2.length(), ' ') + " ##";
380 this->writeString(row);
381 this->lf(1);
382 }
383
384 void writeTableTrailer() {
385 this->lf(1);
386 this->writeString("#Table ##");
387 this->lf(1);
388 }
389
390 void writeTag(const char* tagType) {
391 this->lf(1);
392 this->writeString("#");
393 this->writeString(tagType);
394 }
395
396 void writeTagNoLF(const char* tagType, const char* tagID) {
397 this->writeString("#");
398 this->writeString(tagType);
399 this->writeSpace();
400 this->writeString(tagID);
401 }
402
403 void writeTagNoLF(const char* tagType, string tagID) {
404 this->writeTagNoLF(tagType, tagID.c_str());
405 }
406
407 void writeTag(const char* tagType, const char* tagID) {
408 this->lf(1);
409 this->writeTagNoLF(tagType, tagID);
410 }
411
412 void writeTag(const char* tagType, string tagID) {
413 this->writeTag(tagType, tagID.c_str());
414 }
415
416 void writeTagTable(string tagType, string body) {
417 this->writeTag(tagType.c_str());
418 this->writeSpace(1);
419 this->writeString("#");
420 this->writeSpace(1);
421 this->writeString(body);
422 this->writeSpace(1);
423 this->writeString("##");
424 }
425
426protected:
427 static void ValidateKeyWords();
428
429 struct DefinitionMap {
430 unordered_map<string, Definition*>* fInclude;
431 MarkType fMarkType;
432 };
433
434 vector<DefinitionMap> fMaps;
435 unordered_map<string, Definition> fIncludeMap;
436 list<Definition> fGlobals;
437 unordered_map<string, IClassDefinition> fIClassMap;
438 unordered_map<string, Definition*> fIConstMap;
439 unordered_map<string, Definition*> fIDefineMap;
440 unordered_map<string, Definition*> fIEnumMap;
441 unordered_map<string, Definition*> fIFunctionMap;
442 unordered_map<string, Definition*> fIStructMap;
443 unordered_map<string, Definition*> fITemplateMap;
444 unordered_map<string, Definition*> fITypedefMap;
445 unordered_map<string, Definition*> fIUnionMap;
446 CheckCode fCheck;
447 Definition* fRootTopic;
448 Definition* fConstExpr;
449 Definition* fInBrace;
450 Definition* fLastObject;
451 Definition* fPriorEnum;
452 Definition* fPriorObject;
453 int fPriorIndex;
454 const char* fIncludeWord;
455 Elided fElided;
456 char fPrev;
457 bool fInChar;
458 bool fInCharCommentString;
459 bool fInComment;
460 bool fInDefine;
461 bool fInEnum;
462 bool fInFunction;
463 bool fInString;
464 bool fFailed;
465
466 typedef ParserCommon INHERITED;
467};
468
469#endif