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