From 4855f78dd16ad50003ec537c98062e24a831cd45 Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Tue, 6 Feb 2018 09:41:53 -0500 Subject: fix bookmaker nightly - mark the interfaces that use SkMask as deprecated - add more autogenerated subtopics - make subtopic names singular, avoiding collision with Skia names - simplify #Deprecated and #Bug tags - add "#Deprecated soon" to note things to be deprecated - fix some spelling errors - refresh web docs - add self-check functionality to find methods outside subtopics TBR=caryclark@google.com Docs-Preview: https://skia.org/?cl=102150 Bug: skia:6898 Change-Id: I0e742a56d49dccd4409bb68eed9167c8ad7611ce Reviewed-on: https://skia-review.googlesource.com/102150 Commit-Queue: Cary Clark Reviewed-by: Cary Clark --- tools/bookmaker/bookmaker.cpp | 44 +++-- tools/bookmaker/bookmaker.h | 44 +++-- tools/bookmaker/definition.cpp | 17 ++ tools/bookmaker/includeWriter.cpp | 38 +++- tools/bookmaker/mdOut.cpp | 61 ++++-- tools/bookmaker/selfCheck.cpp | 394 +++----------------------------------- tools/bookmaker/spellCheck.cpp | 45 ++--- 7 files changed, 197 insertions(+), 446 deletions(-) (limited to 'tools/bookmaker') diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index 0de8a46f3a..9d5a2782f3 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -248,7 +248,6 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy case MarkType::kDescription: case MarkType::kStdOut: // may be one-liner - case MarkType::kBug: case MarkType::kNoExample: case MarkType::kParam: case MarkType::kReturn: @@ -285,7 +284,6 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy } // not one-liners case MarkType::kCode: - case MarkType::kDeprecated: case MarkType::kExample: case MarkType::kExperimental: case MarkType::kFormula: @@ -344,7 +342,9 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy // always treated as one-liners (can't detect misuse easily) case MarkType::kAlias: case MarkType::kAnchor: + case MarkType::kBug: case MarkType::kDefine: + case MarkType::kDeprecated: case MarkType::kDuration: case MarkType::kFile: case MarkType::kHeight: @@ -361,6 +361,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy case MarkType::kTime: case MarkType::kVolatile: case MarkType::kWidth: + // todo : add check disallowing children? if (hasEnd && MarkType::kAnchor != markType && MarkType::kLine != markType) { return this->reportError("one liners omit end element"); } else if (!hasEnd && MarkType::kAnchor == markType) { @@ -415,7 +416,15 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy definition->fContentEnd = text->fContentEnd; definition->fTerminator = fChar; definition->fChildren.emplace_back(text); - } + } else if (MarkType::kDeprecated == markType) { + this->skipSpace(); + fParent->fDeprecated = true; + fParent->fToBeDeprecated = this->skipExact("soon"); + this->skipSpace(); + if ('\n' != this->peek()) { + return this->reportError("unexpected text after #Deprecated"); + } + } break; case MarkType::kExternal: (void) this->collectExternals(); // FIXME: detect errors in external defs? @@ -1250,6 +1259,20 @@ TextParser::TextParser(const Definition* definition) : definition->fLineCount) { } +string TextParser::ReportFilename(string file) { + string fullName; +#ifdef SK_BUILD_FOR_WIN + TCHAR pathChars[MAX_PATH]; + DWORD pathLen = GetCurrentDirectory(MAX_PATH, pathChars); + for (DWORD index = 0; index < pathLen; ++index) { + fullName += pathChars[index] == (char)pathChars[index] ? (char)pathChars[index] : '?'; + } + fullName += '\\'; +#endif + fullName += file; + return fullName; +} + void TextParser::reportError(const char* errorStr) const { this->reportWarning(errorStr); SkDebugf(""); // convenient place to set a breakpoint @@ -1265,17 +1288,8 @@ void TextParser::reportWarning(const char* errorStr) const { spaces -= lineLen; lineLen = err.lineLength(); } - string fileName; -#ifdef SK_BUILD_FOR_WIN - TCHAR pathChars[MAX_PATH]; - DWORD pathLen = GetCurrentDirectory(MAX_PATH, pathChars); - for (DWORD index = 0; index < pathLen; ++index) { - fileName += pathChars[index] == (char)pathChars[index] ? (char)pathChars[index] : '?'; - } - fileName += '\\'; -#endif - fileName += fFileName; - SkDebugf("\n%s(%zd): error: %s\n", fileName.c_str(), err.fLineCount, errorStr); + string fullName = this->ReportFilename(fFileName); + SkDebugf("\n%s(%zd): error: %s\n", fullName.c_str(), err.fLineCount, errorStr); if (0 == lineLen) { SkDebugf("[blank line]\n"); } else { @@ -1476,7 +1490,6 @@ vector BmhParser::typeName(MarkType markType, bool* checkEnd) { this->skipNoName(); break; case MarkType::kCode: - case MarkType::kDeprecated: case MarkType::kDescription: case MarkType::kDoxygen: case MarkType::kExperimental: @@ -1498,6 +1511,7 @@ vector BmhParser::typeName(MarkType markType, bool* checkEnd) { case MarkType::kBug: // fixme: expect number case MarkType::kDefine: case MarkType::kDefinedBy: + case MarkType::kDeprecated: case MarkType::kDuration: case MarkType::kFile: case MarkType::kHeight: diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index 65e8f1562a..96372756a1 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -390,6 +390,7 @@ public: } void reportError(const char* errorStr) const; + static string ReportFilename(string file); void reportWarning(const char* errorStr) const; template T reportError(const char* errorStr) const { @@ -841,6 +842,7 @@ public: bool exampleToScript(string* result, ExampleOptions ) const; string extractText(TrimExtract trimExtract) const; string fiddleName() const; + const Definition* findClone(string match) const; string formatFunction() const; const Definition* hasChild(MarkType markType) const; bool hasMatch(const string& name) const; @@ -919,9 +921,11 @@ public: Type fType = Type::kNone; bool fClone = false; bool fCloned = false; + bool fDeprecated = false; bool fOperatorConst = false; bool fPrivate = false; bool fShort = false; + bool fToBeDeprecated = false; bool fMemberStart = false; bool fAnonymous = false; mutable bool fVisited = false; @@ -2034,15 +2038,15 @@ public: bool buildReferences(const char* docDir, const char* mdOutDirOrFile); bool buildStatus(const char* docDir, const char* mdOutDir); - static constexpr const char* kClassesAndStructs = "Classes_and_Structs"; - static constexpr const char* kConstants = "Constants"; - static constexpr const char* kConstructors = "Constructors"; - static constexpr const char* kMemberFunctions = "Member_Functions"; - static constexpr const char* kMembers = "Members"; - static constexpr const char* kOperators = "Operators"; + static constexpr const char* kClassesAndStructs = "Class_or_Struct"; + static constexpr const char* kConstants = "Constant"; + static constexpr const char* kConstructors = "Constructor"; + static constexpr const char* kMemberFunctions = "Member_Function"; + static constexpr const char* kMembers = "Member"; + static constexpr const char* kOperators = "Operator"; static constexpr const char* kOverview = "Overview"; - static constexpr const char* kRelatedFunctions = "Related_Functions"; - static constexpr const char* kSubtopics = "Subtopics"; + static constexpr const char* kRelatedFunctions = "Related_Function"; + static constexpr const char* kSubtopics = "Subtopic"; private: enum class TableState { @@ -2051,6 +2055,16 @@ private: kColumn, }; + struct TableContents { + TableContents() + : fShowClones(false) { + } + + string fDescription; + vector fMembers; + bool fShowClones; + }; + string addReferences(const char* start, const char* end, BmhParser::Resolvable ); bool buildRefFromFile(const char* fileName, const char* outDir); bool checkParamReturnBody(const Definition* def) const; @@ -2068,8 +2082,11 @@ private: bool parseFromFile(const char* path) override { return true; } void populateTables(const Definition* def); - vector& populator(const char* key) { - return fPopulators.find(key)->second.fMembers; + TableContents& populator(const char* key) { + auto entry = fPopulators.find(key); + // FIXME: this should have been detected earlier + SkASSERT(fPopulators.end() != entry); + return entry->second; } void reset() override { @@ -2103,14 +2120,9 @@ private: void resolveOut(const char* start, const char* end, BmhParser::Resolvable ); void rowOut(const char * name, const string& description); - void subtopicOut(vector& data); + void subtopicOut(const TableContents& tableContents); void subtopicsOut(); - struct TableContents { - string fDescription; - vector fMembers; - }; - unordered_map fPopulators; vector fClassStack; diff --git a/tools/bookmaker/definition.cpp b/tools/bookmaker/definition.cpp index 7885c6301c..757169b1a9 100644 --- a/tools/bookmaker/definition.cpp +++ b/tools/bookmaker/definition.cpp @@ -560,6 +560,7 @@ bool Definition::exampleToScript(string* result, ExampleOptions exampleOptions) break; case MarkType::kToDo: break; + case MarkType::kBug: case MarkType::kMarkChar: case MarkType::kPlatform: // ignore for now @@ -1014,6 +1015,22 @@ string Definition::fiddleName() const { return fFiddle.substr(start, end - start); } +const Definition* Definition::findClone(string match) const { + for (auto child : fChildren) { + if (!child->fClone) { + continue; + } + if (match == child->fName) { + return child; + } + auto inner = child->findClone(match); + if (inner) { + return inner; + } + } + return nullptr; +} + const Definition* Definition::hasChild(MarkType markType) const { for (auto iter : fChildren) { if (markType == iter->fMarkType) { diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index ba93d3e615..77baca0016 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -53,6 +53,13 @@ void IncludeWriter::descriptionOut(const Definition* def) { commentStart = prop->fTerminator; break; case MarkType::kDeprecated: + SkASSERT(def->fDeprecated); + if (def->fToBeDeprecated) { + this->writeString("To be deprecated soon."); + } else { + this->writeString("Deprecated."); + } + this->lfcr(); case MarkType::kPrivate: commentLen = (int) (prop->fStart - commentStart); if (commentLen > 0) { @@ -62,6 +69,9 @@ void IncludeWriter::descriptionOut(const Definition* def) { } } commentStart = prop->fContentStart; + if (def->fToBeDeprecated) { + commentStart += 4; // skip over "soon" // FIXME: this is awkward + } commentLen = (int) (prop->fContentEnd - commentStart); if (commentLen > 0) { this->writeBlockIndent(commentLen, commentStart); @@ -159,7 +169,7 @@ void IncludeWriter::descriptionOut(const Definition* def) { break; } } - SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500)); + SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500) || def->fDeprecated); if (commentLen > 0) { this->rewriteBlock(commentLen, commentStart, Phrase::kNo); } @@ -440,23 +450,35 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child commentEnd = currentEnumItem->fContentEnd; } TextParser enumComment(fFileName, commentStart, commentEnd, currentEnumItem->fLineCount); + bool isDeprecated = false; if (enumComment.skipToLineStart()) { // skip const value commentStart = enumComment.fChar; commentLen = (int) (commentEnd - commentStart); } else { - const Definition* privateDef = currentEnumItem->fChildren[0]; - SkASSERT(MarkType::kPrivate == privateDef->fMarkType); - commentStart = privateDef->fContentStart; - commentLen = (int) (privateDef->fContentEnd - privateDef->fContentStart); + const Definition* childDef = currentEnumItem->fChildren[0]; + isDeprecated = MarkType::kDeprecated == childDef->fMarkType; + if (MarkType::kPrivate == childDef->fMarkType || isDeprecated) { + commentStart = childDef->fContentStart; + if (currentEnumItem->fToBeDeprecated) { + SkASSERT(isDeprecated); + commentStart += 4; // skip over "soon" // FIXME: this is awkward + } + commentLen = (int) (childDef->fContentEnd - commentStart); + } } // FIXME: may assert here if there's no const value // should have detected and errored on that earlier when enum fContentStart was set - SkASSERT(commentLen > 0 && commentLen < 1000); + SkASSERT((commentLen > 0 && commentLen < 1000) || isDeprecated); if (!currentEnumItem->fShort) { this->writeCommentHeader(); fIndent += 4; - bool wroteLineFeed = Wrote::kLF == - this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + bool wroteLineFeed = false; + if (isDeprecated) { + this->writeString(currentEnumItem->fToBeDeprecated + ? "To be deprecated soon." : "Deprecated."); + } + wroteLineFeed = Wrote::kLF == + this->rewriteBlock(commentLen, commentStart, Phrase::kNo); fIndent -= 4; if (wroteLineFeed || fColumn > 100 - 3 /* space * / */ ) { this->lfcr(); diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp index b51bb8d77e..7bc70af669 100644 --- a/tools/bookmaker/mdOut.cpp +++ b/tools/bookmaker/mdOut.cpp @@ -975,9 +975,6 @@ void MdOut::markTypeOut(Definition* def) { if (kSubtopics == name) { this->subtopicsOut(); } else { - SkASSERT(kClassesAndStructs == name || kConstants == name || kConstructors == name - || kMemberFunctions == name || kMembers == name || kOperators == name - || kRelatedFunctions == name); this->subtopicOut(this->populator(name.c_str())); } } break; @@ -1187,17 +1184,20 @@ void MdOut::mdHeaderOutLF(int depth, int lf) { void MdOut::populateTables(const Definition* def) { const Definition* csParent = this->csParent(); for (auto child : def->fChildren) { + if (string::npos != child->fName.find("Rect_Set")) { + SkDebugf(""); + } if (MarkType::kTopic == child->fMarkType || MarkType::kSubtopic == child->fMarkType) { bool legacyTopic = fPopulators.end() != fPopulators.find(child->fName); if (!legacyTopic && child->fName != kOverview) { - this->populator(kRelatedFunctions).push_back(child); + this->populator(kRelatedFunctions).fMembers.push_back(child); } this->populateTables(child); continue; } if (child->isStructOrClass()) { if (fClassStack.size() > 0) { - this->populator(kClassesAndStructs).push_back(child); + this->populator(kClassesAndStructs).fMembers.push_back(child); } fClassStack.push_back(child); this->populateTables(child); @@ -1205,11 +1205,11 @@ void MdOut::populateTables(const Definition* def) { continue; } if (MarkType::kEnum == child->fMarkType || MarkType::kEnumClass == child->fMarkType) { - this->populator(kConstants).push_back(child); + this->populator(kConstants).fMembers.push_back(child); continue; } if (MarkType::kMember == child->fMarkType) { - this->populator(kMembers).push_back(child); + this->populator(kMembers).fMembers.push_back(child); continue; } if (MarkType::kMethod != child->fMarkType) { @@ -1220,17 +1220,26 @@ void MdOut::populateTables(const Definition* def) { } if (Definition::MethodType::kConstructor == child->fMethodType || Definition::MethodType::kDestructor == child->fMethodType) { - this->populator(kConstructors).push_back(child); + this->populator(kConstructors).fMembers.push_back(child); continue; } if (Definition::MethodType::kOperator == child->fMethodType) { - this->populator(kOperators).push_back(child); + this->populator(kOperators).fMembers.push_back(child); continue; } - this->populator(kMemberFunctions).push_back(child); + this->populator(kMemberFunctions).fMembers.push_back(child); if (csParent && (0 == child->fName.find(csParent->fName + "::Make") || 0 == child->fName.find(csParent->fName + "::make"))) { - this->populator(kConstructors).push_back(child); + this->populator(kConstructors).fMembers.push_back(child); + continue; + } + for (auto item : child->fChildren) { + if (MarkType::kIn == item->fMarkType) { + string name(item->fContentStart, item->fContentEnd - item->fContentStart); + fPopulators[name].fMembers.push_back(child); + fPopulators[name].fShowClones = true; + break; + } } } } @@ -1331,7 +1340,7 @@ void MdOut::subtopicsOut() { this->rowOut("---", "---"); for (auto item : { kClassesAndStructs, kConstants, kConstructors, kMemberFunctions, kMembers, kOperators, kRelatedFunctions } ) { - for (auto entry : this->populator(item)) { + for (auto entry : this->populator(item).fMembers) { if (entry->csParent() == csParent) { string description = fPopulators.find(item)->second.fDescription; if (kConstructors == item) { @@ -1344,7 +1353,8 @@ void MdOut::subtopicsOut() { } } -void MdOut::subtopicOut(vector& data) { +void MdOut::subtopicOut(const TableContents& tableContents) { + const auto& data = tableContents.fMembers; const Definition* csParent = this->csParent(); SkASSERT(csParent); fRoot = csParent->asRoot(); @@ -1360,6 +1370,9 @@ void MdOut::subtopicOut(vector& data) { items[name] = entry; } for (auto entry : items) { + if (entry.second->fDeprecated) { + continue; + } const Definition* oneLiner = nullptr; for (auto child : entry.second->fChildren) { if (MarkType::kLine == child->fMarkType) { @@ -1367,8 +1380,30 @@ void MdOut::subtopicOut(vector& data) { break; } } + if (!oneLiner) { + SkDebugf(""); + } SkASSERT(oneLiner); this->rowOut(entry.first.c_str(), string(oneLiner->fContentStart, oneLiner->fContentEnd - oneLiner->fContentStart)); + if (string::npos != entry.second->fName.find("SkRect::set")) { + SkDebugf(""); + } + if (tableContents.fShowClones && entry.second->fCloned) { + int cloneNo = 2; + string builder = entry.second->fName; + if ("()" == builder.substr(builder.length() - 2)) { + builder = builder.substr(0, builder.length() - 2); + } + builder += '_'; + do { + string match = builder + to_string(cloneNo); + auto child = csParent->findClone(match); + if (!child) { + break; + } + this->rowOut("", child->methodName()); + } while (++cloneNo); + } } } diff --git a/tools/bookmaker/selfCheck.cpp b/tools/bookmaker/selfCheck.cpp index fd8ef59fa1..3392945a9f 100644 --- a/tools/bookmaker/selfCheck.cpp +++ b/tools/bookmaker/selfCheck.cpp @@ -7,11 +7,12 @@ #include "bookmaker.h" +#ifdef SK_BUILD_FOR_WIN +#include +#endif // Check that mutiple like-named methods are under one Subtopic -// Check that all subtopics are in table of contents - // Check that SeeAlso reference each other // Would be nice to check if other classes have 'create' methods that are included @@ -33,27 +34,10 @@ public: return fBmhParser.reportError("expected root topic"); } fRoot = topicDef->asRoot(); - if (!this->checkMethodSummary()) { - return false; - } - if (!this->checkMethodSubtopic()) { - return false; - } - if (!this->checkSubtopicSummary()) { - return false; - } - if (!this->checkConstructorsSummary()) { - return false; - } - if (!this->checkOperatorsSummary()) { - return false; - } if (!this->checkSeeAlso()) { return false; } - if (!this->checkCreators()) { - return false; - } + // report functions that are not covered by related hierarchy if (!this->checkRelatedFunctions()) { return false; } @@ -62,164 +46,8 @@ public: } protected: - // Check that all constructors are in a table of contents - // should be 'creators' instead of constructors? - bool checkConstructorsSummary() { - for (auto& rootChild : fRoot->fChildren) { - if (!rootChild->isStructOrClass()) { - continue; - } - auto& cs = rootChild; - auto constructors = this->findTopic("Constructors", Optional::kYes); - if (constructors && MarkType::kSubtopic != constructors->fMarkType) { - return constructors->reportError("expected #Subtopic Constructors"); - } - vector constructorEntries; - if (constructors) { - if (!this->collectEntries(constructors, &constructorEntries)) { - return false; - } - } - // mark corresponding methods as visited (may be more than one per entry) - for (auto& csChild : cs->fChildren) { - if (MarkType::kMethod != csChild->fMarkType) { - // only check methods for now - continue; - } - string name; - if (!this->childName(csChild, &name)) { - return false; - } - string returnType; - if (Definition::MethodType::kConstructor != csChild->fMethodType && - Definition::MethodType::kDestructor != csChild->fMethodType) { - string makeCheck = name.substr(0, 4); - if ("Make" != makeCheck && "make" != makeCheck) { - continue; - } - // for now, assume return type of interest is first word to start Sk - string search(csChild->fStart, csChild->fContentStart - csChild->fStart); - auto end = search.find(makeCheck); - if (string::npos == end) { - return csChild->reportError("expected Make in content"); - } - search = search.substr(0, end); - if (string::npos == search.find(cs->fName)) { - // if return value doesn't match current struct or class, look in - // returned struct / class instead - auto sk = search.find("Sk"); - if (string::npos != sk) { - // todo: build class name, find it, search for match in its overview - continue; - } - } - } - if (constructorEntries.end() == - std::find(constructorEntries.begin(), constructorEntries.end(), name)) { - return csChild->reportError("missing constructor in Constructors"); - } - } - } - return true; - } - - bool checkCreators() { - return true; - } - - bool checkMethodSubtopic() { - return true; - } - - // Check that summary contains all methods - bool checkMethodSummary() { - // look for struct or class in fChildren - const Definition* cs = this->classOrStruct(); - if (!cs) { - return true; // topics may not have included classes or structs - } - auto memberFunctions = this->findTopic("Member_Functions", Optional::kNo); - if (MarkType::kSubtopic != memberFunctions->fMarkType) { - return memberFunctions->reportError("expected #Subtopic Member_Functions"); - } - vector methodEntries; // build map of overview entries - if (!this->collectEntries(memberFunctions, &methodEntries)) { - return false; - } - // mark corresponding methods as visited (may be more than one per entry) - for (auto& csChild : cs->fChildren) { - if (MarkType::kMethod != csChild->fMarkType) { - // only check methods for now - continue; - } - if (Definition::MethodType::kConstructor == csChild->fMethodType) { - continue; - } - if (Definition::MethodType::kDestructor == csChild->fMethodType) { - continue; - } - if (Definition::MethodType::kOperator == csChild->fMethodType) { - continue; - } - string name; - if (!this->childName(csChild, &name)) { - return false; - } - if (methodEntries.end() == - std::find(methodEntries.begin(), methodEntries.end(), name)) { - return csChild->reportError("missing method in Member_Functions"); - } - } - return true; - } - - // Check that all operators are in a table of contents - bool checkOperatorsSummary() { - const Definition* cs = this->classOrStruct(); - if (!cs) { - return true; // topics may not have included classes or structs - } - const Definition* operators = this->findTopic("Operators", Optional::kYes); - if (operators && MarkType::kSubtopic != operators->fMarkType) { - return operators->reportError("expected #Subtopic Operators"); - } - vector operatorEntries; - if (operators) { - if (!this->collectEntries(operators, &operatorEntries)) { - return false; - } - } - for (auto& csChild : cs->fChildren) { - if (Definition::MethodType::kOperator != csChild->fMethodType) { - continue; - } - string name; - if (!this->childName(csChild, &name)) { - return false; - } - bool found = false; - for (auto str : operatorEntries) { - if (string::npos != str.find(name)) { - found = true; - break; - } - } - if (!found) { - return csChild->reportError("missing operator in Operators"); - } - } - return true; - } bool checkRelatedFunctions() { - auto related = this->findTopic("Related_Functions", Optional::kYes); - if (!related) { - return true; - } - vector relatedEntries; - if (!this->collectEntries(related, &relatedEntries)) { - return false; - } const Definition* cs = this->classOrStruct(); vector methodNames; if (cs) { @@ -243,36 +71,28 @@ protected: // since format of clones is in flux, defer this check for now continue; } - - SkASSERT(string::npos != csChild->fName.find(prefix)); - string name = csChild->fName.substr(csChild->fName.find(prefix)); - methodNames.push_back(name); - } - } - vector trim = methodNames; - for (auto entryName : relatedEntries) { - auto entryDef = this->findTopic(entryName, Optional::kNo); - if (!entryDef) { - - } - vector entries; - this->collectEntries(entryDef, &entries); - for (auto entry : entries) { - auto it = std::find(methodNames.begin(), methodNames.end(), entry); - if (it == methodNames.end()) { - return cs->reportError("missing method"); - } - it = std::find(trim.begin(), trim.end(), entry); - if (it != trim.end()) { - using std::swap; - swap(*it, trim.back()); - trim.pop_back(); - } + bool containsMarkTypeIn = csChild->fDeprecated; // no markup for deprecated + for (auto child : csChild->fChildren) { + if (MarkType::kIn == child->fMarkType) { + containsMarkTypeIn = true; + break; + } + } + if (!containsMarkTypeIn) { +#ifdef SK_BUILD_FOR_WIN + /* SkDebugf works in both visual studio and git shell, but + in git shell output is not piped to grep. + printf does not generate output in visual studio, but + does in git shell and can be piped. + */ + if (IsDebuggerPresent()) { + SkDebugf("No #In: %s\n", csChild->fName.c_str()); + } else +#endif + printf("No #In: %s\n", csChild->fName.c_str()); + } } } - if (trim.size() > 0) { - return cs->reportError("extra method"); - } return true; } @@ -280,81 +100,6 @@ protected: return true; } - bool checkSubtopicSummary() { - const auto& cs = this->classOrStruct(); - if (!cs) { - return true; - } - auto overview = this->findOverview(cs); - if (!overview) { - return false; - } - const Definition* subtopics = this->findTopic("Subtopics", Optional::kNo); - if (MarkType::kSubtopic != subtopics->fMarkType) { - return subtopics->reportError("expected #Subtopic Subtopics"); - } - const Definition* relatedFunctions = this->findTopic("Related_Functions", Optional::kYes); - if (relatedFunctions && MarkType::kSubtopic != relatedFunctions->fMarkType) { - return relatedFunctions->reportError("expected #Subtopic Related_Functions"); - } - vector subtopicEntries; - if (!this->collectEntries(subtopics, &subtopicEntries)) { - return false; - } - if (relatedFunctions && !this->collectEntries(relatedFunctions, &subtopicEntries)) { - return false; - } - for (auto& csChild : cs->fChildren) { - if (MarkType::kSubtopic != csChild->fMarkType) { - continue; - } - string name; - if (!this->childName(csChild, &name)) { - return false; - } - bool found = false; - for (auto str : subtopicEntries) { - if (string::npos != str.find(name)) { - found = true; - break; - } - } - if (!found) { - return csChild->reportError("missing SubTopic in SubTopics"); - } - } - return true; - } - - bool childName(const Definition* def, string* name) { - auto start = def->fName.find_last_of(':'); - start = string::npos == start ? 0 : start + 1; - *name = def->fName.substr(start); - if (def->fClone) { - auto lastUnderline = name->find_last_of('_'); - if (string::npos == lastUnderline) { - return def->reportError("expect _ in name"); - } - if (lastUnderline + 1 >= name->length()) { - return def->reportError("expect char after _ in name"); - } - for (auto index = lastUnderline + 1; index < name->length(); ++index) { - if (!isdigit((*name)[index])) { - return def->reportError("expect digit after _ in name"); - } - } - *name = name->substr(0, lastUnderline); - bool allLower = true; - for (auto ch : *name) { - allLower &= (bool) islower(ch); - } - if (allLower) { - *name += "()"; - } - } - return true; - } - const Definition* classOrStruct() { for (auto& rootChild : fRoot->fChildren) { if (rootChild->isStructOrClass()) { @@ -364,102 +109,11 @@ protected: return nullptr; } - static const Definition* overview_def(const Definition* parent) { - Definition* overview = nullptr; - if (parent) { - for (auto& csChild : parent->fChildren) { - if ("Overview" == csChild->fName) { - if (overview) { - return csChild->reportError("expected only one Overview"); - } - overview = csChild; - } - } - } - return overview; - } - - const Definition* findOverview(const Definition* parent) { - // expect Overview as Topic in every main class or struct - const Definition* overview = overview_def(parent); - const Definition* parentOverview = parent ? overview_def(parent->fParent) : nullptr; - if (overview && parentOverview) { - return overview->reportError("expected only one Overview 2"); - } - overview = overview ? overview : parentOverview; - if (!overview) { - return parent->reportError("missing #Topic Overview"); - } - return overview; - } - enum class Optional { kNo, kYes, }; - const Definition* findTopic(string name, Optional optional) { - string undashed = name; - std::replace(undashed.begin(), undashed.end(), '-', '_'); - string topicKey = fRoot->fName + '_' + undashed; - auto topicKeyIter = fBmhParser.fTopicMap.find(topicKey); - if (fBmhParser.fTopicMap.end() == topicKeyIter) { - // TODO: remove this and require member functions outside of overview - topicKey = fRoot->fName + "_Overview_" + undashed; // legacy form for now - topicKeyIter = fBmhParser.fTopicMap.find(topicKey); - if (fBmhParser.fTopicMap.end() == topicKeyIter) { - if (Optional::kNo == optional) { - return fRoot->reportError("missing subtopic"); - } - return nullptr; - } - } - return topicKeyIter->second; - } - - bool collectEntries(const Definition* entries, vector* strings) { - const Definition* table = nullptr; - for (auto& child : entries->fChildren) { - if (MarkType::kTable == child->fMarkType && child->fName == entries->fName) { - table = child; - break; - } - } - if (!table) { - return entries->reportError("missing #Table in Overview Subtopic"); - } - bool expectLegend = true; - string prior = " "; // expect entries to be alphabetical - for (auto& row : table->fChildren) { - if (MarkType::kLegend == row->fMarkType) { - if (!expectLegend) { - return row->reportError("expect #Legend only once"); - } - // todo: check if legend format matches table's rows' format - expectLegend = false; - } else if (expectLegend) { - return row->reportError("expect #Legend first"); - } - if (MarkType::kRow != row->fMarkType) { - continue; // let anything through for now; can tighten up in the future - } - // expect column 0 to point to function name - Definition* column0 = row->fChildren[0]; - string name = string(column0->fContentStart, - column0->fContentEnd - column0->fContentStart); - if (prior > name) { - return row->reportError("expect alphabetical order"); - } - if (prior == name) { - return row->reportError("expect unique names"); - } - // todo: error if name is all lower case and doesn't end in () - strings->push_back(name); - prior = name; - } - return true; - } - private: const BmhParser& fBmhParser; RootDefinition* fRoot; diff --git a/tools/bookmaker/spellCheck.cpp b/tools/bookmaker/spellCheck.cpp index 0daa4602ad..efc79ca528 100644 --- a/tools/bookmaker/spellCheck.cpp +++ b/tools/bookmaker/spellCheck.cpp @@ -53,7 +53,6 @@ private: INHERITED::resetCommon(); fMethod = nullptr; fRoot = nullptr; - fTableState = TableState::kNone; fInCode = false; fInConst = false; fInFormula = false; @@ -74,7 +73,7 @@ private: const BmhParser& fBmhParser; Definition* fMethod; RootDefinition* fRoot; - TableState fTableState; + int fLocalLine; bool fInCode; bool fInConst; bool fInDescription; @@ -136,10 +135,6 @@ bool SpellCheck::check(Definition* def) { fLineCount = def->fLineCount; string printable = def->printableName(); const char* textStart = def->fContentStart; - if (MarkType::kParam != def->fMarkType && MarkType::kConst != def->fMarkType && - MarkType::kPrivate != def->fMarkType && TableState::kNone != fTableState) { - fTableState = TableState::kNone; - } switch (def->fMarkType) { case MarkType::kAlias: break; @@ -159,12 +154,6 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kConst: { fInConst = true; - if (TableState::kNone == fTableState) { - fTableState = TableState::kRow; - } - if (TableState::kRow == fTableState) { - fTableState = TableState::kColumn; - } this->wordCheck(def->fName); const char* lineEnd = strchr(textStart, '\n'); this->wordCheck(lineEnd - textStart, textStart); @@ -204,8 +193,12 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kImage: break; + case MarkType::kIn: + break; case MarkType::kLegend: break; + case MarkType::kLine: + break; case MarkType::kLink: break; case MarkType::kList: @@ -225,7 +218,6 @@ bool SpellCheck::check(Definition* def) { if (!def->isClone() && Definition::MethodType::kOperator != def->fMethodType) { this->wordCheck(method_name); } - fTableState = TableState::kNone; fMethod = def; } break; case MarkType::kNoExample: @@ -233,12 +225,6 @@ bool SpellCheck::check(Definition* def) { case MarkType::kOutdent: break; case MarkType::kParam: { - if (TableState::kNone == fTableState) { - fTableState = TableState::kRow; - } - if (TableState::kRow == fTableState) { - fTableState = TableState::kColumn; - } TextParser paramParser(def->fFileName, def->fStart, def->fContentStart, def->fLineCount); paramParser.skipWhiteSpace(); @@ -254,6 +240,8 @@ bool SpellCheck::check(Definition* def) { } break; case MarkType::kPlatform: break; + case MarkType::kPopulate: + break; case MarkType::kPrivate: break; case MarkType::kReturn: @@ -262,6 +250,8 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kSeeAlso: break; + case MarkType::kSet: + break; case MarkType::kStdOut: { fInStdOut = true; TextParser code(def); @@ -336,8 +326,6 @@ bool SpellCheck::check(Definition* def) { case MarkType::kConst: fInConst = false; case MarkType::kParam: - SkASSERT(TableState::kColumn == fTableState); - fTableState = TableState::kRow; break; case MarkType::kReturn: case MarkType::kSeeAlso: @@ -390,6 +378,7 @@ void SpellCheck::leafCheck(const char* start, const char* end) { const char* wordStart = nullptr; const char* wordEnd = nullptr; const char* possibleEnd = nullptr; + fLocalLine = 0; do { if (wordStart && wordEnd) { if (!allLower || (!inQuotes && '\"' != lastCh && !inParens @@ -457,6 +446,9 @@ void SpellCheck::leafCheck(const char* start, const char* end) { allLower = false; case '-': // note that dash doesn't clear allLower break; + case '\n': + ++fLocalLine; + // fall through default: wordEnd = chPtr; break; @@ -492,7 +484,8 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) { continue; } if (iter.second.fCount == 1) { - SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine, + string fullName = this->ReportFilename(iter.second.fFile); + SkDebugf("%s(%d): %s\n", fullName.c_str(), iter.second.fLine, iter.first.c_str()); } } @@ -562,7 +555,8 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) { break; } if (check.compare(mispelled) == 0) { - SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine, + string fullName = this->ReportFilename(iter.second.fFile); + SkDebugf("%s(%d): %s\n", fullName.c_str(), iter.second.fLine, iter.first.c_str()); if (report.count() == ++index) { break; @@ -651,9 +645,12 @@ void SpellCheck::wordCheck(const string& str) { if (mappy.end() != iter) { iter->second.fCount += 1; } else { + if ("offscreen" == str) { + SkDebugf(""); + } CheckEntry* entry = &mappy[str]; entry->fFile = fFileName; - entry->fLine = fLineCount; + entry->fLine = fLineCount + fLocalLine; entry->fCount = 1; } } -- cgit v1.2.3