From ce1012403bacf017c0d91c779fa9e9bddd1475f8 Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Fri, 1 Sep 2017 15:51:02 -0400 Subject: bookmaker spelling with fixed linux build Work on spell-checker to identify errors and isolate more concepts requiring definitions. fix linux build Docs-Preview: https://skia.org/?cl=42103 Docs-Preview: https://skia.org/?cl=41180 Tbr: caryclark@google.com Bug: skia: 6898 Change-Id: Id939b0c2915c22e0fa1b15623c1a56fbe9d4051d Reviewed-on: https://skia-review.googlesource.com/42103 Reviewed-by: Cary Clark Commit-Queue: Cary Clark --- tools/bookmaker/bookmaker.cpp | 143 ++++++++++++++-------- tools/bookmaker/bookmaker.h | 157 ++++++++++++++---------- tools/bookmaker/includeParser.cpp | 26 ++-- tools/bookmaker/includeWriter.cpp | 50 ++++---- tools/bookmaker/mdOut.cpp | 23 ++-- tools/bookmaker/spellCheck.cpp | 250 +++++++++++++++++++++++++++++++++----- 6 files changed, 458 insertions(+), 191 deletions(-) (limited to 'tools/bookmaker') diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index b3d3190b78..ac8f04da9f 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -7,7 +7,6 @@ #include "bookmaker.h" -#include "SkCommandLineFlags.h" #include "SkOSFile.h" #include "SkOSPath.h" @@ -790,12 +789,12 @@ bool RootDefinition::dumpUnVisited() { return allStructElementsFound; } -const Definition* RootDefinition::find(const string& ref) const { +const Definition* RootDefinition::find(const string& ref, AllowParens allowParens) const { const auto leafIter = fLeaves.find(ref); if (leafIter != fLeaves.end()) { return &leafIter->second; } - if (string::npos == ref.find("()")) { + if (AllowParens::kYes == allowParens && string::npos == ref.find("()")) { string withParens = ref + "()"; const auto parensIter = fLeaves.find(withParens); if (parensIter != fLeaves.end()) { @@ -810,7 +809,7 @@ const Definition* RootDefinition::find(const string& ref) const { const Definition* result = nullptr; for (const auto& branch : fBranches) { const RootDefinition* rootDef = branch.second; - result = rootDef->find(ref); + result = rootDef->find(ref, allowParens); if (result) { break; } @@ -866,7 +865,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy } definition = fParent; } else { - if (!hasEnd && fRoot->find(name)) { + if (!hasEnd && fRoot->find(name, RootDefinition::AllowParens::kNo)) { return this->reportError("duplicate symbol"); } if (MarkType::kStruct == markType || MarkType::kClass == markType) { @@ -990,7 +989,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy case MarkType::kDefinedBy: { string prefixed(fRoot->fName); const char* start = fChar; - string name(start, this->trimmedBracketEnd(fMC, OneLine::kYes) - start); + string name(start, this->trimmedBracketEnd(fMC) - start); prefixed += "::" + name; this->skipToEndBracket(fMC); const auto leafIter = fRoot->fLeaves.find(prefixed); @@ -1039,7 +1038,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy definition->fName = typeNameBuilder[0]; definition->fFiddle = fParent->fFiddle; definition->fContentStart = fChar; - definition->fContentEnd = this->trimmedBracketEnd(fMC, OneLine::kYes); + definition->fContentEnd = this->trimmedBracketEnd(fMC); this->skipToEndBracket(fMC); SkAssertResult(fMC == this->next()); SkAssertResult(fMC == this->next()); @@ -1079,6 +1078,9 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy fMarkup.emplace_front(markType, defStart, fLineCount, fParent); definition = &fMarkup.front(); definition->fContentStart = fChar; + if (MarkType::kFormula == markType && MarkType::kRow == definition->fParent->fMarkType) { + SkDebugf(""); + } definition->fName = typeNameBuilder[0]; definition->fFiddle = fParent->fFiddle; char suffix = '\0'; @@ -1127,7 +1129,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy definition->fName = typeNameBuilder[0]; definition->fFiddle = normalized_name(typeNameBuilder[0]); definition->fContentStart = fChar; - definition->fContentEnd = this->trimmedBracketEnd('\n', OneLine::kYes); + definition->fContentEnd = this->trimmedBracketEnd('\n'); definition->fTerminator = this->lineEnd() - 1; fParent->fChildren.push_back(definition); if (MarkType::kAnchor == markType) { @@ -1137,7 +1139,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy this->skipWhiteSpace(); Definition* link = &fMarkup.front(); link->fContentStart = fChar; - link->fContentEnd = this->trimmedBracketEnd(fMC, OneLine::kYes); + link->fContentEnd = this->trimmedBracketEnd(fMC); this->skipToEndBracket(fMC); SkAssertResult(fMC == this->next()); SkAssertResult(fMC == this->next()); @@ -1393,14 +1395,29 @@ int BmhParser::endHashCount() const { return count; } +bool BmhParser::endTableColumn(const char* end, const char* terminator) { + if (!this->popParentStack(fParent)) { + return false; + } + fWorkingColumn->fContentEnd = end; + fWorkingColumn->fTerminator = terminator; + fColStart = fChar - 1; + this->skipSpace(); + fTableState = TableState::kColumnStart; + return true; +} + // FIXME: some examples may produce different output on different platforms // if the text output can be different, think of how to author that bool BmhParser::findDefinitions() { bool lineStart = true; + const char* lastChar = nullptr; + const char* lastMC = nullptr; fParent = nullptr; while (!this->eof()) { if (this->peek() == fMC) { + lastMC = fChar; this->next(); if (this->peek() == fMC) { this->next(); @@ -1408,10 +1425,25 @@ bool BmhParser::findDefinitions() { return this->reportError("expected definition"); } if (this->peek() != fMC) { - vector parentName; - parentName.push_back(fParent->fName); - if (!this->addDefinition(fChar - 1, true, fParent->fMarkType, parentName)) { - return false; + if (MarkType::kColumn == fParent->fMarkType) { + SkASSERT(TableState::kColumnEnd == fTableState); + if (!this->endTableColumn(lastChar, lastMC)) { + return false; + } + SkASSERT(fRow); + if (!this->popParentStack(fParent)) { + return false; + } + fRow->fContentEnd = fWorkingColumn->fContentEnd; + fWorkingColumn = nullptr; + fRow = nullptr; + fTableState = TableState::kNone; + } else { + vector parentName; + parentName.push_back(fParent->fName); + if (!this->addDefinition(fChar - 1, true, fParent->fMarkType, parentName)) { + return false; + } } } else { SkAssertResult(this->next() == fMC); @@ -1462,15 +1494,22 @@ bool BmhParser::findDefinitions() { && MarkType::kLegend != fParent->fMarkType && MarkType::kList != fParent->fMarkType)) { int endHashes = this->endHashCount(); - if (endHashes <= 1) { // one line comment + if (endHashes <= 1) { if (fParent) { - fMarkup.emplace_front(MarkType::kComment, fChar - 1, fLineCount, fParent); - Definition* comment = &fMarkup.front(); - comment->fContentStart = fChar - 1; - this->skipToEndBracket('\n'); - comment->fContentEnd = fChar; - comment->fTerminator = fChar; - fParent->fChildren.push_back(comment); + if (TableState::kColumnEnd == fTableState) { + if (!this->endTableColumn(lastChar, lastMC)) { + return false; + } + } else { // one line comment + fMarkup.emplace_front(MarkType::kComment, fChar - 1, fLineCount, + fParent); + Definition* comment = &fMarkup.front(); + comment->fContentStart = fChar - 1; + this->skipToEndBracket('\n'); + comment->fContentEnd = fChar; + comment->fTerminator = fChar; + fParent->fChildren.push_back(comment); + } } else { fChar = fLine + this->lineLength() - 1; } @@ -1485,41 +1524,37 @@ bool BmhParser::findDefinitions() { return this->reportError("missing table"); } } - } else { + } else if (TableState::kNone == fTableState) { bool parentIsList = MarkType::kList == fParent->fMarkType; + if (parentIsList && fLineCount > 1230) { + SkDebugf(""); + } // fixme? no nested tables for now - const char* colStart = fChar - 1; - fMarkup.emplace_front(MarkType::kRow, colStart, fLineCount, fParent); - Definition* row = &fMarkup.front(); + fColStart = fChar - 1; + fMarkup.emplace_front(MarkType::kRow, fColStart, fLineCount, fParent); + fRow = &fMarkup.front(); + fRow->fName = fParent->fName; this->skipWhiteSpace(); - row->fContentStart = fChar; - this->setAsParent(row); - const char* lineEnd = this->lineEnd(); - do { - fMarkup.emplace_front(MarkType::kColumn, colStart, fLineCount, fParent); - Definition* column = &fMarkup.front(); - column->fContentStart = fChar; - column->fContentEnd = this->trimmedBracketEnd(fMC, - parentIsList ? OneLine::kNo : OneLine::kYes); - this->skipToEndBracket(fMC); - colStart = fChar; - SkAssertResult(fMC == this->next()); - if (fMC == this->peek()) { - this->next(); - } - column->fTerminator = fChar; - fParent->fChildren.push_back(column); - this->skipSpace(); - } while (fChar < lineEnd && '\n' != this->peek()); - if (!this->popParentStack(fParent)) { - return false; - } - const Definition* lastCol = row->fChildren.back(); - row->fContentEnd = lastCol->fContentEnd; + fRow->fContentStart = fChar; + this->setAsParent(fRow); + fTableState = TableState::kColumnStart; + } + if (TableState::kColumnStart == fTableState) { + fMarkup.emplace_front(MarkType::kColumn, fColStart, fLineCount, fParent); + fWorkingColumn = &fMarkup.front(); + fWorkingColumn->fName = fParent->fName; + fWorkingColumn->fContentStart = fChar; + this->setAsParent(fWorkingColumn); + fTableState = TableState::kColumnEnd; + continue; } } } - lineStart = this->next() == '\n'; + char nextChar = this->next(); + lineStart = nextChar == '\n'; + if (' ' < nextChar) { + lastChar = fChar; + } } if (fParent) { return this->reportError("mismatched end"); @@ -2115,7 +2150,7 @@ DEFINE_string2(include, i, "", "A path to a *.h file or a directory."); DEFINE_bool2(hack, k, false, "Do a find/replace hack to update all *.bmh files. (Requires -b)"); DEFINE_bool2(populate, p, false, "Populate include from bmh. (Requires -b -i)"); DEFINE_string2(ref, r, "", "Resolve refs and write bmh_*.md files to path. (Requires -b)"); -DEFINE_bool2(spellcheck, s, false, "Spell-check. (Requires -b)"); +DEFINE_string2(spellcheck, s, "", "Spell-check [once, all, mispellings]. (Requires -b)"); DEFINE_bool2(tokens, t, false, "Output include tokens. (Requires -i)"); DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)"); @@ -2198,7 +2233,7 @@ int main(int argc, char** const argv) { SkCommandLineFlags::PrintUsage(); return 1; } - if (FLAGS_bmh.isEmpty() && FLAGS_spellcheck) { + if (FLAGS_bmh.isEmpty() && !FLAGS_spellcheck.isEmpty()) { SkDebugf("-s requires -b\n"); SkCommandLineFlags::PrintUsage(); return 1; @@ -2257,8 +2292,8 @@ int main(int argc, char** const argv) { MdOut mdOut(bmhParser); mdOut.buildReferences(FLAGS_bmh[0], FLAGS_ref[0]); } - if (!done && FLAGS_spellcheck && FLAGS_examples.isEmpty()) { - bmhParser.spellCheck(FLAGS_bmh[0]); + if (!done && !FLAGS_spellcheck.isEmpty() && FLAGS_examples.isEmpty()) { + bmhParser.spellCheck(FLAGS_bmh[0], FLAGS_spellcheck); done = true; } int examples = 0; diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index 71ff0d5dd6..503db20f24 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -10,6 +10,7 @@ #define STDOUT_TO_IDE_OUT 0 +#include "SkCommandLineFlags.h" #include "SkData.h" #include @@ -205,11 +206,6 @@ class TextParser : public NonAssignable { TextParser() {} // only for ParserCommon to call friend class ParserCommon; public: - enum OneLine { - kNo, - kYes - }; - class Save { public: Save(TextParser* parser) { @@ -435,7 +431,7 @@ public: void skipToNonAlphaNum() { while (fChar < fEnd && (isalnum(fChar[0]) || '_' == fChar[0] || '-' == fChar[0] - || (':' == fChar[0] && fChar +1 < fEnd && ':' == fChar[1]) + || (':' == fChar[0] && fChar + 1 < fEnd && ':' == fChar[1]) || ('.' == fChar[0] && fChar + 1 < fEnd && isalpha(fChar[1])))) { if (':' == fChar[0] && fChar +1 < fEnd && ':' == fChar[1]) { fChar++; @@ -452,7 +448,7 @@ public: bool skipName(const char* word) { size_t len = strlen(word); - if (len < (size_t) (fEnd - fChar) && !strncmp(word, fChar, len)) { + if (len <= (size_t) (fEnd - fChar) && !strncmp(word, fChar, len)) { fChar += len; } return this->eof() || ' ' >= fChar[0]; @@ -495,7 +491,7 @@ public: bool startsWith(const char* str) const { size_t len = strlen(str); - ptrdiff_t lineLen = this->lineLength(); + ptrdiff_t lineLen = fEnd - fChar; return len <= (size_t) lineLen && 0 == strncmp(str, fChar, len); } @@ -556,8 +552,8 @@ public: return nullptr; } - const char* trimmedBracketEnd(const char bracket, OneLine oneLine) const { - int max = (int) (OneLine::kYes == oneLine ? this->lineLength() : fEnd - fChar); + const char* trimmedBracketEnd(const char bracket) const { + int max = (int) (this->lineLength()); int index = 0; while (index < max && bracket != fChar[index]) { ++index; @@ -899,6 +895,11 @@ public: class RootDefinition : public Definition { public: + enum class AllowParens { + kNo, + kYes, + }; + RootDefinition() { } @@ -920,7 +921,7 @@ public: const RootDefinition* asRoot() const override { return this; } void clearVisited(); bool dumpUnVisited(); - const Definition* find(const string& ref) const; + const Definition* find(const string& ref, AllowParens ) const; bool isRoot() const override { return true; } RootDefinition* rootParent() override { return fRootParent; } void setRootParent(RootDefinition* rootParent) { fRootParent = rootParent; } @@ -1108,6 +1109,9 @@ public: } void writeString(const char* str) { + if (!strcmp("utf-8", str)) { + SkDebugf(""); + } SkASSERT(strlen(str) > 0); SkASSERT(' ' < str[0]); SkASSERT(' ' < str[strlen(str) - 1]); @@ -1194,6 +1198,12 @@ public: kOptional, }; + enum class TableState { + kNone, + kColumnStart, + kColumnEnd, + }; + #define M(mt) (1LL << (int) MarkType::k##mt) #define M_D M(Description) #define M_CS M(Class) | M(Struct) @@ -1216,60 +1226,61 @@ public: , fMaps { // names without formal definitions (e.g. Column) aren't included // fill in other names once they're actually used - { "", nullptr, MarkType::kNone, R_Y, E_N, 0 } -, { "A", nullptr, MarkType::kAnchor, R_Y, E_N, 0 } -, { "Alias", nullptr, MarkType::kAlias, R_N, E_N, 0 } -, { "Bug", nullptr, MarkType::kBug, R_N, E_N, 0 } -, { "Class", &fClassMap, MarkType::kClass, R_Y, E_O, M_CSST | M(Root) } -, { "Code", nullptr, MarkType::kCode, R_Y, E_N, M_CSST | M_E } -, { "", nullptr, MarkType::kColumn, R_Y, E_N, M(Row) } -, { "", nullptr, MarkType::kComment, R_N, E_N, 0 } -, { "Const", &fConstMap, MarkType::kConst, R_Y, E_N, M_E | M_ST } -, { "Define", nullptr, MarkType::kDefine, R_O, E_N, M_ST } -, { "DefinedBy", nullptr, MarkType::kDefinedBy, R_N, E_N, M(Method) } -, { "Deprecated", nullptr, MarkType::kDeprecated, R_Y, E_N, 0 } -, { "Description", nullptr, MarkType::kDescription, R_Y, E_N, M(Example) } -, { "Doxygen", nullptr, MarkType::kDoxygen, R_Y, E_N, 0 } -, { "Enum", &fEnumMap, MarkType::kEnum, R_Y, E_O, M_CSST | M(Root) } -, { "EnumClass", &fClassMap, MarkType::kEnumClass, R_Y, E_O, M_CSST | M(Root) } -, { "Error", nullptr, MarkType::kError, R_N, E_N, M(Example) } -, { "Example", nullptr, MarkType::kExample, R_O, E_N, M_CSST | M_E | M(Method) } + { "", nullptr, MarkType::kNone, R_Y, E_N, 0 } +, { "A", nullptr, MarkType::kAnchor, R_Y, E_N, 0 } +, { "Alias", nullptr, MarkType::kAlias, R_N, E_N, 0 } +, { "Bug", nullptr, MarkType::kBug, R_N, E_N, 0 } +, { "Class", &fClassMap, MarkType::kClass, R_Y, E_O, M_CSST | M(Root) } +, { "Code", nullptr, MarkType::kCode, R_Y, E_N, M_CSST | M_E } +, { "", nullptr, MarkType::kColumn, R_Y, E_N, M(Row) } +, { "", nullptr, MarkType::kComment, R_N, E_N, 0 } +, { "Const", &fConstMap, MarkType::kConst, R_Y, E_N, M_E | M_ST } +, { "Define", nullptr, MarkType::kDefine, R_O, E_N, M_ST } +, { "DefinedBy", nullptr, MarkType::kDefinedBy, R_N, E_N, M(Method) } +, { "Deprecated", nullptr, MarkType::kDeprecated, R_Y, E_N, 0 } +, { "Description", nullptr, MarkType::kDescription, R_Y, E_N, M(Example) } +, { "Doxygen", nullptr, MarkType::kDoxygen, R_Y, E_N, 0 } +, { "Enum", &fEnumMap, MarkType::kEnum, R_Y, E_O, M_CSST | M(Root) } +, { "EnumClass", &fClassMap, MarkType::kEnumClass, R_Y, E_O, M_CSST | M(Root) } +, { "Error", nullptr, MarkType::kError, R_N, E_N, M(Example) } +, { "Example", nullptr, MarkType::kExample, R_O, E_N, M_CSST | M_E | M(Method) } , { "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, M_ST | M(Member) | M(Method) | M_D } -, { "Function", nullptr, MarkType::kFunction, R_O, E_N, M(Example) } -, { "Height", nullptr, MarkType::kHeight, R_N, E_N, M(Example) } -, { "Image", nullptr, MarkType::kImage, R_N, E_N, M(Example) } -, { "Legend", nullptr, MarkType::kLegend, R_Y, E_N, M(Table) } -, { "", nullptr, MarkType::kLink, R_Y, E_N, M(Anchor) } -, { "List", nullptr, MarkType::kList, R_Y, E_N, M(Method) | M_CSST | M_E | M_D } -, { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 } -, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M(Class) | M(Struct) } -, { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST } -, { "NoExample", nullptr, MarkType::kNoExample, R_Y, E_N, 0 } -, { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) } -, { "Platform", nullptr, MarkType::kPlatform, R_Y, E_N, M(Example) } -, { "Private", nullptr, MarkType::kPrivate, R_N, E_N, 0 } -, { "Return", nullptr, MarkType::kReturn, R_Y, E_N, M(Method) } -, { "", nullptr, MarkType::kRoot, R_Y, E_N, 0 } -, { "", nullptr, MarkType::kRow, R_Y, E_N, M(Table) | M(List) } -, { "SeeAlso", nullptr, MarkType::kSeeAlso, R_Y, E_N, M_CSST | M_E | M(Method) } -, { "StdOut", nullptr, MarkType::kStdOut, R_N, E_N, M(Example) } -, { "Struct", &fClassMap, MarkType::kStruct, R_Y, E_O, M(Class) | M(Root) | M_ST } -, { "Substitute", nullptr, MarkType::kSubstitute, R_N, E_N, M_ST } -, { "Subtopic", nullptr, MarkType::kSubtopic, R_Y, E_Y, M_CSST } -, { "Table", nullptr, MarkType::kTable, R_Y, E_N, M(Method) | M_CSST | M_E } -, { "Template", nullptr, MarkType::kTemplate, R_Y, E_N, 0 } -, { "", nullptr, MarkType::kText, R_Y, E_N, 0 } -, { "Time", nullptr, MarkType::kTime, R_Y, E_N, M(Track) } -, { "ToDo", nullptr, MarkType::kToDo, R_N, E_N, 0 } -, { "Topic", nullptr, MarkType::kTopic, R_Y, E_Y, M_CS | M(Root) | M(Topic) } -, { "Track", nullptr, MarkType::kTrack, R_Y, E_N, M_E | M_ST } -, { "Typedef", &fTypedefMap, MarkType::kTypedef, R_Y, E_N, M(Subtopic) | M(Topic) } -, { "", nullptr, MarkType::kUnion, R_Y, E_N, 0 } -, { "Volatile", nullptr, MarkType::kVolatile, R_N, E_N, M(StdOut) } -, { "Width", nullptr, MarkType::kWidth, R_N, E_N, M(Example) } } +, { "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, + M(Column) | M_ST | M(Member) | M(Method) | M_D } +, { "Function", nullptr, MarkType::kFunction, R_O, E_N, M(Example) } +, { "Height", nullptr, MarkType::kHeight, R_N, E_N, M(Example) } +, { "Image", nullptr, MarkType::kImage, R_N, E_N, M(Example) } +, { "Legend", nullptr, MarkType::kLegend, R_Y, E_N, M(Table) } +, { "", nullptr, MarkType::kLink, R_N, E_N, M(Anchor) } +, { "List", nullptr, MarkType::kList, R_Y, E_N, M(Method) | M_CSST | M_E | M_D } +, { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 } +, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M(Class) | M(Struct) } +, { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST } +, { "NoExample", nullptr, MarkType::kNoExample, R_Y, E_N, 0 } +, { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) } +, { "Platform", nullptr, MarkType::kPlatform, R_N, E_N, M(Example) } +, { "Private", nullptr, MarkType::kPrivate, R_N, E_N, 0 } +, { "Return", nullptr, MarkType::kReturn, R_Y, E_N, M(Method) } +, { "", nullptr, MarkType::kRoot, R_Y, E_N, 0 } +, { "", nullptr, MarkType::kRow, R_Y, E_N, M(Table) | M(List) } +, { "SeeAlso", nullptr, MarkType::kSeeAlso, R_Y, E_N, M_CSST | M_E | M(Method) } +, { "StdOut", nullptr, MarkType::kStdOut, R_N, E_N, M(Example) } +, { "Struct", &fClassMap, MarkType::kStruct, R_Y, E_O, M(Class) | M(Root) | M_ST } +, { "Substitute", nullptr, MarkType::kSubstitute, R_N, E_N, M_ST } +, { "Subtopic", nullptr, MarkType::kSubtopic, R_Y, E_Y, M_CSST } +, { "Table", nullptr, MarkType::kTable, R_Y, E_N, M(Method) | M_CSST | M_E } +, { "Template", nullptr, MarkType::kTemplate, R_Y, E_N, 0 } +, { "", nullptr, MarkType::kText, R_Y, E_N, 0 } +, { "Time", nullptr, MarkType::kTime, R_Y, E_N, M(Track) } +, { "ToDo", nullptr, MarkType::kToDo, R_N, E_N, 0 } +, { "Topic", nullptr, MarkType::kTopic, R_Y, E_Y, M_CS | M(Root) | M(Topic) } +, { "Track", nullptr, MarkType::kTrack, R_Y, E_N, M_E | M_ST } +, { "Typedef", &fTypedefMap, MarkType::kTypedef, R_Y, E_N, M(Subtopic) | M(Topic) } +, { "", nullptr, MarkType::kUnion, R_Y, E_N, 0 } +, { "Volatile", nullptr, MarkType::kVolatile, R_N, E_N, M(StdOut) } +, { "Width", nullptr, MarkType::kWidth, R_N, E_N, M(Example) } } { this->reset(); } @@ -1296,6 +1307,7 @@ public: string className(MarkType markType); bool collectExternals(); int endHashCount() const; + bool endTableColumn(const char* end, const char* terminator); RootDefinition* findBmhObject(MarkType markType, const string& typeName) { auto map = fMaps[(int) markType].fBmh; @@ -1326,6 +1338,9 @@ public: void reset() override { INHERITED::resetCommon(); fRoot = nullptr; + fWorkingColumn = nullptr; + fRow = nullptr; + fTableState = TableState::kNone; fMC = '#'; fInChar = false; fInCharCommentString = false; @@ -1337,7 +1352,7 @@ public: bool skipNoName(); bool skipToDefinitionEnd(MarkType markType); - void spellCheck(const char* match) const; + void spellCheck(const char* match, SkCommandLineFlags::StringArray report) const; vector topicName(); vector typeName(MarkType markType, bool* expectEnd); string uniqueName(const string& base, MarkType markType); @@ -1368,6 +1383,10 @@ public: unordered_map fTopicMap; unordered_map fAliasMap; RootDefinition* fRoot; + Definition* fWorkingColumn; + Definition* fRow; + const char* fColStart; + TableState fTableState; mutable char fMC; // markup character bool fAnonymous; bool fCloned; @@ -1639,6 +1658,12 @@ public: kSpace, }; + enum class RefType { + kUndefined, + kNormal, + kExternal, + }; + enum class Wrote { kNone, kLF, @@ -1699,7 +1724,7 @@ public: } string resolveMethod(const char* start, const char* end, bool first); - string resolveRef(const char* start, const char* end, bool first); + string resolveRef(const char* start, const char* end, bool first, RefType* refType); Wrote rewriteBlock(int size, const char* data); Definition* structMemberOut(const Definition* memberStart, const Definition& child); void structOut(const Definition* root, const Definition& child, diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp index 21a47d6e8a..cc7627ac7c 100644 --- a/tools/bookmaker/includeParser.cpp +++ b/tools/bookmaker/includeParser.cpp @@ -231,7 +231,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { continue; } string fullName = classMapper.first + "::" + token.fName; - const Definition* def = root->find(fullName); + const Definition* def = root->find(fullName, RootDefinition::AllowParens::kYes); switch (token.fMarkType) { case MarkType::kMethod: { if (this->internalName(token)) { @@ -241,7 +241,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { string paramName = className + "::"; paramName += string(token.fContentStart, token.fContentEnd - token.fContentStart); - def = root->find(paramName); + def = root->find(paramName, RootDefinition::AllowParens::kYes); if (!def && 0 == token.fName.find("operator")) { string operatorName = className + "::"; TextParser oper("", token.fStart, token.fContentEnd, 0); @@ -258,7 +258,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { } } while (!oper.eof() && oper.next() && parens > 0); operatorName += string(start, oper.fChar - start); - def = root->find(operatorName); + def = root->find(operatorName, RootDefinition::AllowParens::kYes); } } if (!def) { @@ -267,17 +267,18 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { string constructorName = className + "::"; constructorName += string(token.fContentStart + skip, token.fContentEnd - token.fContentStart - skip); - def = root->find(constructorName); + def = root->find(constructorName, RootDefinition::AllowParens::kYes); } if (!def && 0 == token.fName.find("SK_")) { string incName = token.fName + "()"; string macroName = className + "::" + incName; - def = root->find(macroName); + def = root->find(macroName, RootDefinition::AllowParens::kYes); if (def) { if (def->fName == incName) { def->fVisited = true; if ("SK_TO_STRING_NONVIRT" == token.fName) { - def = root->find(className + "::toString"); + def = root->find(className + "::toString", + RootDefinition::AllowParens::kYes); if (def) { def->fVisited = true; } else { @@ -300,7 +301,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { } if (allLower) { string lowerName = className + "::" + token.fName + "()"; - def = root->find(lowerName); + def = root->find(lowerName, RootDefinition::AllowParens::kYes); } } if (!def) { @@ -314,7 +315,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { if (!def) { // simple method names inside nested classes have a bug and are missing trailing parens string withParens = fullName + "()"; // FIXME: this shouldn't be necessary - def = root->find(withParens); + def = root->find(withParens, RootDefinition::AllowParens::kNo); } if (!def) { SkDebugf("method missing from bmh: %s\n", fullName.c_str()); @@ -359,7 +360,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { ++lastUnderscore; string anonName = className + "::" + string(lastUnderscore, wordEnd - lastUnderscore) + 's'; - def = root->find(anonName); + def = root->find(anonName, RootDefinition::AllowParens::kYes); } if (!def) { SkDebugf("enum missing from bmh: %s\n", fullName.c_str()); @@ -386,10 +387,10 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { string constName = MarkType::kEnumClass == token.fMarkType ? fullName : className; constName += "::" + child->fName; - def = root->find(constName); + def = root->find(constName, RootDefinition::AllowParens::kYes); if (!def) { string innerName = classMapper.first + "::" + child->fName; - def = root->find(innerName); + def = root->find(innerName, RootDefinition::AllowParens::kYes); } if (!def) { if (string::npos == child->fName.find("Legacy_")) { @@ -1142,7 +1143,7 @@ bool IncludeParser::parseMember(Definition* child, Definition* markupDef) { break; } const char* start = parser.fChar; - const char* end = parser.trimmedBracketEnd('\n', OneLine::kYes); + const char* end = parser.trimmedBracketEnd('\n'); if (Bracket::kSlashStar == comment->fBracket) { const char* commentEnd = parser.strnstr("*/", end); if (commentEnd) { @@ -1450,6 +1451,7 @@ bool IncludeParser::parseChar() { return reportError("malformed closing comment"); } if (Bracket::kSlashStar == this->topBracket()) { + this->next(); // include close in bracket -- FIXME? will this skip stuff? this->popBracket(); } break; diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index af2fb89fb8..78b0364b06 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -33,9 +33,9 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root, child.fChildren[0]->fName = enumName; } fullName = root->fName + "::" + enumName; - enumDef = root->find(enumName); + enumDef = root->find(enumName, RootDefinition::AllowParens::kNo); if (!enumDef) { - enumDef = root->find(fullName); + enumDef = root->find(fullName, RootDefinition::AllowParens::kNo); } SkASSERT(enumDef); // child[0] should be #Code comment starts at child[0].fTerminator @@ -48,7 +48,7 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root, if (fAnonymousEnumCount > 1) { enumName += '_' + to_string(fAnonymousEnumCount); } - enumDef = root->find(enumName); + enumDef = root->find(enumName, RootDefinition::AllowParens::kNo); SkASSERT(enumDef); ++fAnonymousEnumCount; } @@ -794,7 +794,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti } ++alternate; string alternateMethod = methodName + '_' + to_string(alternate); - clonedMethod = root->find(alternateMethod); + clonedMethod = root->find(alternateMethod, RootDefinition::AllowParens::kNo); } while (clonedMethod); if (!clonedMethod) { return this->reportError("cloned method not found"); @@ -823,7 +823,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti --continueEnd; } methodName += string(fContinuation, continueEnd - fContinuation); - method = root->find(methodName); + method = root->find(methodName, RootDefinition::AllowParens::kNo); if (!method) { fLineCount = child.fLineCount; fclose(fOut); // so we can see what we've written so far @@ -836,7 +836,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti continue; } methodName += "()"; - method = root->find(methodName); + method = root->find(methodName, RootDefinition::AllowParens::kNo); if (method && MarkType::kDefinedBy == method->fMarkType) { method = method->fParent; } @@ -873,7 +873,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti methodName = root->fName + "::" + child.fName; inConstructor = root->fName == child.fName; fContinuation = child.fContentEnd; - method = root->find(methodName); + method = root->find(methodName, RootDefinition::AllowParens::kNo); if (!method) { continue; } @@ -905,9 +905,10 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti } if (fInStruct) { fIndent += 4; - fStructDef = root->find(child.fName); + fStructDef = root->find(child.fName, RootDefinition::AllowParens::kNo); if (nullptr == structDef) { - fStructDef = root->find(root->fName + "::" + child.fName); + fStructDef = root->find(root->fName + "::" + child.fName, + RootDefinition::AllowParens::kNo); } this->structSizeMembers(child); fIndent -= 4; @@ -937,9 +938,10 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti SkASSERT(0); // incomplete } } else { - structDef = root->find(child.fName); + structDef = root->find(child.fName, RootDefinition::AllowParens::kNo); if (nullptr == structDef) { - structDef = root->find(root->fName + "::" + child.fName); + structDef = root->find(root->fName + "::" + child.fName, + RootDefinition::AllowParens::kNo); } if (!structDef) { this->lf(2); @@ -1162,7 +1164,8 @@ string IncludeWriter::resolveMethod(const char* start, const char* end, bool fir } } SkASSERT(parent); - auto defRef = parent->find(parent->fName + "::" + methodname); + auto defRef = parent->find(parent->fName + "::" + methodname, + RootDefinition::AllowParens::kNo); if (defRef && MarkType::kMethod == defRef->fMarkType) { substitute = methodname + "()"; } @@ -1175,9 +1178,17 @@ string IncludeWriter::resolveMethod(const char* start, const char* end, bool fir return substitute; } -string IncludeWriter::resolveRef(const char* start, const char* end, bool first) { +string IncludeWriter::resolveRef(const char* start, const char* end, bool first, + RefType* refType) { // look up Xxx_Xxx string undername(start, end - start); + for (const auto& external : fBmhParser->fExternals) { + if (external.fName == undername) { + *refType = RefType::kExternal; + return external.fName; + } + } + *refType = RefType::kNormal; SkASSERT(string::npos == undername.find(' ')); const Definition* rootDef = nullptr; { @@ -1200,11 +1211,6 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first) if (fBmhParser->fAliasMap.end() != aliasIter) { rootDef = aliasIter->second->fParent; } else if (!first) { - for (const auto& external : fBmhParser->fExternals) { - if (external.fName == undername) { - return external.fName; - } - } SkDebugf("unfound: %s\n", undername.c_str()); this->reportError("reference unfound"); return ""; @@ -1291,11 +1297,12 @@ int IncludeWriter::lookupReference(const PunctuationState punctuation, const Wor const int start, const int run, int lastWrite, const char last, const char* data) { const int end = PunctuationState::kDelimiter == punctuation || PunctuationState::kPeriod == punctuation ? run - 1 : run; - string temp = this->resolveRef(&data[start], &data[end], Word::kFirst == word); + RefType refType = RefType::kUndefined; + string resolved = string(&data[start], (size_t) (end - start)); + string temp = this->resolveRef(&data[start], &data[end], Word::kFirst == word, &refType); if (!temp.length()) { if (Word::kFirst != word && '_' != last) { - temp = string(&data[start], (size_t) (end - start)); - temp = ConvertRef(temp, false); + temp = ConvertRef(resolved, false); } } if (temp.length()) { @@ -1439,6 +1446,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data) { embeddedSymbol = true; break; case '\'': // possessive apostrophe isn't treated as delimiting punctation + case '\"': // quote is passed straight through case '=': case '!': // assumed not to be punctuation, but a programming symbol case '&': case '>': case '<': case '{': case '}': case '/': case '*': case '[': case ']': diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp index 3718151e76..0a53fc4147 100644 --- a/tools/bookmaker/mdOut.cpp +++ b/tools/bookmaker/mdOut.cpp @@ -184,7 +184,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, for (string prefix : { "_", "::" } ) { RootDefinition* root = test->asRoot(); string prefixed = root->fName + prefix + ref; - if (const Definition* def = root->find(prefixed)) { + if (const Definition* def = root->find(prefixed, + RootDefinition::AllowParens::kYes)) { result += linkRef(leadingSpaces, def, ref); goto found; } @@ -363,7 +364,7 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, if (ref == fRoot->fName) { return fRoot; } - if (const Definition* definition = fRoot->find(ref)) { + if (const Definition* definition = fRoot->find(ref, RootDefinition::AllowParens::kYes)) { return definition; } Definition* test = fRoot; @@ -376,14 +377,16 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, if (ref == leaf.first) { return leaf.second; } - const Definition* definition = leaf.second->find(ref); + const Definition* definition = leaf.second->find(ref, + RootDefinition::AllowParens::kYes); if (definition) { return definition; } } for (string prefix : { "::", "_" } ) { string prefixed = root->fName + prefix + ref; - if (const Definition* definition = root->find(prefixed)) { + if (const Definition* definition = root->find(prefixed, + RootDefinition::AllowParens::kYes)) { return definition; } if (isupper(prefixed[0])) { @@ -401,7 +404,7 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, auto classIter = fBmhParser.fClassMap.find(className); if (classIter != fBmhParser.fClassMap.end()) { const RootDefinition& classDef = classIter->second; - const Definition* result = classDef.find(ref); + const Definition* result = classDef.find(ref, RootDefinition::AllowParens::kYes); if (result) { return result; } @@ -414,7 +417,7 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, // try with a prefix if ('k' == ref[0]) { for (auto const& iter : fBmhParser.fEnumMap) { - if (iter.second.find(ref)) { + if (iter.second.find(ref, RootDefinition::AllowParens::kYes)) { return &iter.second; } } @@ -456,13 +459,15 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, string className(ref, 0, pos); auto classIter = fBmhParser.fClassMap.find(className); if (classIter != fBmhParser.fClassMap.end()) { - if (const Definition* definition = classIter->second.find(ref)) { + if (const Definition* definition = classIter->second.find(ref, + RootDefinition::AllowParens::kYes)) { return definition; } } auto enumIter = fBmhParser.fEnumMap.find(className); if (enumIter != fBmhParser.fEnumMap.end()) { - if (const Definition* definition = enumIter->second.find(ref)) { + if (const Definition* definition = enumIter->second.find(ref, + RootDefinition::AllowParens::kYes)) { return definition; } } @@ -682,7 +687,7 @@ void MdOut::markTypeOut(Definition* def) { TextParser tp(def->fFileName, def->fStart, def->fContentStart, def->fLineCount); tp.skipExact("#Member"); tp.skipWhiteSpace(); - const char* end = tp.trimmedBracketEnd('\n', TextParser::OneLine::kYes); + const char* end = tp.trimmedBracketEnd('\n'); this->lfAlways(2); fprintf(fOut, " %.*s ", def->fFiddle.c_str(), (int) (end - tp.fChar), tp.fChar); diff --git a/tools/bookmaker/spellCheck.cpp b/tools/bookmaker/spellCheck.cpp index e43a412eed..06a5d2be70 100644 --- a/tools/bookmaker/spellCheck.cpp +++ b/tools/bookmaker/spellCheck.cpp @@ -34,7 +34,7 @@ public: this->reset(); } bool check(const char* match); - void report(); + void report(SkCommandLineFlags::StringArray report); private: enum class TableState { kNone, @@ -56,6 +56,7 @@ private: fTableState = TableState::kNone; fInCode = false; fInConst = false; + fInFormula = false; fInDescription = false; fInStdOut = false; } @@ -77,6 +78,7 @@ private: bool fInCode; bool fInConst; bool fInDescription; + bool fInFormula; bool fInStdOut; typedef ParserCommon INHERITED; }; @@ -88,10 +90,10 @@ private: modifiers to try to maintain a consistent voice. Maybe also look for passive verbs (e.g. 'is') and suggest active ones? */ -void BmhParser::spellCheck(const char* match) const { +void BmhParser::spellCheck(const char* match, SkCommandLineFlags::StringArray report) const { SpellCheck checker(*this); checker.check(match); - checker.report(); + checker.report(report); } bool SpellCheck::check(const char* match) { @@ -112,13 +114,22 @@ bool SpellCheck::check(const char* match) { return true; } +static bool all_lower(const string& str) { + for (auto c : str) { + if (!islower(c)) { + return false; + } + } + return true; +} + bool SpellCheck::check(Definition* def) { fFileName = def->fFileName; fLineCount = def->fLineCount; string printable = def->printableName(); const char* textStart = def->fContentStart; if (MarkType::kParam != def->fMarkType && MarkType::kConst != def->fMarkType && - TableState::kNone != fTableState) { + MarkType::kPrivate != def->fMarkType && TableState::kNone != fTableState) { fTableState = TableState::kNone; } switch (def->fMarkType) { @@ -170,11 +181,14 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kExample: break; + case MarkType::kExperimental: + break; case MarkType::kExternal: break; case MarkType::kFile: break; case MarkType::kFormula: + fInFormula = true; break; case MarkType::kFunction: break; @@ -184,12 +198,19 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kLegend: break; + case MarkType::kLink: + break; case MarkType::kList: break; + case MarkType::kMarkChar: + break; case MarkType::kMember: break; case MarkType::kMethod: { string method_name = def->methodName(); + if (all_lower(method_name)) { + method_name += "()"; + } string formattedStr = def->formatFunction(); if (!def->isClone()) { this->wordCheck(method_name); @@ -197,6 +218,8 @@ bool SpellCheck::check(Definition* def) { fTableState = TableState::kNone; fMethod = def; } break; + case MarkType::kNoExample: + break; case MarkType::kParam: { if (TableState::kNone == fTableState) { fTableState = TableState::kRow; @@ -219,6 +242,8 @@ bool SpellCheck::check(Definition* def) { } break; case MarkType::kPlatform: break; + case MarkType::kPrivate: + break; case MarkType::kReturn: break; case MarkType::kRow: @@ -240,6 +265,8 @@ bool SpellCheck::check(Definition* def) { fRoot = def->asRoot(); this->wordCheck(def->fName); break; + case MarkType::kSubstitute: + break; case MarkType::kSubtopic: this->printCheck(printable); break; @@ -263,6 +290,8 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kUnion: break; + case MarkType::kVolatile: + break; case MarkType::kWidth: break; default: @@ -284,6 +313,9 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kExample: break; + case MarkType::kFormula: + fInFormula = false; + break; case MarkType::kLegend: break; case MarkType::kMethod: @@ -336,21 +368,90 @@ void SpellCheck::childCheck(const Definition* def, const char* start) { } void SpellCheck::leafCheck(const char* start, const char* end) { - TextParser text("", start, end, fLineCount); + const char* chPtr = start; + int inAngles = 0; + int inParens = 0; + bool inQuotes = false; + bool allLower = true; + char priorCh = 0; + char lastCh = 0; + const char* wordStart = nullptr; + const char* wordEnd = nullptr; + const char* possibleEnd = nullptr; do { - const char* lineStart = text.fChar; - text.skipToAlpha(); - if (text.eof()) { + if (wordStart && wordEnd) { + if (!allLower || (!inQuotes && '\"' != lastCh && !inParens + && ')' != lastCh && !inAngles && '>' != lastCh)) { + string word(wordStart, (possibleEnd ? possibleEnd : wordEnd) - wordStart); + wordCheck(word); + } + wordStart = nullptr; + } + if (chPtr == end) { break; } - const char* wordStart = text.fChar; - text.fChar = lineStart; - text.skipTo(wordStart); // advances line number - text.skipToNonAlphaNum(); - fLineCount = text.fLineCount; - string word(wordStart, text.fChar - wordStart); - wordCheck(word); - } while (!text.eof()); + switch (*chPtr) { + case '>': + if (isalpha(lastCh)) { + --inAngles; + SkASSERT(inAngles >= 0); + } + wordEnd = chPtr; + break; + case '(': + ++inParens; + possibleEnd = chPtr; + break; + case ')': + --inParens; + if ('(' == lastCh) { + wordEnd = chPtr + 1; + } else { + wordEnd = chPtr; + } + SkASSERT(inParens >= 0); + break; + case '\"': + inQuotes = !inQuotes; + wordEnd = chPtr; + SkASSERT(inQuotes == !wordStart); + break; + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + allLower = false; + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + if (!wordStart) { + wordStart = chPtr; + wordEnd = nullptr; + possibleEnd = nullptr; + allLower = 'a' <= *chPtr; + if ('<' == lastCh || ('<' == priorCh && '/' == lastCh)) { + ++inAngles; + } + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '_': + allLower = false; + case '-': // note that dash doesn't clear allLower + break; + default: + wordEnd = chPtr; + break; + } + priorCh = lastCh; + lastCh = *chPtr; + } while (++chPtr <= end); } void SpellCheck::printCheck(const string& str) { @@ -360,25 +461,107 @@ void SpellCheck::printCheck(const string& str) { } } -void SpellCheck::report() { - for (auto iter : fWords) { - if (string::npos != iter.second.fFile.find("undocumented.bmh")) { - continue; - } - if (string::npos != iter.second.fFile.find("markup.bmh")) { - continue; +static bool stringCompare(const std::pair& i, const std::pair& j) { + return i.first.compare(j.first) < 0; +} + +void SpellCheck::report(SkCommandLineFlags::StringArray report) { + vector> elems(fWords.begin(), fWords.end()); + std::sort(elems.begin(), elems.end(), stringCompare); + if (report.contains("once")) { + for (auto iter : elems) { + if (string::npos != iter.second.fFile.find("undocumented.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("markup.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("usingBookmaker.bmh")) { + continue; + } + if (iter.second.fCount == 1) { + SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine, + iter.first.c_str()); + } } - if (string::npos != iter.second.fFile.find("usingBookmaker.bmh")) { - continue; + SkDebugf("\n"); + } + if (report.contains("all")) { + int column = 0; + for (auto iter : elems) { + if (string::npos != iter.second.fFile.find("undocumented.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("markup.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("usingBookmaker.bmh")) { + continue; + } + string check = iter.first.c_str(); + bool allLower = true; + for (auto c : check) { + if (isupper(c)) { + allLower = false; + break; + } + } + if (!allLower) { + continue; + } + if (column + check.length() > 100) { + SkDebugf("\n"); + column = 0; + } + SkDebugf("%s ", check.c_str()); + column += check.length(); } - if (iter.second.fCount == 1) { - SkDebugf("%s %s %d\n", iter.first.c_str(), iter.second.fFile.c_str(), - iter.second.fLine); + SkDebugf("\n\n"); + } + if (report.contains("mispellings")) { + const char* mispelled[] = { + "decrementing", + "differentially", + "incrementing", + "superset", + }; + const char** mispellPtr = mispelled; + const char** mispellEnd = &mispelled[SK_ARRAY_COUNT(mispelled)]; + for (auto iter : elems) { + if (string::npos != iter.second.fFile.find("undocumented.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("markup.bmh")) { + continue; + } + if (string::npos != iter.second.fFile.find("usingBookmaker.bmh")) { + continue; + } + string check = iter.first.c_str(); + while (check.compare(*mispellPtr) > 0) { + SkDebugf("%s not found\n", *mispellPtr); + if (mispellEnd == ++mispellPtr) { + break; + } + } + if (mispellEnd == mispellPtr) { + break; + } + if (check.compare(*mispellPtr) == 0) { + SkDebugf("%s(%d): %s\n", iter.second.fFile.c_str(), iter.second.fLine, + iter.first.c_str()); + if (mispellEnd == ++mispellPtr) { + break; + } + } } } } void SpellCheck::wordCheck(const string& str) { + if ("nullptr" == str) { + return; // doesn't seem worth it, treating nullptr as a word in need of correction + } bool hasColon = false; bool hasDot = false; bool hasParen = false; @@ -433,11 +616,20 @@ void SpellCheck::wordCheck(const string& str) { && islower(str[0]) && isupper(str[1])) { inCode = true; } + bool methodParam = false; + if (fMethod) { + for (auto child : fMethod->fChildren) { + if (MarkType::kParam == child->fMarkType && str == child->fName) { + methodParam = true; + break; + } + } + } auto& mappy = hasColon ? fColons : hasDot ? fDots : hasParen ? fParens : hasUnderscore ? fUnderscores : - fInStdOut || inCode || fInConst ? fCode : + fInStdOut || fInFormula || inCode || fInConst || methodParam ? fCode : sawDigit ? fDigits : fWords; auto iter = mappy.find(str); if (mappy.end() != iter) { -- cgit v1.2.3