2018-11-01 13:29:36 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2018 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef includeParser_DEFINED
|
|
|
|
#define includeParser_DEFINED
|
|
|
|
|
|
|
|
#include "SkString.h"
|
|
|
|
|
|
|
|
#include "parserCommon.h"
|
|
|
|
|
|
|
|
class BmhParser;
|
|
|
|
|
|
|
|
struct IClassDefinition : public Definition {
|
|
|
|
unordered_map<string, Definition*> fConsts;
|
|
|
|
unordered_map<string, Definition*> fDefines;
|
|
|
|
unordered_map<string, Definition*> fEnums;
|
|
|
|
unordered_map<string, Definition*> fMembers;
|
|
|
|
unordered_map<string, Definition*> fMethods;
|
|
|
|
unordered_map<string, Definition*> fStructs;
|
|
|
|
unordered_map<string, Definition*> fTypedefs;
|
|
|
|
};
|
|
|
|
|
|
|
|
class IncludeParser : public ParserCommon {
|
|
|
|
public:
|
|
|
|
enum class IsStruct {
|
|
|
|
kNo,
|
|
|
|
kYes,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class Elided {
|
|
|
|
kNo,
|
|
|
|
kYes,
|
|
|
|
};
|
|
|
|
|
2018-11-16 19:36:02 +00:00
|
|
|
enum class Suggest {
|
|
|
|
kMethodMissing,
|
|
|
|
kMethodDiffers,
|
|
|
|
};
|
|
|
|
|
2018-11-01 13:29:36 +00:00
|
|
|
struct CheckCode {
|
|
|
|
enum class State {
|
|
|
|
kNone,
|
|
|
|
kClassDeclaration,
|
|
|
|
kConstructor,
|
|
|
|
kForwardDeclaration,
|
|
|
|
kMethod,
|
|
|
|
};
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
fInDebugCode = nullptr;
|
|
|
|
fPrivateBrace = 0;
|
|
|
|
fBraceCount = 0;
|
|
|
|
fIndent = 0;
|
|
|
|
fDoubleReturn = 0;
|
|
|
|
fState = State::kNone;
|
|
|
|
fPrivateProtected = false;
|
|
|
|
fTypedefReturn = false;
|
|
|
|
fSkipAPI = false;
|
|
|
|
fSkipInline = false;
|
|
|
|
fSkipWarnUnused = false;
|
|
|
|
fWriteReturn = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* fInDebugCode;
|
|
|
|
int fPrivateBrace;
|
|
|
|
int fBraceCount;
|
|
|
|
int fIndent;
|
|
|
|
int fDoubleReturn;
|
|
|
|
State fState;
|
|
|
|
bool fPrivateProtected;
|
|
|
|
bool fTypedefReturn;
|
|
|
|
bool fSkipAPI;
|
|
|
|
bool fSkipInline;
|
|
|
|
bool fSkipWarnUnused;
|
|
|
|
bool fWriteReturn;
|
|
|
|
};
|
|
|
|
|
|
|
|
IncludeParser() : ParserCommon()
|
|
|
|
, fMaps {
|
|
|
|
{ &fIConstMap, MarkType::kConst }
|
|
|
|
, { &fIDefineMap, MarkType::kDefine }
|
|
|
|
, { &fIEnumMap, MarkType::kEnum }
|
|
|
|
, { &fIEnumMap, MarkType::kEnumClass }
|
|
|
|
, { &fIStructMap, MarkType::kStruct }
|
|
|
|
, { &fITemplateMap, MarkType::kTemplate }
|
|
|
|
, { &fITypedefMap, MarkType::kTypedef }
|
|
|
|
, { &fIUnionMap, MarkType::kUnion }
|
|
|
|
}
|
|
|
|
{
|
|
|
|
this->reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
~IncludeParser() override {}
|
|
|
|
|
|
|
|
void addKeyword(KeyWord keyWord);
|
|
|
|
|
|
|
|
void addPunctuation(Punctuation punctuation) {
|
|
|
|
fParent->fTokens.emplace_back(punctuation, fChar, fLineCount, fParent, '\0');
|
|
|
|
}
|
|
|
|
|
|
|
|
void addWord() {
|
|
|
|
fParent->fTokens.emplace_back(fIncludeWord, fChar, fLineCount, fParent, '\0');
|
|
|
|
fIncludeWord = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool advanceInclude(TextParser& i);
|
|
|
|
bool inAlignAs() const;
|
|
|
|
void checkForMissingParams(const vector<string>& methodParams,
|
|
|
|
const vector<string>& foundParams);
|
|
|
|
bool checkForWord();
|
2018-11-16 19:36:02 +00:00
|
|
|
void checkTokens(list<Definition>& tokens, string key, string className,
|
|
|
|
RootDefinition* root, BmhParser& bmhParser);
|
2018-11-01 13:29:36 +00:00
|
|
|
string className() const;
|
|
|
|
|
|
|
|
string codeBlock(const Definition& def, bool inProgress) const {
|
|
|
|
return codeBlock(def.fMarkType, def.fName, inProgress);
|
|
|
|
}
|
|
|
|
|
|
|
|
string codeBlock(MarkType markType, string name, bool inProgress) const {
|
|
|
|
if (MarkType::kClass == markType || MarkType::kStruct == markType) {
|
|
|
|
auto map = fIClassMap.find(name);
|
|
|
|
SkASSERT(fIClassMap.end() != map || inProgress);
|
|
|
|
return fIClassMap.end() != map ? map->second.fCode : "";
|
|
|
|
}
|
|
|
|
if (MarkType::kConst == markType) {
|
|
|
|
auto map = fIConstMap.find(name);
|
|
|
|
SkASSERT(fIConstMap.end() != map);
|
|
|
|
return map->second->fCode;
|
|
|
|
}
|
|
|
|
if (MarkType::kDefine == markType) {
|
|
|
|
auto map = fIDefineMap.find(name);
|
|
|
|
SkASSERT(fIDefineMap.end() != map);
|
|
|
|
return map->second->fCode;
|
|
|
|
}
|
|
|
|
if (MarkType::kEnum == markType || MarkType::kEnumClass == markType) {
|
|
|
|
auto map = fIEnumMap.find(name);
|
|
|
|
SkASSERT(fIEnumMap.end() != map);
|
|
|
|
return map->second->fCode;
|
|
|
|
}
|
|
|
|
if (MarkType::kTypedef == markType) {
|
|
|
|
auto map = fITypedefMap.find(name);
|
|
|
|
SkASSERT(fITypedefMap.end() != map);
|
|
|
|
return map->second->fCode;
|
|
|
|
}
|
|
|
|
SkASSERT(0);
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void codeBlockAppend(string& result, char ch) const;
|
|
|
|
void codeBlockSpaces(string& result, int indent) const;
|
|
|
|
|
|
|
|
bool crossCheck(BmhParser& );
|
|
|
|
IClassDefinition* defineClass(const Definition& includeDef, string className);
|
|
|
|
void dumpClassTokens(IClassDefinition& classDef);
|
|
|
|
void dumpComment(const Definition& );
|
|
|
|
void dumpCommonTail(const Definition& );
|
|
|
|
void dumpConst(const Definition& , string className);
|
|
|
|
void dumpDefine(const Definition& );
|
|
|
|
void dumpEnum(const Definition& , string name);
|
|
|
|
bool dumpGlobals(string* globalFileName, long int* globalTell);
|
|
|
|
void dumpMethod(const Definition& , string className);
|
|
|
|
void dumpMember(const Definition& );
|
|
|
|
bool dumpTokens();
|
|
|
|
bool dumpTokens(string skClassName, string globalFileName, long int* globalTell);
|
|
|
|
void dumpTypedef(const Definition& , string className);
|
|
|
|
|
|
|
|
string elidedCodeBlock(const Definition& );
|
|
|
|
string filteredBlock(string inContents, string filterContents);
|
2018-11-15 13:25:12 +00:00
|
|
|
bool findCommentAfter(const Definition& includeDef, Definition* markupDef);
|
2018-11-01 13:29:36 +00:00
|
|
|
bool findComments(const Definition& includeDef, Definition* markupDef);
|
|
|
|
Definition* findIncludeObject(const Definition& includeDef, MarkType markType,
|
|
|
|
string typeName);
|
|
|
|
static KeyWord FindKey(const char* start, const char* end);
|
|
|
|
Definition* findMethod(const Definition& bmhDef);
|
|
|
|
Bracket grandParentBracket() const;
|
|
|
|
const Definition* include(string ) const;
|
|
|
|
bool isClone(const Definition& token);
|
|
|
|
bool isConstructor(const Definition& token, string className);
|
|
|
|
bool isInternalName(const Definition& token);
|
|
|
|
bool isMember(const Definition& token) const;
|
|
|
|
bool isOperator(const Definition& token);
|
2018-11-15 13:25:12 +00:00
|
|
|
bool isUndocumentable(string filename, const char* start, const char* end, int lineCount);
|
2018-11-01 13:29:36 +00:00
|
|
|
Definition* parentBracket(Definition* parent) const;
|
|
|
|
bool parseChar();
|
|
|
|
bool parseComment(string filename, const char* start, const char* end, int lineCount,
|
2018-11-15 13:25:12 +00:00
|
|
|
Definition* markupDef, bool* undocumentedPtr);
|
2018-11-01 13:29:36 +00:00
|
|
|
bool parseClass(Definition* def, IsStruct);
|
|
|
|
bool parseConst(Definition* child, Definition* markupDef);
|
|
|
|
bool parseDefine(Definition* child, Definition* markupDef);
|
|
|
|
bool parseEnum(Definition* child, Definition* markupDef);
|
2018-11-15 13:25:12 +00:00
|
|
|
bool parseEnumConst(list<Definition>::iterator& tokenIter,
|
|
|
|
const list<Definition>::iterator& tokenEnd, Definition* markupChild);
|
2018-11-01 13:29:36 +00:00
|
|
|
|
|
|
|
bool parseFromFile(const char* path) override {
|
|
|
|
this->reset();
|
|
|
|
if (!INHERITED::parseSetup(path)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
string name(path);
|
|
|
|
return this->parseInclude(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parseInclude(string name);
|
|
|
|
bool parseMember(Definition* child, Definition* markupDef);
|
|
|
|
bool parseMethod(Definition* child, Definition* markupDef);
|
|
|
|
bool parseObject(Definition* child, Definition* markupDef);
|
|
|
|
bool parseObjects(Definition* parent, Definition* markupDef);
|
2018-11-15 13:25:12 +00:00
|
|
|
bool parseOneEnumConst(list<Definition>& constList, Definition* markupChild, bool skipWord);
|
2018-11-01 13:29:36 +00:00
|
|
|
bool parseTemplate(Definition* child, Definition* markupDef);
|
|
|
|
bool parseTypedef(Definition* child, Definition* markupDef);
|
|
|
|
bool parseUsing();
|
|
|
|
bool parseUnion();
|
|
|
|
|
|
|
|
void popBracket() {
|
|
|
|
if (Definition::Type::kKeyWord == fParent->fType
|
|
|
|
&& KeyWord::kTypename == fParent->fKeyWord) {
|
|
|
|
this->popObject();
|
|
|
|
}
|
|
|
|
SkASSERT(Definition::Type::kBracket == fParent->fType);
|
|
|
|
this->popObject();
|
|
|
|
Bracket bracket = this->topBracket();
|
|
|
|
this->setBracketShortCuts(bracket);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushBracket(Bracket bracket) {
|
2018-11-15 13:25:12 +00:00
|
|
|
if ("#else" == string(fChar, 5)) {
|
|
|
|
SkDebugf("");
|
|
|
|
}
|
2018-11-01 13:29:36 +00:00
|
|
|
this->setBracketShortCuts(bracket);
|
|
|
|
fParent->fTokens.emplace_back(bracket, fChar, fLineCount, fParent, '\0');
|
|
|
|
Definition* container = &fParent->fTokens.back();
|
|
|
|
this->addDefinition(container);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool references(const SkString& file) const;
|
|
|
|
|
|
|
|
static void RemoveFile(const char* docs, const char* includes);
|
|
|
|
static void RemoveOneFile(const char* docs, const char* includesFileOrPath);
|
|
|
|
|
|
|
|
void reset() override {
|
|
|
|
INHERITED::resetCommon();
|
|
|
|
fRootTopic = nullptr;
|
|
|
|
fConstExpr = nullptr;
|
|
|
|
fInBrace = nullptr;
|
|
|
|
fIncludeWord = nullptr;
|
|
|
|
fLastObject = nullptr;
|
|
|
|
fPriorEnum = nullptr;
|
|
|
|
fPriorObject = nullptr;
|
|
|
|
fPrev = '\0';
|
|
|
|
fInChar = false;
|
|
|
|
fInCharCommentString = false;
|
|
|
|
fInComment = false;
|
|
|
|
fInDefine = false;
|
|
|
|
fInEnum = false;
|
|
|
|
fInFunction = false;
|
|
|
|
fInString = false;
|
|
|
|
fFailed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setBracketShortCuts(Bracket bracket) {
|
|
|
|
fInComment = Bracket::kSlashSlash == bracket || Bracket::kSlashStar == bracket;
|
|
|
|
fInString = Bracket::kString == bracket;
|
|
|
|
fInChar = Bracket::kChar == bracket;
|
|
|
|
fInCharCommentString = fInChar || fInComment || fInString;
|
|
|
|
}
|
|
|
|
|
2018-11-16 19:36:02 +00:00
|
|
|
void suggestFix(Suggest suggest, const Definition& iDef, const RootDefinition* root,
|
|
|
|
const Definition* bDef);
|
2018-11-01 13:29:36 +00:00
|
|
|
Bracket topBracket() const;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
string uniqueName(const unordered_map<string, T>& m, string typeName) {
|
|
|
|
string base(typeName.size() > 0 ? typeName : "_anonymous");
|
|
|
|
string name(base);
|
|
|
|
int anonCount = 1;
|
|
|
|
do {
|
|
|
|
auto iter = m.find(name);
|
|
|
|
if (iter == m.end()) {
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
name = base + '_';
|
|
|
|
name += to_string(++anonCount);
|
|
|
|
} while (true);
|
|
|
|
// should never get here
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
|
|
|
void validate() const;
|
|
|
|
void writeCodeBlock();
|
|
|
|
string writeCodeBlock(const Definition&, MarkType );
|
|
|
|
string writeCodeBlock(TextParser& i, MarkType , int indent);
|
|
|
|
|
|
|
|
void writeDefinition(const Definition& def) {
|
|
|
|
if (def.length() > 1) {
|
|
|
|
this->writeBlock((int) (def.fContentEnd - def.fContentStart), def.fContentStart);
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeDefinition(const Definition& def, string name, int spaces) {
|
|
|
|
this->writeBlock((int) (def.fContentEnd - def.fContentStart), def.fContentStart);
|
|
|
|
this->writeSpace(spaces);
|
|
|
|
this->writeString(name);
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeEndTag() {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeEndTag(const char* tagType) {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString(string("#") + tagType + " ##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeEndTag(const char* tagType, const char* tagID, int spaces = 1) {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString(string("#") + tagType + " " + tagID);
|
|
|
|
this->writeSpace(spaces);
|
|
|
|
this->writeString("##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeEndTag(const char* tagType, string tagID, int spaces = 1) {
|
|
|
|
this->writeEndTag(tagType, tagID.c_str(), spaces);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeIncompleteTag(const char* tagType, string tagID, int spaces = 1) {
|
|
|
|
this->writeString(string("#") + tagType + " " + tagID);
|
|
|
|
this->writeSpace(spaces);
|
|
|
|
this->writeString("incomplete");
|
|
|
|
this->writeSpace();
|
|
|
|
this->writeString("##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeIncompleteTag(const char* tagType) {
|
|
|
|
this->writeString(string("#") + tagType + " incomplete ##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTableHeader(const char* col1, size_t pad, const char* col2) {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("#Table");
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("#Legend");
|
|
|
|
this->lf(1);
|
|
|
|
string legend = "# ";
|
|
|
|
legend += col1;
|
|
|
|
if (pad > strlen(col1)) {
|
|
|
|
legend += string(pad - strlen(col1), ' ');
|
|
|
|
}
|
|
|
|
legend += " # ";
|
|
|
|
legend += col2;
|
|
|
|
legend += " ##";
|
|
|
|
this->writeString(legend);
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("#Legend ##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTableRow(size_t pad, string col1) {
|
|
|
|
this->lf(1);
|
|
|
|
string row = "# " + col1 + string(pad - col1.length(), ' ') + " # ##";
|
|
|
|
this->writeString(row);
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTableRow(size_t pad1, string col1, size_t pad2, string col2) {
|
|
|
|
this->lf(1);
|
|
|
|
string row = "# " + col1 + string(pad1 - col1.length(), ' ') + " # " +
|
|
|
|
col2 + string(pad2 - col2.length(), ' ') + " ##";
|
|
|
|
this->writeString(row);
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTableTrailer() {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("#Table ##");
|
|
|
|
this->lf(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTag(const char* tagType) {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeString("#");
|
|
|
|
this->writeString(tagType);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTagNoLF(const char* tagType, const char* tagID) {
|
|
|
|
this->writeString("#");
|
|
|
|
this->writeString(tagType);
|
|
|
|
this->writeSpace();
|
|
|
|
this->writeString(tagID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTagNoLF(const char* tagType, string tagID) {
|
|
|
|
this->writeTagNoLF(tagType, tagID.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTag(const char* tagType, const char* tagID) {
|
|
|
|
this->lf(1);
|
|
|
|
this->writeTagNoLF(tagType, tagID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTag(const char* tagType, string tagID) {
|
|
|
|
this->writeTag(tagType, tagID.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTagTable(string tagType, string body) {
|
|
|
|
this->writeTag(tagType.c_str());
|
|
|
|
this->writeSpace(1);
|
|
|
|
this->writeString("#");
|
|
|
|
this->writeSpace(1);
|
|
|
|
this->writeString(body);
|
|
|
|
this->writeSpace(1);
|
|
|
|
this->writeString("##");
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
static void ValidateKeyWords();
|
|
|
|
|
|
|
|
struct DefinitionMap {
|
|
|
|
unordered_map<string, Definition*>* fInclude;
|
|
|
|
MarkType fMarkType;
|
|
|
|
};
|
|
|
|
|
|
|
|
vector<DefinitionMap> fMaps;
|
|
|
|
unordered_map<string, Definition> fIncludeMap;
|
|
|
|
list<Definition> fGlobals;
|
|
|
|
unordered_map<string, IClassDefinition> fIClassMap;
|
|
|
|
unordered_map<string, Definition*> fIConstMap;
|
|
|
|
unordered_map<string, Definition*> fIDefineMap;
|
|
|
|
unordered_map<string, Definition*> fIEnumMap;
|
|
|
|
unordered_map<string, Definition*> fIFunctionMap;
|
|
|
|
unordered_map<string, Definition*> fIStructMap;
|
|
|
|
unordered_map<string, Definition*> fITemplateMap;
|
|
|
|
unordered_map<string, Definition*> fITypedefMap;
|
|
|
|
unordered_map<string, Definition*> fIUnionMap;
|
|
|
|
CheckCode fCheck;
|
|
|
|
Definition* fRootTopic;
|
|
|
|
Definition* fConstExpr;
|
|
|
|
Definition* fInBrace;
|
|
|
|
Definition* fLastObject;
|
|
|
|
Definition* fPriorEnum;
|
|
|
|
Definition* fPriorObject;
|
|
|
|
int fPriorIndex;
|
|
|
|
const char* fIncludeWord;
|
|
|
|
Elided fElided;
|
|
|
|
char fPrev;
|
|
|
|
bool fInChar;
|
|
|
|
bool fInCharCommentString;
|
|
|
|
bool fInComment;
|
|
|
|
bool fInDefine;
|
|
|
|
bool fInEnum;
|
|
|
|
bool fInFunction;
|
|
|
|
bool fInString;
|
|
|
|
bool fFailed;
|
|
|
|
|
|
|
|
typedef ParserCommon INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|