From 186d08f621efcaf9960ffe4a1dd9e6703de8a698 Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Tue, 3 Apr 2018 08:43:27 -0400 Subject: fix bugs exposed by documenting SkImageInfo - More rigorous symbol identification creates additional links, and finds spurious errors like unnecessary parentheses. - Fixed code to allow preprocessor directives in #Code blocks (still more to do). - Fixed examples waiting on fiddle updates. - Make SkImageInfo officially documented (update in status.json). - Fixed enum indentation. Docs-Preview: https://skia.org/?cl=115656 Bug: skia:6898 Change-Id: Ifcf5cfd3f6c03b3b83155c898b2b035a2f3d443c Reviewed-on: https://skia-review.googlesource.com/115656 Commit-Queue: Cary Clark Reviewed-by: Cary Clark --- tools/bookmaker/bookmaker.cpp | 51 +++++++++---- tools/bookmaker/bookmaker.h | 106 +++++++++++++++++++-------- tools/bookmaker/cataloger.cpp | 2 +- tools/bookmaker/definition.cpp | 6 +- tools/bookmaker/includeParser.cpp | 28 +++++-- tools/bookmaker/includeWriter.cpp | 150 ++++++++++++++++++++------------------ tools/bookmaker/mdOut.cpp | 135 +++++++++++++++++++--------------- tools/bookmaker/parserCommon.cpp | 4 +- 8 files changed, 294 insertions(+), 188 deletions(-) (limited to 'tools/bookmaker') diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index 4016a19439..223c5b521a 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -50,6 +50,9 @@ trouble with aliases, plurals need to keep first letter of includeWriter @param / @return lowercase Quad -> quad, Quads -> quads deprecated methods should be sorted down in md out, and show include "Deprecated." text body. +rewrap text to fit in some number of columns +#Literal is inflexible, making the entire #Code block link-less (see $Literal in SkImageInfo) + would rather keep links for boby above #Literal, and/or make it a block and not a one-liner see head of selfCheck.cpp for additional todos */ @@ -639,7 +642,7 @@ string BmhParser::className(MarkType markType) { const char* end = this->lineEnd(); const char* mc = this->strnchr(fMC, end); string classID; - TextParser::Save savePlace(this); + TextParserSave savePlace(this); this->skipSpace(); const char* wordStart = fChar; this->skipToNonAlphaNum(); @@ -1054,9 +1057,6 @@ bool BmhParser::findDefinitions() { const char* lastMC = nullptr; fParent = nullptr; while (!this->eof()) { - if (195 == fLineCount && "docs\\SkImageInfo_Reference.bmh" == fFileName) { - SkDebugf(""); - } if (this->peek() == fMC) { lastMC = fChar; this->next(); @@ -1570,7 +1570,7 @@ string BmhParser::methodName() { bool addConst = false; if (isConstructor || expectOperator) { paren = this->strnchr(')', end) + 1; - TextParser::Save saveState(this); + TextParserSave saveState(this); this->skipTo(paren); if (this->skipExact("_const")) { addConst = true; @@ -1593,7 +1593,7 @@ string BmhParser::methodName() { } this->next(); } - TextParser::Save saveState(this); + TextParserSave saveState(this); this->skipWhiteSpace(); if (this->startsWith("const")) { this->skipName("const"); @@ -1739,6 +1739,22 @@ void TextParser::reportWarning(const char* errorStr) const { } } +void TextParser::setForErrorReporting(const Definition* definition, const char* str) { + fFileName = definition->fFileName; + fStart = definition->fContentStart; + fLine = str; + while (fLine > fStart && fLine[-1] != '\n') { + --fLine; + } + fChar = str; + fEnd = definition->fContentEnd; + fLineCount = definition->fLineCount; + const char* lineInc = fStart; + while (lineInc < str) { + fLineCount += '\n' == *lineInc++; + } +} + string TextParser::typedefName() { // look for typedef as one of three forms: // typedef return-type (*NAME)(params); @@ -2289,7 +2305,7 @@ int main(int argc, char** const argv) { if (FLAGS_tokens) { IncludeParser::RemoveFile(FLAGS_bmh[0], FLAGS_include[0]); } - if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh")) { + if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh", ParserCommon::OneFile::kNo)) { return -1; } } else if (!FLAGS_status.isEmpty()) { @@ -2304,7 +2320,7 @@ int main(int argc, char** const argv) { return 1; } HackParser hacker(bmhParser); - if (!hacker.parseFile(FLAGS_bmh[0], ".bmh")) { + if (!hacker.parseFile(FLAGS_bmh[0], ".bmh", ParserCommon::OneFile::kNo)) { SkDebugf("hack failed\n"); return -1; } @@ -2317,7 +2333,7 @@ int main(int argc, char** const argv) { if (!FLAGS_include.isEmpty() && FLAGS_tokens) { IncludeParser includeParser; includeParser.validate(); - if (!includeParser.parseFile(FLAGS_include[0], ".h")) { + if (!includeParser.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) { return -1; } if (FLAGS_tokens) { @@ -2332,7 +2348,7 @@ int main(int argc, char** const argv) { IncludeParser includeParser; includeParser.validate(); if (!FLAGS_include.isEmpty() && - !includeParser.parseFile(FLAGS_include[0], ".h")) { + !includeParser.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) { return -1; } if (!FLAGS_status.isEmpty() && !includeParser.parseStatus(FLAGS_status[0], ".h", @@ -2347,7 +2363,7 @@ int main(int argc, char** const argv) { IncludeWriter includeWriter; includeWriter.validate(); if (!FLAGS_include.isEmpty() && - !includeWriter.parseFile(FLAGS_include[0], ".h")) { + !includeWriter.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) { return -1; } if (!FLAGS_status.isEmpty() && !includeWriter.parseStatus(FLAGS_status[0], ".h", @@ -2364,7 +2380,7 @@ int main(int argc, char** const argv) { } if (!done && !FLAGS_fiddle.isEmpty() && FLAGS_examples.isEmpty()) { FiddleParser fparser(&bmhParser); - if (!fparser.parseFile(FLAGS_fiddle[0], ".txt")) { + if (!fparser.parseFile(FLAGS_fiddle[0], ".txt", ParserCommon::OneFile::kNo)) { return -1; } } @@ -2377,7 +2393,7 @@ int main(int argc, char** const argv) { if (!FLAGS_status.isEmpty() && !cparser.openStatus(FLAGS_status[0], FLAGS_ref[0])) { return -1; } - if (!cparser.parseFile(FLAGS_fiddle[0], ".txt")) { + if (!cparser.parseFile(FLAGS_fiddle[0], ".txt", ParserCommon::OneFile::kNo)) { return -1; } if (!cparser.closeCatalog()) { @@ -2387,9 +2403,16 @@ int main(int argc, char** const argv) { done = true; } if (!done && !FLAGS_ref.isEmpty() && FLAGS_examples.isEmpty()) { + IncludeParser includeParser; + includeParser.validate(); + if (!FLAGS_include.isEmpty() && !includeParser.parseFile(FLAGS_include[0], ".h", + ParserCommon::OneFile::kYes)) { + return -1; + } MdOut mdOut(bmhParser); mdOut.fDebugOut = FLAGS_stdout; - if (!FLAGS_bmh.isEmpty() && mdOut.buildReferences(FLAGS_bmh[0], FLAGS_ref[0])) { + if (!FLAGS_bmh.isEmpty() && mdOut.buildReferences(includeParser, + FLAGS_bmh[0], FLAGS_ref[0])) { bmhParser.fWroteOut = true; } if (!FLAGS_status.isEmpty() && mdOut.buildStatus(FLAGS_status[0], FLAGS_ref[0])) { diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index 968644f8b1..a0f6bca6a7 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -240,31 +240,11 @@ public: class Definition; class TextParser : public NonAssignable { - TextParser() {} // only for ParserCommon to call + TextParser() {} // only for ParserCommon, TextParserSave friend class ParserCommon; + friend class TextParserSave; public: virtual ~TextParser() {} - class Save { - public: - Save(TextParser* parser) { - fParser = parser; - fLine = parser->fLine; - fChar = parser->fChar; - fLineCount = parser->fLineCount; - } - - void restore() const { - fParser->fLine = fLine; - fParser->fChar = fChar; - fParser->fLineCount = fLineCount; - } - - private: - TextParser* fParser; - const char* fLine; - const char* fChar; - int fLineCount; - }; TextParser(const string& fileName, const char* start, const char* end, int lineCount) : fFileName(fileName) @@ -417,6 +397,8 @@ public: return true; } + void setForErrorReporting(const Definition* , const char* ); + bool skipToEndBracket(char endBracket, const char* end = nullptr) { if (nullptr == end) { end = fEnd; @@ -690,6 +672,33 @@ public: size_t fLineCount; }; +class TextParserSave { +public: + TextParserSave(TextParser* parser) { + fParser = parser; + fSave.fFileName = parser->fFileName; + fSave.fStart = parser->fStart; + fSave.fLine = parser->fLine; + fSave.fChar = parser->fChar; + fSave.fEnd = parser->fEnd; + fSave.fLineCount = parser->fLineCount; + } + + void restore() const { + fParser->fFileName = fSave.fFileName; + fParser->fStart = fSave.fStart; + fParser->fLine = fSave.fLine; + fParser->fChar = fSave.fChar; + fParser->fEnd = fSave.fEnd; + fParser->fLineCount = fSave.fLineCount; + } + +private: + TextParser* fParser; + TextParser fSave; +}; + + class EscapeParser : public TextParser { public: EscapeParser(const char* start, const char* end) : @@ -1019,6 +1028,10 @@ struct TypeNames { class ParserCommon : public TextParser { public: + enum class OneFile { + kNo, + kYes, + }; ParserCommon() : TextParser() , fParent(nullptr) @@ -1078,7 +1091,7 @@ public: fPendingSpace = 0; } - bool parseFile(const char* file, const char* suffix); + bool parseFile(const char* file, const char* suffix, OneFile ); bool parseStatus(const char* file, const char* suffix, StatusFilter filter); virtual bool parseFromFile(const char* path) = 0; bool parseSetup(const char* path); @@ -1206,8 +1219,9 @@ public: enum class Resolvable { kNo, // neither resolved nor output kYes, // resolved, output - kOut, // not resolved, but output - kLiteral, // output untouched (FIXME: is this really different from kOut?) + kOut, // mostly resolved, output (FIXME: is this really different from kYes?) + kFormula, // resolve methods as they are used, not as they are prototyped + kLiteral, // output untouched kClone, // resolved, output, with references to clones as well }; @@ -1252,6 +1266,7 @@ public: #define R_Y Resolvable::kYes #define R_N Resolvable::kNo #define R_O Resolvable::kOut +#define R_F Resolvable::kFormula #define R_C Resolvable::kClone #define E_Y Exemplary::kYes @@ -1284,7 +1299,7 @@ public: , { "Experimental", nullptr, MarkType::kExperimental, R_Y, E_N, 0 } , { "External", nullptr, MarkType::kExternal, R_Y, E_N, M(Root) } , { "File", nullptr, MarkType::kFile, R_N, E_N, M(Track) } -, { "Formula", nullptr, MarkType::kFormula, R_O, E_N, +, { "Formula", nullptr, MarkType::kFormula, R_F, E_N, M(Column) | M_E | M_ST | M(Member) | M(Method) | M_D } , { "Function", nullptr, MarkType::kFunction, R_O, E_N, M(Example) | M(NoExample) } , { "Height", nullptr, MarkType::kHeight, R_N, E_N, M(Example) | M(NoExample) } @@ -1301,7 +1316,7 @@ public: , { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 } , { "Member", nullptr, MarkType::kMember, R_Y, E_N, M_CSST } , { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST } -, { "NoExample", nullptr, MarkType::kNoExample, R_O, E_N, M_CSST | M_E | M(Method) } +, { "NoExample", nullptr, MarkType::kNoExample, R_N, E_N, M_CSST | M_E | M(Method) } , { "Outdent", nullptr, MarkType::kOutdent, R_N, E_N, M(Code) } , { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) } , { "PhraseDef", nullptr, MarkType::kPhraseDef, R_Y, E_N, M(Subtopic) } @@ -1338,6 +1353,8 @@ public: #undef R_O #undef R_N #undef R_Y +#undef R_F +#undef R_C #undef M_E #undef M_CSST @@ -1346,6 +1363,10 @@ public: #undef M_D #undef M +#undef E_Y +#undef E_N +#undef E_O + ~BmhParser() override {} bool addDefinition(const char* defStart, bool hasEnd, MarkType markType, @@ -1634,6 +1655,8 @@ public: 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); @@ -1888,6 +1911,11 @@ public: kChars, }; + enum class MemberPass { + kCount, + kOut, + }; + struct IterState { IterState (list::iterator tIter, list::iterator tIterEnd) : fDefIter(tIter) @@ -1902,6 +1930,17 @@ public: const ParentPair* fPrev; }; + struct Preprocessor { + Preprocessor() + : fStart(nullptr) + , fEnd(nullptr) + , fWord(false) { + } + const char* fStart; + const char* fEnd; + bool fWord; + }; + IncludeWriter() : IncludeParser() { this->reset(); } @@ -1924,7 +1963,10 @@ public: void descriptionOut(const Definition* def, SkipFirstLine , Phrase ); void enumHeaderOut(const RootDefinition* root, const Definition& child); void enumMembersOut(const RootDefinition* root, Definition& child); + bool enumPreprocessor(Definition* token, MemberPass pass, + vector& iterStack, IterState** iterState, Preprocessor* ); void enumSizeItems(const Definition& child); + bool findEnumSubtopic(string undername, const Definition** ) const; Definition* findMemberCommentBlock(const vector& bmhChildren, const string& name) const; int lookupMethod(const PunctuationState punctuation, const Word word, const int start, const int run, int lastWrite, @@ -2101,7 +2143,7 @@ public: this->reset(); } - bool buildReferences(const char* docDir, const char* mdOutDirOrFile); + bool buildReferences(const IncludeParser& , const char* docDir, const char* mdOutDirOrFile); bool buildStatus(const char* docDir, const char* mdOutDir); static constexpr const char* kClassesAndStructs = "Class_or_Struct"; @@ -2137,7 +2179,7 @@ private: void childrenOut(const Definition* def, const char* contentStart); const Definition* csParent() const; const Definition* findParamType(); - const Definition* isDefined(const TextParser& parser, const string& ref, bool report); + const Definition* isDefined(const TextParser& , const string& ref, BmhParser::Resolvable ); string linkName(const Definition* ) const; string linkRef(const string& leadingSpaces, const Definition*, const string& ref, BmhParser::Resolvable ) const; @@ -2166,7 +2208,8 @@ private: fHasFiddle = false; fInDescription = false; fInList = false; - fRespectLeadingSpace = false; + fResolveAndIndent = false; + fLiteralAndIndent = false; } BmhParser::Resolvable resolvable(const Definition* definition) const { @@ -2204,7 +2247,8 @@ private: bool fInDescription; // FIXME: for now, ignore unfound camelCase in description since it may // be defined in example which at present cannot be linked to bool fInList; - bool fRespectLeadingSpace; + bool fLiteralAndIndent; + bool fResolveAndIndent; typedef ParserCommon INHERITED; }; diff --git a/tools/bookmaker/cataloger.cpp b/tools/bookmaker/cataloger.cpp index a564d3ee98..de46ecd1a7 100644 --- a/tools/bookmaker/cataloger.cpp +++ b/tools/bookmaker/cataloger.cpp @@ -86,7 +86,7 @@ bool Catalog::parseFromFile(const char* path) { this->writeString("var text = {"); this->lf(1); fTextOut = true; - TextParser::Save save(this); + TextParserSave save(this); if (!parseFiddles()) { return false; } diff --git a/tools/bookmaker/definition.cpp b/tools/bookmaker/definition.cpp index 14f6daab81..e3a5aa3bd5 100644 --- a/tools/bookmaker/definition.cpp +++ b/tools/bookmaker/definition.cpp @@ -200,7 +200,7 @@ bool Definition::parseOperator(size_t doubleColons, string& result) { SkAssertResult(iParser.skipExact("operator")); iParser.skipWhiteSpace(); fMethodType = Definition::MethodType::kOperator; - TextParser::Save save(&iParser); + TextParserSave save(&iParser); for (auto parser : opData) { save.restore(); if (!iParser.skipExact(parser.fSymbol)) { @@ -670,7 +670,7 @@ string Definition::formatFunction(Format format) const { indent = (size_t) (lastEnd - lastStart); } // trim indent so longest line doesn't exceed box width - TextParser::Save savePlace(&methodParser); + TextParserSave savePlace(&methodParser); const char* saveStart = lastStart; ptrdiff_t maxLine = 0; do { @@ -889,7 +889,7 @@ string Definition::methodName() const { bool Definition::nextMethodParam(TextParser* methodParser, const char** nextEndPtr, string* paramName) const { int parenCount = 0; - TextParser::Save saveState(methodParser); + TextParserSave saveState(methodParser); while (true) { if (methodParser->eof()) { return methodParser->reportError("#Method function missing close paren"); diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp index 8365a82d1c..4040fb6d15 100644 --- a/tools/bookmaker/includeParser.cpp +++ b/tools/bookmaker/includeParser.cpp @@ -1363,9 +1363,6 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { markupChild->fName = markupDef->fName + "::" + string(nameStart, (size_t) (enumName.fChar - nameStart)); } - if (string::npos != markupChild->fName.find("SkColorType")) { - SkDebugf(""); - } if (!this->findComments(*child, markupChild)) { return false; } @@ -1433,7 +1430,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { if ('/' == parser.next()) { char slashStar = parser.next(); if ('/' == slashStar || '*' == slashStar) { - TextParser::Save save(&parser); + TextParserSave save(&parser); char doxCheck = parser.next(); if ((slashStar != doxCheck && '!' != doxCheck) || '<' != parser.next()) { save.restore(); @@ -1954,7 +1951,7 @@ bool IncludeParser::parseChar() { return reportError("malformed closing comment"); } if (Bracket::kSlashStar == this->topBracket()) { - TextParser::Save save(this); + TextParserSave save(this); this->next(); // include close in bracket this->popBracket(); save.restore(); // put things back so nothing is skipped @@ -2316,6 +2313,27 @@ void IncludeParser::validate() const { IncludeParser::ValidateKeyWords(); } +bool IncludeParser::references(const SkString& file) const { + // if includes weren't passed one at a time, assume all references are valid + if (fIncludeMap.empty()) { + return true; + } + SkASSERT(file.endsWith(".bmh") ); + string root(file.c_str(), file.size() - 4); + string kReference("_Reference"); + if (string::npos != root.find(kReference)) { + root = root.substr(0, root.length() - kReference.length()); + } + if (fIClassMap.end() != fIClassMap.find(root)) { + return true; + } + if (fIStructMap.end() != fIStructMap.find(root)) { + return true; + } + // TODO incomplete: probably need to look in other places for class-less includes like SkColor.h + return false; +} + void IncludeParser::RemoveFile(const char* docs, const char* includes) { if (!sk_isdir(includes)) { IncludeParser::RemoveOneFile(docs, includes); diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index 067c014070..5b2f8076bc 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -375,43 +375,11 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child vector iterStack; iterStack.emplace_back(child.fTokens.begin(), child.fTokens.end()); IterState* iterState = &iterStack[0]; - bool preprocessorWord = false; - const char* preprocessStart = nullptr; - const char* preprocessEnd = nullptr; + Preprocessor preprocessor; for (int onePast = 0; onePast < 2; onePast += iterState->fDefIter == iterState->fDefEnd) { Definition* token = onePast ? nullptr : &*iterState->fDefIter++; - if (token && Definition::Type::kBracket == token->fType) { - if (Bracket::kSlashSlash == token->fBracket) { - fStart = token->fContentEnd; - continue; // ignore old inline comments - } - if (Bracket::kSlashStar == token->fBracket) { - fStart = token->fContentEnd + 1; - continue; // ignore old inline comments - } - if (Bracket::kPound == token->fBracket) { // preprocessor wraps member - preprocessStart = token->fContentStart; - if (KeyWord::kIf == token->fKeyWord || KeyWord::kIfdef == token->fKeyWord) { - iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end()); - iterState = &iterStack.back(); - preprocessorWord = true; - } else if (KeyWord::kEndif == token->fKeyWord) { - iterStack.pop_back(); - iterState = &iterStack.back(); - preprocessEnd = token->fContentEnd; - } else { - SkASSERT(0); // incomplete - } - continue; - } - SkASSERT(0); // incomplete - } - if (token && Definition::Type::kWord != token->fType) { - SkASSERT(0); // incomplete - } - if (preprocessorWord) { - preprocessorWord = false; - preprocessEnd = token->fContentEnd; + if (this->enumPreprocessor(token, MemberPass::kOut, iterStack, &iterState, + &preprocessor)) { continue; } if (token && State::kItemName == state) { @@ -462,16 +430,17 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child fIndent -= 4; } this->lfcr(); - if (preprocessStart) { - SkASSERT(preprocessEnd); + if (preprocessor.fStart) { + SkASSERT(preprocessor.fEnd); int saveIndent = fIndent; fIndent = SkTMax(0, fIndent - 8); this->lf(2); - this->writeBlock((int) (preprocessEnd - preprocessStart), preprocessStart); + this->writeBlock( + (int) (preprocessor.fEnd - preprocessor.fStart), preprocessor.fStart); this->lfcr(); fIndent = saveIndent; - preprocessStart = nullptr; - preprocessEnd = nullptr; + preprocessor.fStart = nullptr; + preprocessor.fEnd = nullptr; } if (token && State::kItemValue == state) { fStart = token->fContentStart; @@ -538,8 +507,11 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child this->writeString(currentEnumItem->fToBeDeprecated ? "To be deprecated soon." : "Deprecated."); } + TextParserSave save(this); + this->setForErrorReporting(currentEnumItem, commentStart); wroteLineFeed = Wrote::kLF == this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + save.restore(); fIndent -= 4; if (wroteLineFeed || fColumn > 100 - 3 /* space * / */ ) { this->lfcr(); @@ -559,6 +531,55 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child } } +bool IncludeWriter::enumPreprocessor(Definition* token, MemberPass pass, + vector& iterStack, IterState** iterState, Preprocessor* preprocessor) { + if (token && Definition::Type::kBracket == token->fType) { + if (Bracket::kSlashSlash == token->fBracket) { + if (MemberPass::kOut == pass) { + fStart = token->fContentEnd; + } + return true; // ignore old inline comments + } + if (Bracket::kSlashStar == token->fBracket) { + if (MemberPass::kOut == pass) { + fStart = token->fContentEnd + 1; + } + return true; // ignore old inline comments + } + if (Bracket::kPound == token->fBracket) { // preprocessor wraps member + preprocessor->fStart = token->fContentStart; + if (KeyWord::kIf == token->fKeyWord || KeyWord::kIfdef == token->fKeyWord) { + iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end()); + *iterState = &iterStack.back(); + preprocessor->fWord = true; + } else if (KeyWord::kEndif == token->fKeyWord || KeyWord::kElif == token->fKeyWord + || KeyWord::kElse == token->fKeyWord) { + iterStack.pop_back(); + *iterState = &iterStack.back(); + preprocessor->fEnd = token->fContentEnd; + if (KeyWord::kElif == token->fKeyWord) { + iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end()); + *iterState = &iterStack.back(); + preprocessor->fWord = true; + } + } else { + SkASSERT(0); // incomplete + } + return true; + } + return true; + } + if (token && Definition::Type::kWord != token->fType) { + SkASSERT(0); // incomplete + } + if (preprocessor->fWord) { + preprocessor->fWord = false; + preprocessor->fEnd = token->fContentEnd; + return true; + } + return false; +} + void IncludeWriter::enumSizeItems(const Definition& child) { enum class State { kNoItem, @@ -580,36 +601,11 @@ void IncludeWriter::enumSizeItems(const Definition& child) { vector iterStack; iterStack.emplace_back(brace->fTokens.begin(), brace->fTokens.end()); IterState* iterState = &iterStack[0]; - bool preprocessorWord = false; + Preprocessor preprocessor; while (iterState->fDefIter != iterState->fDefEnd) { auto& token = *iterState->fDefIter++; - if (Definition::Type::kBracket == token.fType) { - if (Bracket::kSlashSlash == token.fBracket) { - continue; // ignore old inline comments - } - if (Bracket::kSlashStar == token.fBracket) { - continue; // ignore old inline comments - } - if (Bracket::kPound == token.fBracket) { // preprocessor wraps member - if (KeyWord::kIf == token.fKeyWord || KeyWord::kIfdef == token.fKeyWord) { - iterStack.emplace_back(token.fTokens.begin(), token.fTokens.end()); - iterState = &iterStack.back(); - preprocessorWord = true; - } else if (KeyWord::kEndif == token.fKeyWord) { - iterStack.pop_back(); - iterState = &iterStack.back(); - } else { - SkASSERT(0); // incomplete - } - continue; - } - SkASSERT(0); // incomplete - } - if (Definition::Type::kWord != token.fType) { - SkASSERT(0); // incomplete - } - if (preprocessorWord) { - preprocessorWord = false; + if (this->enumPreprocessor(&token, MemberPass::kCount, iterStack, &iterState, + &preprocessor)) { continue; } if (State::kItemName == state) { @@ -763,6 +759,17 @@ void IncludeWriter::structOut(const Definition* root, const Definition& child, this->writeCommentTrailer(); } +bool IncludeWriter::findEnumSubtopic(string undername, const Definition** rootDefPtr) const { + const Definition* subtopic = fEnumDef->fParent; + string subcheck = subtopic->fFiddle + '_' + undername; + auto iter = fBmhParser->fTopicMap.find(subcheck); + if (iter == fBmhParser->fTopicMap.end()) { + return false; + } + *rootDefPtr = iter->second; + return true; +} + Definition* IncludeWriter::findMemberCommentBlock(const vector& bmhChildren, const string& name) const { for (auto memberDef : bmhChildren) { @@ -1038,9 +1045,6 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti const Definition* requireDense = nullptr; const Definition* startDef = nullptr; for (auto& child : def->fTokens) { - if (51 == child.fLineCount) { - SkDebugf(""); - } if (KeyWord::kOperator == child.fKeyWord && method && Definition::MethodType::kOperator == method->fMethodType) { eatOperator = true; @@ -1728,8 +1732,10 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first, auto aliasIter = fBmhParser->fAliasMap.find(undername); if (fBmhParser->fAliasMap.end() != aliasIter) { rootDef = aliasIter->second; + } else if (fInEnum && fEnumDef && this->findEnumSubtopic(undername, &rootDef)) { + ; } else if (!first) { - SkDebugf("unfound: %s\n", undername.c_str()); + this->fChar = start; this->reportError("reference unfound"); return ""; } diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp index 80d3e21faa..4b4e2b89be 100644 --- a/tools/bookmaker/mdOut.cpp +++ b/tools/bookmaker/mdOut.cpp @@ -93,8 +93,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, continue; } ref = string(start, t.fChar - start); - if (const Definition* def = this->isDefined(t, ref, - BmhParser::Resolvable::kOut != resolvable)) { + if (const Definition* def = this->isDefined(t, ref, resolvable)) { if (MarkType::kExternal == def->fMarkType) { add_ref(leadingSpaces, ref, &result); continue; @@ -122,7 +121,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, } string altTest = ref + '_'; altTest += suffix++; - altDef = this->isDefined(t, altTest, false); + altDef = this->isDefined(t, altTest, BmhParser::Resolvable::kOut); } if (suffix > '9') { t.reportError("too many alts"); @@ -130,13 +129,18 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, return result; } if (!foundMatch) { - if (!(def = this->isDefined(t, fullRef, - BmhParser::Resolvable::kOut != resolvable))) { - if (!result.size()) { + if (!(def = this->isDefined(t, fullRef, resolvable))) { + if (BmhParser::Resolvable::kFormula == resolvable) { + // TODO: look for looser mapping -- if methods name match, look for + // unique mapping based on number of parameters + // for now, just look for function name match + def = this->isDefined(t, ref, resolvable); + } + if (!def && !result.size()) { t.reportError("missing method"); fAddRefFailed = true; + return result; } - return result; } ref = fullRef; } @@ -145,6 +149,11 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, add_ref(leadingSpaces, ref, &result); continue; } + if (!def) { + t.reportError("missing method"); + fAddRefFailed = true; + return result; + } result += linkRef(leadingSpaces, def, ref, resolvable); continue; } @@ -156,7 +165,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, } t.next(); ref = string(start, t.fChar - start); - if (const Definition* def = this->isDefined(t, ref, true)) { + if (const Definition* def = this->isDefined(t, ref, BmhParser::Resolvable::kYes)) { SkASSERT(def->fFiddle.length()); result += linkRef(leadingSpaces, def, ref, resolvable); continue; @@ -173,15 +182,15 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, if (BmhParser::Resolvable::kOut != resolvable) { t.reportError("missed Sk prefixed"); fAddRefFailed = true; + return result; } - return result; } if (!ref.compare(0, 2, "SK")) { if (BmhParser::Resolvable::kOut != resolvable) { t.reportError("missed SK prefixed"); fAddRefFailed = true; + return result; } - return result; } if (!isupper(start[0])) { // TODO: @@ -209,7 +218,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, } } } - if (BmhParser::Resolvable::kOut != resolvable) { + if (BmhParser::Resolvable::kOut != resolvable && + BmhParser::Resolvable::kFormula != resolvable) { t.reportError("missed camelCase"); fAddRefFailed = true; return result; @@ -236,7 +246,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, if (isupper(t.fChar[1]) && startsSentence) { TextParser next(t.fFileName, &t.fChar[1], t.fEnd, t.fLineCount); string nextWord(next.fChar, next.wordEnd() - next.fChar); - if (this->isDefined(t, nextWord, true)) { + if (this->isDefined(t, nextWord, BmhParser::Resolvable::kYes)) { add_ref(leadingSpaces, ref, &result); continue; } @@ -261,6 +271,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, if (BmhParser::Resolvable::kOut != resolvable) { t.reportError("undefined reference"); fAddRefFailed = true; + } else { + add_ref(leadingSpaces, ref, &result); } } } while (!t.eof()); @@ -269,25 +281,22 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, -bool MdOut::buildReferences(const char* docDir, const char* mdFileOrPath) { +bool MdOut::buildReferences(const IncludeParser& includeParser, const char* docDir, + const char* mdFileOrPath) { if (!sk_isdir(mdFileOrPath)) { - SkString mdFile = SkOSPath::Basename(mdFileOrPath); - SkString bmhFile = SkOSPath::Join(docDir, mdFile.c_str()); - bmhFile.remove(bmhFile.size() - 3, 3); - bmhFile += ".bmh"; - SkString mdPath = SkOSPath::Dirname(mdFileOrPath); - if (!this->buildRefFromFile(bmhFile.c_str(), mdPath.c_str())) { - SkDebugf("failed to parse %s\n", mdFileOrPath); - return false; + SkDebugf("must pass directory %s\n", mdFileOrPath); + SkDebugf("pass -i SkXXX.h to build references for a single include\n"); + return false; + } + SkOSFile::Iter it(docDir, ".bmh"); + for (SkString file; it.next(&file); ) { + if (!includeParser.references(file)) { + continue; } - } else { - SkOSFile::Iter it(docDir, ".bmh"); - for (SkString file; it.next(&file); ) { - SkString p = SkOSPath::Join(docDir, file.c_str()); - if (!this->buildRefFromFile(p.c_str(), mdFileOrPath)) { - SkDebugf("failed to parse %s\n", p.c_str()); - return false; - } + SkString p = SkOSPath::Join(docDir, file.c_str()); + if (!this->buildRefFromFile(p.c_str(), mdFileOrPath)) { + SkDebugf("failed to parse %s\n", p.c_str()); + return false; } } return true; @@ -409,7 +418,7 @@ bool MdOut::checkParamReturnBody(const Definition* def) { if (!islower(descriptionStart[0]) && !isdigit(descriptionStart[0])) { paramBody.skipToNonAlphaNum(); string ref = string(descriptionStart, paramBody.fChar - descriptionStart); - if (!this->isDefined(paramBody, ref, true)) { + if (!this->isDefined(paramBody, ref, BmhParser::Resolvable::kYes)) { string errorStr = MarkType::kReturn == def->fMarkType ? "return" : "param"; errorStr += " description must start with lower case"; paramBody.reportError(errorStr.c_str()); @@ -484,7 +493,8 @@ const Definition* MdOut::findParamType() { SkASSERT(!parser.eof()); string name = string(word, parser.fChar - word); if (fLastParam->fName == name) { - const Definition* paramType = this->isDefined(parser, lastFull, false); + const Definition* paramType = this->isDefined(parser, lastFull, + BmhParser::Resolvable::kOut); return paramType; } if (isupper(name[0])) { @@ -494,7 +504,8 @@ const Definition* MdOut::findParamType() { return nullptr; } -const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, bool report) { +const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, + BmhParser::Resolvable resolvable) { auto rootIter = fBmhParser.fClassMap.find(ref); if (rootIter != fBmhParser.fClassMap.end()) { return &rootIter->second; @@ -613,7 +624,8 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, return nullptr; } } else { - if (report) { + if (BmhParser::Resolvable::kOut != resolvable && + BmhParser::Resolvable::kFormula != resolvable) { parser.reportError("SK undefined"); fAddRefFailed = true; } @@ -643,7 +655,8 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, return definition; } } - if (report) { + if (BmhParser::Resolvable::kOut != resolvable && + BmhParser::Resolvable::kFormula != resolvable) { parser.reportError("_ undefined"); fAddRefFailed = true; } @@ -797,6 +810,7 @@ void MdOut::markTypeOut(Definition* def) { FPRINTF("
");
             this->lf(1);
