diff options
author | Cary Clark <caryclark@skia.org> | 2017-10-26 07:58:48 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-26 12:17:36 +0000 |
commit | 154beea85961f73ed7f0da047b7ebd16d2a2d829 (patch) | |
tree | 1e128ab8ce82ea6fd9c1a933d5bb36516dd9af4e /tools/bookmaker | |
parent | 456b292956bbc8e90a50be74fc9ccb95ebf11ebd (diff) |
Add docs for SkMatrix, SkRect, SkIRect, SkBitmap
Also minor changes to earlier docs.
Many small changes to improve indentation in generated includes.
Added support for matrix math illustrations.
Docs-Preview: https://skia.org/?cl=58500
Bug: skia:6898
Change-Id: I7da58ad55f82d7fd41d19288beb2cd71730fb01f
Reviewed-on: https://skia-review.googlesource.com/58500
Commit-Queue: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@google.com>
Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'tools/bookmaker')
-rw-r--r-- | tools/bookmaker/bookmaker.cpp | 8 | ||||
-rw-r--r-- | tools/bookmaker/bookmaker.h | 138 | ||||
-rw-r--r-- | tools/bookmaker/includeParser.cpp | 45 | ||||
-rw-r--r-- | tools/bookmaker/includeWriter.cpp | 289 | ||||
-rw-r--r-- | tools/bookmaker/mdOut.cpp | 32 | ||||
-rw-r--r-- | tools/bookmaker/parserCommon.cpp | 133 | ||||
-rw-r--r-- | tools/bookmaker/spellCheck.cpp | 8 |
7 files changed, 510 insertions, 143 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index cc454982fd..e0694071e2 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -630,6 +630,9 @@ const Definition* Definition::hasParam(const string& ref) const { } bool Definition::methodHasReturn(const string& name, TextParser* methodParser) const { + if (methodParser->skipExact("static")) { + methodParser->skipWhiteSpace(); + } const char* lastStart = methodParser->fChar; const char* nameInParser = methodParser->strnstr(name.c_str(), methodParser->fEnd); methodParser->skipTo(nameInParser); @@ -1160,6 +1163,8 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy case MarkType::kFile: case MarkType::kHeight: case MarkType::kImage: + case MarkType::kLiteral: + case MarkType::kOutdent: case MarkType::kPlatform: case MarkType::kSeeAlso: case MarkType::kSubstitute: @@ -2001,6 +2006,8 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) { case MarkType::kFile: case MarkType::kHeight: case MarkType::kImage: + case MarkType::kLiteral: + case MarkType::kOutdent: case MarkType::kPlatform: case MarkType::kReturn: case MarkType::kSeeAlso: @@ -2335,6 +2342,7 @@ int main(int argc, char** const argv) { } if (!done && !FLAGS_spellcheck.isEmpty() && FLAGS_examples.isEmpty()) { bmhParser.spellCheck(FLAGS_bmh[0], FLAGS_spellcheck); + bmhParser.fWroteOut = true; done = true; } int examples = 0; diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index 857caf4c10..f5f53ff7ab 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -40,6 +40,7 @@ using std::vector; enum class KeyWord { kNone, kSK_API, + kSK_BEGIN_REQUIRE_DENSE, kBool, kChar, kClass, @@ -107,10 +108,12 @@ enum class MarkType { kLegend, kLink, kList, + kLiteral, // don't lookup hyperlinks, do substitution, etc kMarkChar, kMember, kMethod, kNoExample, + kOutdent, kParam, kPlatform, kPrivate, @@ -1063,6 +1066,7 @@ public: fMaxLF = 2; fPendingLF = 0; fPendingSpace = 0; + fOutdentNext = false; nl(); } @@ -1078,46 +1082,14 @@ public: fMaxLF = 1; } - bool writeBlockTrim(int size, const char* data) { - while (size && ' ' >= data[0]) { - ++data; - --size; - } - while (size && ' ' >= data[size - 1]) { - --size; - } - if (size <= 0) { - fLastChar = '\0'; - return false; - } - SkASSERT(size < 16000); - if (size > 3 && !strncmp("#end", data, 4)) { - fMaxLF = 1; - } - if (this->leadingPunctuation(data, (size_t) size)) { - fPendingSpace = 0; - } - writePending(); - if (fDebugOut) { - string check(data, size); - SkDebugf("%s", check.c_str()); - } - fprintf(fOut, "%.*s", size, data); - int added = 0; - fLastChar = data[size - 1]; - while (size > 0 && '\n' != data[--size]) { - ++added; - } - fColumn = size ? added : fColumn + added; - fSpaces = 0; - fLinefeeds = 0; - fMaxLF = added > 2 && !strncmp("#if", &data[size + (size > 0)], 3) ? 1 : 2; - return true; - } void writeBlock(int size, const char* data) { SkAssertResult(writeBlockTrim(size, data)); } + + void writeBlockIndent(int size, const char* data); + bool writeBlockTrim(int size, const char* data); + void writeCommentHeader() { this->lf(2); this->writeString("/**"); @@ -1129,6 +1101,8 @@ public: this->lfcr(); } + void writePending(); + // write a pending space, so that two consecutive calls // don't double write, and trailing spaces on lines aren't written void writeSpace(int count = 1) { @@ -1139,62 +1113,12 @@ public: fPendingSpace = count; } - void writeString(const char* str) { - const size_t len = strlen(str); - SkASSERT(len > 0); - SkASSERT(' ' < str[0]); - fLastChar = str[len - 1]; - SkASSERT(' ' < fLastChar); - SkASSERT(!strchr(str, '\n')); - if (this->leadingPunctuation(str, strlen(str))) { - fPendingSpace = 0; - } - writePending(); - if (fDebugOut) { - SkDebugf("%s", str); - } - fprintf(fOut, "%s", str); - fColumn += len; - fSpaces = 0; - fLinefeeds = 0; - fMaxLF = 2; - } + void writeString(const char* str); void writeString(const string& str) { this->writeString(str.c_str()); } - void writePending() { - fPendingLF = SkTMin(fPendingLF, fMaxLF); - bool wroteLF = false; - while (fLinefeeds < fPendingLF) { - if (fDebugOut) { - SkDebugf("\n"); - } - fprintf(fOut, "\n"); - ++fLinefeeds; - wroteLF = true; - } - fPendingLF = 0; - if (wroteLF) { - SkASSERT(0 == fColumn); - SkASSERT(fIndent >= fSpaces); - if (fDebugOut) { - SkDebugf("%*s", fIndent - fSpaces, ""); - } - fprintf(fOut, "%*s", fIndent - fSpaces, ""); - fColumn = fIndent; - fSpaces = fIndent; - } - for (int index = 0; index < fPendingSpace; ++index) { - if (fDebugOut) { - SkDebugf(" "); - } - fprintf(fOut, " "); - ++fColumn; - } - fPendingSpace = 0; - } unordered_map<string, sk_sp<SkData>> fRawData; unordered_map<string, vector<char>> fLFOnly; @@ -1209,6 +1133,7 @@ public: int fPendingSpace; // one or two spaces should preceed the next string or block char fLastChar; // last written bool fDebugOut; // set true to write to std out + bool fOutdentNext; // set at end of embedded struct to prevent premature outdent private: typedef TextParser INHERITED; }; @@ -1226,6 +1151,7 @@ public: kNo, // neither resolved nor output kYes, // resolved, output kOut, // not resolved, but output + kLiteral, // output untouched (FIXME: is this really different from kOut?) }; enum class Exemplary { @@ -1267,7 +1193,7 @@ public: , { "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_O, E_N, M_CSST | M_E } +, { "Code", nullptr, MarkType::kCode, R_O, E_N, M_CSST | M_E | M(Method) } , { "", 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 } @@ -1291,10 +1217,12 @@ public: , { "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 } +, { "Literal", nullptr, MarkType::kLiteral, R_N, E_N, M(Code) } , { "", 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 } +, { "Outdent", nullptr, MarkType::kOutdent, R_N, E_N, M(Code) } , { "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 } @@ -1474,10 +1402,12 @@ public: , { nullptr, MarkType::kLegend } , { nullptr, MarkType::kLink } , { nullptr, MarkType::kList } + , { nullptr, MarkType::kLiteral } , { nullptr, MarkType::kMarkChar } , { nullptr, MarkType::kMember } , { nullptr, MarkType::kMethod } , { nullptr, MarkType::kNoExample } + , { nullptr, MarkType::kOutdent } , { nullptr, MarkType::kParam } , { nullptr, MarkType::kPlatform } , { nullptr, MarkType::kPrivate } @@ -1685,6 +1615,20 @@ public: this->writeEndTag(tagType, tagID.c_str(), spaces); } + void writeIncompleteTag(const char* tagType, const string& tagID, int spaces = 1) { + this->writeString(string("#") + tagType + " " + tagID); + this->writeSpace(spaces); + this->writeString("incomplete"); + this->writeSpace(); + this->writeString("##"); + this->lf(1); + } + + void writeIncompleteTag(const char* tagType) { + this->writeString(string("#") + tagType + " incomplete ##"); + this->lf(1); + } + void writeTableHeader(const char* col1, size_t pad, const char* col2) { this->lf(1); this->writeString("#Table"); @@ -1858,11 +1802,13 @@ public: fBmhParser = nullptr; fEnumDef = nullptr; fMethodDef = nullptr; - fStructDef = nullptr; + fBmhStructDef = nullptr; fAttrDeprecated = nullptr; fAnonymousEnumCount = 1; fInStruct = false; fWroteMethod = false; + fIndentNext = false; + fPendingMethod = false; } string resolveMethod(const char* start, const char* end, bool first); @@ -1880,7 +1826,7 @@ private: const Definition* fBmhMethod; const Definition* fEnumDef; const Definition* fMethodDef; - const Definition* fStructDef; + const Definition* fBmhStructDef; const Definition* fAttrDeprecated; const char* fContinuation; // used to construct paren-qualified method name int fAnonymousEnumCount; @@ -1891,6 +1837,8 @@ private: int fStructCommentTab; bool fInStruct; bool fWroteMethod; + bool fIndentNext; + bool fPendingMethod; typedef IncludeParser INHERITED; }; @@ -1988,7 +1936,15 @@ private: fInList = false; } - BmhParser::Resolvable resolvable(MarkType markType) { + BmhParser::Resolvable resolvable(const Definition* definition) const { + MarkType markType = definition->fMarkType; + if (MarkType::kCode == markType) { + for (auto child : definition->fChildren) { + if (MarkType::kLiteral == child->fMarkType) { + return BmhParser::Resolvable::kLiteral; + } + } + } if ((MarkType::kExample == markType || MarkType::kFunction == markType) && fHasFiddle) { return BmhParser::Resolvable::kNo; diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp index 4ad83d8aa7..c4ee8e7217 100644 --- a/tools/bookmaker/includeParser.cpp +++ b/tools/bookmaker/includeParser.cpp @@ -10,6 +10,7 @@ const IncludeKey kKeyWords[] = { { "", KeyWord::kNone, KeyProperty::kNone }, { "SK_API", KeyWord::kSK_API, KeyProperty::kModifier }, + { "SK_BEGIN_REQUIRE_DENSE", KeyWord::kSK_BEGIN_REQUIRE_DENSE, KeyProperty::kModifier }, { "bool", KeyWord::kBool, KeyProperty::kNumber }, { "char", KeyWord::kChar, KeyProperty::kNumber }, { "class", KeyWord::kClass, KeyProperty::kObject }, @@ -105,7 +106,7 @@ void IncludeParser::checkForMissingParams(const vector<string>& methodParams, } } if (!found) { - this->writeEndTag("Param", methodParam, 2); + this->writeIncompleteTag("Param", methodParam, 2); } } for (auto& foundParam : foundParams) { @@ -508,11 +509,16 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) { } this->lf(2); this->writeTag("Example"); + this->lf(1); + this->writeString("// incomplete"); + this->lf(1); this->writeEndTag(); this->lf(2); - this->writeEndTag("ToDo", "incomplete"); + this->writeTag("SeeAlso"); + this->writeSpace(); + this->writeString("incomplete"); this->lf(2); - this->writeEndTag(); + this->writeEndTag("Method"); this->lf(2); } } @@ -673,7 +679,7 @@ void IncludeParser::dumpComment(const Definition& token) { this->nl(); } this->lf(2); - this->writeEndTag("Return"); + this->writeIncompleteTag("Return"); } } } @@ -1389,11 +1395,36 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) { auto tokenIter = child->fParent->fTokens.begin(); std::advance(tokenIter, child->fParentIndex); tokenIter = std::prev(tokenIter); - string nameStr(tokenIter->fStart, tokenIter->fContentEnd - tokenIter->fStart); + const char* nameEnd = tokenIter->fContentEnd; + bool add2 = false; + if ('[' == tokenIter->fStart[0]) { + auto closeParen = std::next(tokenIter); + SkASSERT(Definition::Type::kBracket == closeParen->fType && + '(' == closeParen->fContentStart[0]); + nameEnd = closeParen->fContentEnd + 1; + closeParen = std::next(closeParen); + add2 = true; + if (Definition::Type::kKeyWord == closeParen->fType && + KeyWord::kConst == closeParen->fKeyWord) { + add2 = false; + } + tokenIter = std::prev(tokenIter); + } + string nameStr(tokenIter->fStart, nameEnd - tokenIter->fStart); + if (add2) { + nameStr += "_2"; + } while (tokenIter != child->fParent->fTokens.begin()) { auto testIter = std::prev(tokenIter); switch (testIter->fType) { case Definition::Type::kWord: + if (testIter == child->fParent->fTokens.begin() && + (KeyWord::kIfdef == child->fParent->fKeyWord || + KeyWord::kIfndef == child->fParent->fKeyWord || + KeyWord::kIf == child->fParent->fKeyWord)) { + std::next(tokenIter); + break; + } goto keepGoing; case Definition::Type::kKeyWord: { KeyProperty keyProperty = kKeyWords[(int) testIter->fKeyWord].fProperty; @@ -1608,7 +1639,9 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) { // pick up templated function pieces when method is found break; case Bracket::kDebugCode: - // todo: handle this + if (!this->parseObjects(child, markupDef)) { + return false; + } break; case Bracket::kSquare: { // check to see if parent is operator, the only case we handle so far diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index ff7c0e3c56..399fd4688b 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -11,8 +11,44 @@ void IncludeWriter::descriptionOut(const Definition* def) { const char* commentStart = def->fContentStart; int commentLen = (int) (def->fContentEnd - commentStart); bool breakOut = false; + SkDEBUGCODE(bool wroteCode = false); for (auto prop : def->fChildren) { switch (prop->fMarkType) { + case MarkType::kCode: { + bool literal = false; + bool literalOutdent = false; + commentLen = (int) (prop->fStart - commentStart); + if (commentLen > 0) { + SkASSERT(commentLen < 1000); + if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) { + this->lf(2); + } + } + size_t childSize = prop->fChildren.size(); + if (childSize) { + SkASSERT(1 == childSize || 2 == childSize); // incomplete + SkASSERT(MarkType::kLiteral == prop->fChildren[0]->fMarkType); + SkASSERT(1 == childSize || MarkType::kOutdent == prop->fChildren[1]->fMarkType); + commentStart = prop->fChildren[childSize - 1]->fContentStart; + literal = true; + literalOutdent = 2 == childSize && + MarkType::kOutdent == prop->fChildren[1]->fMarkType; + } + commentLen = (int) (prop->fContentEnd - commentStart); + SkASSERT(commentLen > 0); + if (literal) { + if (!literalOutdent) { + fIndent += 4; + } + this->writeBlockIndent(commentLen, commentStart); + this->lf(2); + if (!literalOutdent) { + fIndent -= 4; + } + commentStart = prop->fTerminator; + SkDEBUGCODE(wroteCode = true); + } + } break; case MarkType::kDefinedBy: commentStart = prop->fTerminator; break; @@ -48,20 +84,35 @@ void IncludeWriter::descriptionOut(const Definition* def) { commentStart = prop->fTerminator; commentLen = (int) (def->fContentEnd - commentStart); break; - case MarkType::kFormula: + case MarkType::kFormula: { commentLen = prop->fStart - commentStart; if (commentLen > 0) { if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) { - this->lfcr(); + if (commentLen > 1 && '\n' == prop->fStart[-1] && + '\n' == prop->fStart[-2]) { + this->lf(1); + } else { + this->writeSpace(); + } } } - this->writeBlock(prop->length(), prop->fContentStart); + int saveIndent = fIndent; + if (fIndent < fColumn + 1) { + fIndent = fColumn + 1; + } + this->writeBlockIndent(prop->length(), prop->fContentStart); + fIndent = saveIndent; commentStart = prop->fTerminator; commentLen = (int) (def->fContentEnd - commentStart); - if ('\n' == commentStart[0] && '\n' == commentStart[1]) { + if (commentLen > 1 && '\n' == commentStart[0] && '\n' == commentStart[1]) { this->lf(2); + } else { + SkASSERT('\n' == prop->fTerminator[0]); + if ('.' != prop->fTerminator[1] && !fLinefeeds) { + this->writeSpace(); + } } - break; + } break; case MarkType::kToDo: commentLen = (int) (prop->fStart - commentStart); if (commentLen > 0) { @@ -105,8 +156,10 @@ void IncludeWriter::descriptionOut(const Definition* def) { break; } } - SkASSERT(commentLen > 0 && commentLen < 1500); - this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500)); + if (commentLen > 0) { + this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + } } void IncludeWriter::enumHeaderOut(const RootDefinition* root, @@ -116,6 +169,10 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root, child.fContentStart; this->writeBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing this->lf(2); + if (fIndentNext) { + fIndent += 4; + fIndentNext = false; + } fDeferComment = nullptr; fStart = child.fContentStart; const auto& nameDef = child.fTokens.front(); @@ -172,6 +229,9 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root, const char* commentEnd = test->fStart; if (!wroteHeader && !this->contentFree((int) (commentEnd - commentStart), commentStart)) { + if (fIndentNext) { + fIndent += 4; + } this->writeCommentHeader(); this->writeString("\\enum"); if (fullName.length() > 0) { @@ -193,9 +253,15 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root, } this->rewriteBlock((int) (commentEnd - commentStart), commentStart, Phrase::kNo); if (MarkType::kAnchor == test->fMarkType) { + bool newLine = commentEnd - commentStart > 1 && + '\n' == commentEnd[-1] && '\n' == commentEnd[-2]; commentStart = test->fContentStart; commentEnd = test->fChildren[0]->fStart; - this->writeSpace(); + if (newLine) { + this->lf(2); + } else { + this->writeSpace(); + } this->rewriteBlock((int) (commentEnd - commentStart), commentStart, Phrase::kNo); lastAnchor = true; // this->writeSpace(); } @@ -518,12 +584,17 @@ void IncludeWriter::enumSizeItems(const Definition& child) { // walk children and output complete method doxygen description void IncludeWriter::methodOut(const Definition* method, const Definition& child) { + if (fPendingMethod) { + fIndent -= 4; + fPendingMethod = false; + } fBmhMethod = method; fMethodDef = &child; fContinuation = nullptr; fDeferComment = nullptr; - if (0 == fIndent) { - fIndent = 4; + if (0 == fIndent || fIndentNext) { + fIndent += 4; + fIndentNext = false; } this->writeCommentHeader(); fIndent += 4; @@ -602,13 +673,17 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const const char* blockEnd = fWroteMethod && fDeferComment ? fDeferComment->fStart - 1 : memberStart->fStart; this->writeBlockTrim((int) (blockEnd - blockStart), blockStart); + if (fIndentNext) { + fIndent += 4; + fIndentNext = false; + } fWroteMethod = false; const char* commentStart = nullptr; ptrdiff_t commentLen = 0; string name(child.fContentStart, (int) (child.fContentEnd - child.fContentStart)); bool isShort; Definition* commentBlock = nullptr; - for (auto memberDef : fStructDef->fChildren) { + for (auto memberDef : fBmhStructDef->fChildren) { if (memberDef->fName.length() - name.length() == memberDef->fName.find(name)) { commentStart = memberDef->fContentStart; commentLen = memberDef->fContentEnd - commentStart; @@ -668,8 +743,8 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const this->writeString("//!<"); this->writeSpace(); this->rewriteBlock(commentLen, commentStart, Phrase::kNo); - this->lfcr(); } + this->lf(2); return valueEnd; } @@ -784,7 +859,7 @@ void IncludeWriter::structSizeMembers(const Definition& child) { fStructValueTab -= 1 /* ; */ ; } // iterate through bmh children and see which comments fit on include lines - for (auto& member : fStructDef->fChildren) { + for (auto& member : fBmhStructDef->fChildren) { if (MarkType::kMember != member->fMarkType) { continue; } @@ -800,6 +875,21 @@ void IncludeWriter::structSizeMembers(const Definition& child) { } } +static bool find_start(const Definition* startDef, const char* start) { + for (const auto& child : startDef->fTokens) { + if (child.fContentStart == start) { + return MarkType::kMethod == child.fMarkType; + } + if (child.fContentStart >= start) { + break; + } + if (find_start(&child, start)) { + return true; + } + } + return false; +} + bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefinition* root) { ParentPair pair = { def, prevPair }; // write bulk of original include up to class, method, enum, etc., excepting preceding comment @@ -816,11 +906,30 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti bool inStruct = false; bool inConstructor = false; bool inInline = false; + bool eatOperator = false; + const Definition* requireDense = nullptr; + const Definition* startDef = nullptr; for (auto& child : def->fTokens) { + if (KeyWord::kOperator == child.fKeyWord && method && + Definition::MethodType::kOperator == method->fMethodType) { + eatOperator = true; + continue; + } + if (eatOperator) { + if (Bracket::kSquare == child.fBracket || Bracket::kParen == child.fBracket) { + continue; + } + eatOperator = false; + fContinuation = nullptr; + if (KeyWord::kConst == child.fKeyWord) { + continue; + } + } if (memberEnd) { if (memberEnd != &child) { continue; } + startDef = &child; fStart = child.fContentStart + 1; memberEnd = nullptr; } @@ -958,6 +1067,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti continue; } const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 : + fAttrDeprecated ? fAttrDeprecated->fContentStart - 1 : child.fContentStart; // FIXME: roll end-trimming into writeBlockTrim call while (fStart < bodyEnd && ' ' >= bodyEnd[-1]) { @@ -967,11 +1077,15 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti if (blockSize) { this->writeBlock(blockSize, fStart); } + startDef = &child; fStart = child.fContentStart; methodName = root->fName + "::" + child.fName; inConstructor = root->fName == child.fName; fContinuation = child.fContentEnd; method = root->find(methodName, RootDefinition::AllowParens::kNo); +// if (!method) { +// method = root->find(methodName + "()", RootDefinition::AllowParens::kNo); +// } if (!method) { continue; } @@ -981,13 +1095,26 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti } this->methodOut(method, child); if (fAttrDeprecated) { + startDef = fAttrDeprecated; fStart = fAttrDeprecated->fContentStart; fAttrDeprecated = nullptr; } continue; } if (Definition::Type::kKeyWord == child.fType) { - const Definition* structDef = nullptr; + if (fIndentNext) { + SkDebugf(""); + // too soon +#if 0 // makes struct Lattice indent when it oughtn't + if (KeyWord::kEnum == child.fKeyWord) { + fIndent += 4; + } + if (KeyWord::kPublic != child.fKeyWord) { + fIndentNext = false; + } +#endif + } + const Definition* cIncludeStructDef = nullptr; switch (child.fKeyWord) { case KeyWord::kStruct: case KeyWord::kClass: @@ -1002,20 +1129,51 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti } } if (fInStruct) { + // try child; root+child; root->parent+child; etc. + int trial = 0; + const RootDefinition* search = root; + const Definition* parent = search->fParent; + do { + string name; + if (0 == trial) { + name = child.fName; + } else if (1 == trial) { + name = root->fName + "::" + child.fName; + } else { + SkASSERT(parent); + name = parent->fName + "::" + child.fName; + search = parent->asRoot(); + parent = search->fParent; + } + fBmhStructDef = search->find(name, RootDefinition::AllowParens::kNo); + } while (!fBmhStructDef && ++trial); + root = const_cast<RootDefinition*>(fBmhStructDef->asRoot()); + SkASSERT(root); fIndent += 4; - fStructDef = root->find(child.fName, RootDefinition::AllowParens::kNo); - if (nullptr == structDef) { - fStructDef = root->find(root->fName + "::" + child.fName, - RootDefinition::AllowParens::kNo); - } this->structSizeMembers(child); fIndent -= 4; + SkASSERT(!fIndentNext); + fIndentNext = true; } if (child.fChildren.size() > 0) { const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 : child.fContentStart; this->writeBlockTrim((int) (bodyEnd - fStart), fStart); - fStart = child.fContentStart; + if (fPendingMethod) { + fIndent -= 4; + fPendingMethod = false; + } + startDef = requireDense ? requireDense : &child; + fStart = requireDense ? requireDense->fContentStart : child.fContentStart; + requireDense = nullptr; + if (!fInStruct && child.fName != root->fName) { + root = &fBmhParser->fClassMap[child.fName]; + fRootTopic = root->fParent; + SkASSERT(!root->fVisited); + root->clearVisited(); + fIndent = 0; + fBmhStructDef = root; + } if (child.fName == root->fName) { if (Definition* parent = root->fParent) { if (MarkType::kTopic == parent->fMarkType || @@ -1030,36 +1188,43 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti SkASSERT(0); // incomplete } } else { - structDef = root->find(child.fName, RootDefinition::AllowParens::kNo); - if (nullptr == structDef) { - structDef = root->find(root->fName + "::" + child.fName, + SkASSERT(fInStruct); + #if 0 + fBmhStructDef = root->find(child.fName, RootDefinition::AllowParens::kNo); + if (nullptr == fBmhStructDef) { + fBmhStructDef = root->find(root->fName + "::" + child.fName, RootDefinition::AllowParens::kNo); } - if (!structDef) { + if (!fBmhStructDef) { this->lf(2); fIndent = 0; this->writeBlock((int) (fStart - bodyEnd), bodyEnd); this->lfcr(); continue; } + #endif Definition* codeBlock = nullptr; - SkDEBUGCODE(Definition* nextBlock = nullptr); - for (auto test : structDef->fChildren) { + Definition* nextBlock = nullptr; + for (auto test : fBmhStructDef->fChildren) { if (MarkType::kCode == test->fMarkType) { SkASSERT(!codeBlock); // FIXME: check enum for correct order earlier codeBlock = test; continue; } if (codeBlock) { - SkDEBUGCODE(nextBlock = test); + nextBlock = test; break; } } // FIXME: trigger error earlier if inner #Struct or #Class is missing #Code SkASSERT(nextBlock); // FIXME: check enum for correct order earlier - const char* commentStart = structDef->fContentStart; - const char* commentEnd = codeBlock->fStart; - this->structOut(root, *structDef, commentStart, commentEnd); + const char* commentStart = codeBlock->fTerminator; + const char* commentEnd = nextBlock->fStart; + if (fIndentNext) { +// fIndent += 4; + } + fIndentNext = true; + this->structOut(root, *fBmhStructDef, commentStart, commentEnd); } fDeferComment = nullptr; } else { @@ -1096,17 +1261,21 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti case KeyWord::kSK_API: case KeyWord::kTypedef: break; + case KeyWord::kSK_BEGIN_REQUIRE_DENSE: + requireDense = &child; + break; default: SkASSERT(0); } - if (structDef) { + if (cIncludeStructDef) { TextParser structName(&child); SkAssertResult(structName.skipToEndBracket('{')); + startDef = &child; fStart = structName.fChar + 1; this->writeBlock((int) (fStart - child.fStart), child.fStart); this->lf(2); fIndent += 4; - if (!this->populate(&child, &pair, const_cast<Definition*>(structDef)->asRoot())) { + if (!this->populate(&child, &pair, const_cast<Definition*>(cIncludeStructDef)->asRoot())) { return false; } // output any remaining definitions at current indent level @@ -1126,8 +1295,28 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti if (!this->populate(child.fChildren[0], &pair, root)) { return false; } - } else if (!this->populate(&child, &pair, root)) { - return false; + } else { + if (!this->populate(&child, &pair, root)) { + return false; + } + if (KeyWord::kClass == child.fKeyWord || KeyWord::kStruct == child.fKeyWord) { + fStructMemberTab = 0; + if (fInStruct) { + fInStruct = false; + do { + SkASSERT(root); + root = const_cast<RootDefinition*>(root->fParent->asRoot()); + } while (MarkType::kTopic == root->fMarkType || + MarkType::kSubtopic == root->fMarkType); + SkASSERT(MarkType::kStruct == root->fMarkType || + MarkType::kClass == root->fMarkType); + fPendingMethod = false; + if (startDef) { + fPendingMethod = find_start(startDef, fStart); + } + fOutdentNext = !fPendingMethod; + } + } } } continue; @@ -1140,17 +1329,25 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti this->enumMembersOut(root, child); this->writeString("};"); this->lf(2); + startDef = child.fParent; fStart = child.fParent->fContentEnd; SkASSERT(';' == fStart[0]); ++fStart; fDeferComment = nullptr; fInEnum = false; + if (fIndentNext) { +// fIndent -= 4; + fIndentNext = false; + } continue; } if (fAttrDeprecated) { continue; } fDeferComment = nullptr; + if (KeyWord::kClass == def->fKeyWord || KeyWord::kStruct == def->fKeyWord) { + fIndentNext = true; + } if (!this->populate(&child, &pair, root)) { return false; } @@ -1162,13 +1359,17 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti auto iter = def->fTokens.begin(); std::advance(iter, child.fParentIndex - 1); memberStart = &*iter; - if (!fStructDef) { + if (!fStructMemberTab) { SkASSERT(KeyWord::kStruct == def->fParent->fKeyWord); - fStructDef = def->fParent; - this->structSizeMembers(*fStructDef); + fIndent += 4; + this->structSizeMembers(*def->fParent); + fIndent -= 4; +// SkASSERT(!fIndentNext); + fIndentNext = true; } } memberEnd = this->structMemberOut(memberStart, child); + startDef = &child; fStart = child.fContentEnd + 1; fDeferComment = nullptr; } @@ -1322,8 +1523,8 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first, rootDefIter = fBmhParser->fTopicMap.find(prefixedName); if (fBmhParser->fTopicMap.end() != rootDefIter) { rootDef = rootDefIter->second; - } else if (fStructDef) { - string localPrefix = fStructDef->fFiddle + '_' + undername; + } else if (fBmhStructDef) { + string localPrefix = fBmhStructDef->fFiddle + '_' + undername; rootDefIter = fBmhParser->fTopicMap.find(localPrefix); if (fBmhParser->fTopicMap.end() != rootDefIter) { rootDef = rootDefIter->second; @@ -1648,7 +1849,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr break; case Word::kCap: case Word::kFirst: - if (!isupper(last)) { + if (!isupper(last) && '~' != last) { word = Word::kMixed; } break; @@ -1697,6 +1898,14 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr hasIndirection |= embeddedIndirection; hasSymbol |= embeddedSymbol; break; + case '~': + SkASSERT(Word::kStart == word); + word = PunctuationState::kStart == punctuation ? Word::kFirst : Word::kCap; + start = run; + hasUpper = true; + hasIndirection |= embeddedIndirection; + hasSymbol |= embeddedSymbol; + break; default: SkASSERT(0); } diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp index 242d667736..ed3cd2bcaf 100644 --- a/tools/bookmaker/mdOut.cpp +++ b/tools/bookmaker/mdOut.cpp @@ -324,7 +324,7 @@ bool MdOut::buildRefFromFile(const char* name, const char* outDir) { bool MdOut::checkParamReturnBody(const Definition* def) const { TextParser paramBody(def); const char* descriptionStart = paramBody.fChar; - if (!islower(descriptionStart[0])) { + if (!islower(descriptionStart[0]) && !isdigit(descriptionStart[0])) { paramBody.skipToNonAlphaNum(); string ref = string(descriptionStart, paramBody.fChar - descriptionStart); if (!this->isDefined(paramBody, ref, true)) { @@ -349,7 +349,7 @@ void MdOut::childrenOut(const Definition* def, const char* start) { } else if (MarkType::kEnumClass == def->fMarkType) { fEnumClass = def; } - BmhParser::Resolvable resolvable = this->resolvable(def->fMarkType); + BmhParser::Resolvable resolvable = this->resolvable(def); for (auto& child : def->fChildren) { end = child->fStart; if (BmhParser::Resolvable::kNo != resolvable) { @@ -640,7 +640,7 @@ void MdOut::markTypeOut(Definition* def) { case MarkType::kCode: this->lfAlways(2); fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;" - "width: 44em; background-color: #f0f0f0\">"); + "width: 50em; background-color: #f0f0f0\">"); this->lf(1); break; case MarkType::kColumn: @@ -714,7 +714,7 @@ void MdOut::markTypeOut(Definition* def) { fprintf(fOut, "<div><fiddle-embed name=\"%s\">", def->fHash.c_str()); } else { fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;" - "width: 44em; background-color: #f0f0f0\">"); + "width: 50em; background-color: #f0f0f0\">"); this->lf(1); } } break; @@ -742,6 +742,8 @@ void MdOut::markTypeOut(Definition* def) { fprintf(fOut, "<table>"); this->lf(1); break; + case MarkType::kLiteral: + break; case MarkType::kMarkChar: fBmhParser.fMC = def->fContentStart[0]; break; @@ -768,7 +770,7 @@ void MdOut::markTypeOut(Definition* def) { } // TODO: put in css spec that we can define somewhere else (if markup supports that) - // TODO: 50em below should match limt = 80 in formatFunction() + // TODO: 50em below should match limit = 80 in formatFunction() this->writePending(); string preformattedStr = preformat(formattedStr); fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;" @@ -781,6 +783,8 @@ void MdOut::markTypeOut(Definition* def) { } break; case MarkType::kNoExample: break; + case MarkType::kOutdent: + break; case MarkType::kParam: { if (TableState::kNone == fTableState) { this->mdHeaderOut(3); @@ -1004,6 +1008,24 @@ void MdOut::mdHeaderOutLF(int depth, int lf) { } void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) { + if (BmhParser::Resolvable::kLiteral == resolvable && end > start) { + while ('\n' == *start) { + ++start; + } + const char* spaceStart = start; + while (' ' == *start) { + ++start; + } + if (start > spaceStart) { + fIndent = start - spaceStart; + } + this->writeBlockTrim(end - start, start); + if ('\n' == end[-1]) { + this->lf(1); + } + fIndent = 0; + return; + } // FIXME: this needs the markdown character present when the def was defined, // not the last markdown character the parser would have seen... while (fBmhParser.fMC == end[-1]) { diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp index cb55bcb640..fbfcbae728 100644 --- a/tools/bookmaker/parserCommon.cpp +++ b/tools/bookmaker/parserCommon.cpp @@ -7,6 +7,11 @@ #include "bookmaker.h" +static void debug_out(int len, const char* data) { + // convenient place to intercept arbitrary output + SkDebugf("%.*s", len, data); +} + bool ParserCommon::parseSetup(const char* path) { this->reset(); sk_sp<SkData> data = SkData::MakeFromFileName(path); @@ -49,3 +54,131 @@ bool ParserCommon::parseSetup(const char* path) { fLineCount = 1; return true; } + +void ParserCommon::writeBlockIndent(int size, const char* data) { + while (size && ' ' >= data[size - 1]) { + --size; + } + bool newLine = false; + while (size) { + while (size && ' ' > data[0]) { + ++data; + --size; + } + if (!size) { + return; + } + if (newLine) { + this->lf(1); + } + TextParser parser(fFileName, data, data + size, fLineCount); + const char* lineEnd = parser.strnchr('\n', data + size); + int len = lineEnd ? (int) (lineEnd - data) : size; + this->writePending(); + this->indentToColumn(fIndent); + if (fDebugOut) { + debug_out(len, data); + } + fprintf(fOut, "%.*s", len, data); + size -= len; + data += len; + newLine = true; + } +} + +bool ParserCommon::writeBlockTrim(int size, const char* data) { + if (fOutdentNext) { + fIndent -= 4; + fOutdentNext = false; + } + while (size && ' ' >= data[0]) { + ++data; + --size; + } + while (size && ' ' >= data[size - 1]) { + --size; + } + if (size <= 0) { + fLastChar = '\0'; + return false; + } + SkASSERT(size < 16000); + if (size > 3 && !strncmp("#end", data, 4)) { + fMaxLF = 1; + } + if (this->leadingPunctuation(data, (size_t) size)) { + fPendingSpace = 0; + } + this->writePending(); + if (fDebugOut) { + debug_out(size, data); + } + fprintf(fOut, "%.*s", size, data); + int added = 0; + fLastChar = data[size - 1]; + while (size > 0 && '\n' != data[--size]) { + ++added; + } + fColumn = size ? added : fColumn + added; + fSpaces = 0; + fLinefeeds = 0; + fMaxLF = added > 2 && !strncmp("#if", &data[size + (size > 0)], 3) ? 1 : 2; + if (fOutdentNext) { + fIndent -= 4; + fOutdentNext = false; + } + return true; +} + +void ParserCommon::writePending() { + fPendingLF = SkTMin(fPendingLF, fMaxLF); + bool wroteLF = false; + while (fLinefeeds < fPendingLF) { + if (fDebugOut) { + SkDebugf("\n"); + } + fprintf(fOut, "\n"); + ++fLinefeeds; + wroteLF = true; + } + fPendingLF = 0; + if (wroteLF) { + SkASSERT(0 == fColumn); + SkASSERT(fIndent >= fSpaces); + if (fDebugOut) { + SkDebugf("%*s", fIndent - fSpaces, ""); + } + fprintf(fOut, "%*s", fIndent - fSpaces, ""); + fColumn = fIndent; + fSpaces = fIndent; + } + for (int index = 0; index < fPendingSpace; ++index) { + if (fDebugOut) { + SkDebugf(" "); + } + fprintf(fOut, " "); + ++fColumn; + } + fPendingSpace = 0; +} + +void ParserCommon::writeString(const char* str) { + const size_t len = strlen(str); + SkASSERT(len > 0); + SkASSERT(' ' < str[0]); + fLastChar = str[len - 1]; + SkASSERT(' ' < fLastChar); + SkASSERT(!strchr(str, '\n')); + if (this->leadingPunctuation(str, strlen(str))) { + fPendingSpace = 0; + } + this->writePending(); + if (fDebugOut) { + debug_out((int) strlen(str), str); + } + fprintf(fOut, "%s", str); + fColumn += len; + fSpaces = 0; + fLinefeeds = 0; + fMaxLF = 2; +} diff --git a/tools/bookmaker/spellCheck.cpp b/tools/bookmaker/spellCheck.cpp index 3a32f37bc4..e2c4286e18 100644 --- a/tools/bookmaker/spellCheck.cpp +++ b/tools/bookmaker/spellCheck.cpp @@ -202,6 +202,8 @@ bool SpellCheck::check(Definition* def) { break; case MarkType::kList: break; + case MarkType::kLiteral: + break; case MarkType::kMarkChar: break; case MarkType::kMember: @@ -220,6 +222,8 @@ bool SpellCheck::check(Definition* def) { } break; case MarkType::kNoExample: break; + case MarkType::kOutdent: + break; case MarkType::kParam: { if (TableState::kNone == fTableState) { fTableState = TableState::kRow; @@ -490,6 +494,7 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) { if (report.contains("all")) { int column = 0; char lastInitial = 'a'; + int count = 0; for (auto iter : elems) { if (string::npos != iter.second.fFile.find("undocumented.bmh")) { continue; @@ -521,8 +526,9 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) { } SkDebugf("%s ", check.c_str()); column += check.length(); + ++count; } - SkDebugf("\n\n"); + SkDebugf("\n\ncount = %d\n", count); return; } int index = 0; |