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