+            fResolveAndIndent = true;
             break;
         case MarkType::kColumn:
             this->writePending();
@@ -889,7 +903,7 @@ void MdOut::markTypeOut(Definition* def) {
                 if (def->fWrapper.length() > 0) {
                     FPRINTF("%s", def->fWrapper.c_str());
                 }
-                fRespectLeadingSpace = true;
+                fLiteralAndIndent = true;
             }
             } break;
         case MarkType::kExperimental:
@@ -1107,7 +1121,8 @@ void MdOut::markTypeOut(Definition* def) {
         case MarkType::kWidth:
             break;
         case MarkType::kPhraseDef:
-            break;
+            // skip text and children
+            return;
         case MarkType::kPhraseRef:
             if (fBmhParser.fPhraseMap.end() == fBmhParser.fPhraseMap.find(def->fName)) {
                 def->reportError("missing phrase definition");
@@ -1139,9 +1154,12 @@ void MdOut::markTypeOut(Definition* def) {
             }
             break;
         case MarkType::kCode:
+            fIndent = 0;
+            this->lf(1);
             this->writePending();
             FPRINTF("
"); this->lf(2); + fResolveAndIndent = false; break; case MarkType::kColumn: if (fInList) { @@ -1174,7 +1192,7 @@ void MdOut::markTypeOut(Definition* def) { FPRINTF(""); } this->lf(2); - fRespectLeadingSpace = false; + fLiteralAndIndent = false; break; case MarkType::kLink: this->writeString(""); @@ -1317,10 +1335,16 @@ void MdOut::populateTables(const Definition* def) { } void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) { - if ((BmhParser::Resolvable::kLiteral == resolvable || fRespectLeadingSpace) && end > start) { + if ((BmhParser::Resolvable::kLiteral == resolvable || fLiteralAndIndent || + fResolveAndIndent) && end > start) { + int linefeeds = 0; while ('\n' == *start) { + ++linefeeds; ++start; } + if (fResolveAndIndent && linefeeds) { + this->lf(linefeeds); + } const char* spaceStart = start; while (' ' == *start) { ++start; @@ -1328,6 +1352,8 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable if (start > spaceStart) { fIndent = start - spaceStart; } + } + if (BmhParser::Resolvable::kLiteral == resolvable || fLiteralAndIndent) { this->writeBlockTrim(end - start, start); if ('\n' == end[-1]) { this->lf(1); @@ -1347,14 +1373,20 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable trim_end_spaces(resolved); if (resolved.length()) { TextParser paragraph(fFileName, &*resolved.begin(), &*resolved.end(), fLineCount); - TextParser original(fFileName, start, end, fLineCount); - while (!original.eof() && '\n' == original.peek()) { - original.next(); - } - original.skipSpace(); while (!paragraph.eof()) { + while ('\n' == paragraph.peek()) { + paragraph.next(); + if (paragraph.eof()) { + return; + } + } + const char* lineStart = paragraph.fChar; paragraph.skipWhiteSpace(); const char* contentStart = paragraph.fChar; + if (fResolveAndIndent && contentStart > lineStart) { + this->writePending(); + this->indentToColumn(contentStart - lineStart); + } paragraph.skipToEndBracket('\n'); ptrdiff_t lineLength = paragraph.fChar - contentStart; if (lineLength) { @@ -1364,17 +1396,6 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable string str(contentStart, lineLength); this->writeString(str.c_str()); } -#if 0 - int linefeeds = 0; - while (lineLength > 0 && '\n' == contentStart[--lineLength]) { - - ++linefeeds; - } - if (lineLength > 0) { - this->nl(); - } - fLinefeeds += linefeeds; -#endif if (paragraph.eof()) { break; } @@ -1386,12 +1407,6 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable this->lf(linefeeds); } } -#if 0 - while (end > start && end[0] == '\n') { - FPRINTF("\n"); - --end; - } -#endif } } diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp index 2e9ad81e45..072c996df3 100644 --- a/tools/bookmaker/parserCommon.cpp +++ b/tools/bookmaker/parserCommon.cpp @@ -14,13 +14,13 @@ static void debug_out(int len, const char* data) { SkDebugf("%.*s", len, data); } -bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix) { +bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix, OneFile oneFile) { if (!sk_isdir(fileOrPath)) { if (!this->parseFromFile(fileOrPath)) { SkDebugf("failed to parse %s\n", fileOrPath); return false; } - } else { + } else if (OneFile::kNo == oneFile) { SkOSFile::Iter it(fileOrPath, suffix); for (SkString file; it.next(&file); ) { SkString p = SkOSPath::Join(fileOrPath, file.c_str()); -- cgit v1.2.3