diff options
author | Cary Clark <caryclark@skia.org> | 2017-08-29 17:36:51 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-30 11:06:02 +0000 |
commit | 73fa972d0bd9de7cb801323495b5d1fabd31b24f (patch) | |
tree | 3a376a200b59bfd5c434eba345cf8e978a8f8ba6 /tools/bookmaker | |
parent | 1a763632d21636504d78910f7dea0aa708c6365f (diff) |
work on path
Work on SkPath.h documentation; fixed self-consistency
bugs identified by bookmaker. Fixed a couple of
minor typos in SkPath.h itself.
Also brought SkPaint and SkCanvas docs up to date.
TBR=reed@google.com
Docs-Preview: https://skia.org/?cl=39040
Bug: skia: 6898
Change-Id: Id89d4e2fa7fb6ee2e3cbec7ea762e06308b67d8b
Reviewed-on: https://skia-review.googlesource.com/39040
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 | 302 | ||||
-rw-r--r-- | tools/bookmaker/bookmaker.h | 18 | ||||
-rw-r--r-- | tools/bookmaker/includeParser.cpp | 42 | ||||
-rw-r--r-- | tools/bookmaker/includeWriter.cpp | 60 |
4 files changed, 305 insertions, 117 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index cbb34a2a4f..0c23c7720a 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -25,7 +25,9 @@ Text Encoding anchors in paragraph are echoed instead of being linked to anchor consts like enum members need fully qualfied refs to make a valid link enum comments should be disallowed unless after #Enum and before first #Const ... or, should look for enum comments in other places - +trouble with aliases, plurals + need to keep first letter of includeWriter @param / @return lowercase + Quad -> quad, Quads -> quads */ static string normalized_name(string name) { @@ -92,7 +94,8 @@ void Definition::setCanonicalFiddle() { fMethodType = Definition::MethodType::kNone; size_t doubleColons = fName.find("::", 0); SkASSERT(string::npos != doubleColons); - string result = fName.substr(0, doubleColons) + "_"; + string base = fName.substr(0, doubleColons); + string result = base + "_"; doubleColons += 2; if (string::npos != fName.find('~', doubleColons)) { fMethodType = Definition::MethodType::kDestructor; @@ -118,56 +121,69 @@ void Definition::setCanonicalFiddle() { } else { SkASSERT(0); // todo: incomplete } - } else if (string::npos != fName.find("()", doubleColons)) { - if (isupper(fName[doubleColons])) { - fMethodType = Definition::MethodType::kConstructor; - result += "empty_constructor"; - } else { - result += fName.substr(doubleColons, fName.length() - doubleColons - 2); - } } else { - size_t comma = fName.find(',', doubleColons); - size_t openParen = fName.find('(', doubleColons); - if (string::npos == comma && string::npos != openParen) { - fMethodType = Definition::MethodType::kConstructor; - result += isMove ? "move_" : "copy_"; - result += "constructor"; - } else if (string::npos == openParen) { - result += fName.substr(doubleColons); + size_t parens = fName.find("()", doubleColons); + if (string::npos != parens) { + string methodName = fName.substr(doubleColons, parens - doubleColons); + do { + size_t nextDouble = methodName.find("::"); + if (string::npos == nextDouble) { + break; + } + base = methodName.substr(0, nextDouble); + result += base + '_'; + methodName = methodName.substr(nextDouble + 2); + doubleColons += nextDouble + 2; + } while (true); + if (base == methodName) { + fMethodType = Definition::MethodType::kConstructor; + result += "empty_constructor"; + } else { + result += fName.substr(doubleColons, fName.length() - doubleColons - 2); + } } else { - fMethodType = Definition::MethodType::kConstructor; - // name them by their param types, e.g. SkCanvas__int_int_const_SkSurfaceProps_star - SkASSERT(string::npos != openParen); - // TODO: move forward until parens are balanced and terminator =,) - TextParser params("", &fName[openParen] + 1, &*fName.end(), 0); - bool underline = false; - while (!params.eof()) { -// SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now -// SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses - if (params.startsWith("const") || params.startsWith("int") - || params.startsWith("Sk")) { - const char* wordStart = params.fChar; - params.skipToNonAlphaNum(); - if (underline) { - result += '_'; - } else { - underline = true; - } - result += string(wordStart, params.fChar - wordStart); - } else { - params.skipToNonAlphaNum(); + size_t openParen = fName.find('(', doubleColons); + if (string::npos == openParen) { + result += fName.substr(doubleColons); + } else { + size_t comma = fName.find(',', doubleColons); + if (string::npos == comma) { + result += isMove ? "move_" : "copy_"; } - if (!params.eof() && '*' == params.peek()) { - if (underline) { - result += '_'; + fMethodType = Definition::MethodType::kConstructor; + // name them by their param types, + // e.g. SkCanvas__int_int_const_SkSurfaceProps_star + // TODO: move forward until parens are balanced and terminator =,) + TextParser params("", &fName[openParen] + 1, &*fName.end(), 0); + bool underline = false; + while (!params.eof()) { + // SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now + // SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses + if (params.startsWith("const") || params.startsWith("int") + || params.startsWith("Sk")) { + const char* wordStart = params.fChar; + params.skipToNonAlphaNum(); + if (underline) { + result += '_'; + } else { + underline = true; + } + result += string(wordStart, params.fChar - wordStart); } else { - underline = true; + params.skipToNonAlphaNum(); + } + if (!params.eof() && '*' == params.peek()) { + if (underline) { + result += '_'; + } else { + underline = true; + } + result += "star"; + params.next(); + params.skipSpace(); } - result += "star"; - params.next(); - params.skipSpace(); + params.skipToAlpha(); } - params.skipToAlpha(); } } } @@ -391,13 +407,25 @@ bool Definition::checkMethod() const { return true; } -bool Definition::crossCheck(const char* tokenID, const Definition& includeToken) const { - const char* defStart = fStart; - SkASSERT('#' == defStart[0]); // FIXME: needs to be per definition - ++defStart; - SkASSERT(!strncmp(defStart, tokenID, strlen(tokenID))); - defStart += strlen(tokenID); - return crossCheckInside(defStart, fContentStart, includeToken); +bool Definition::crossCheck2(const Definition& includeToken) const { + TextParser parser(fFileName, fStart, fContentStart, fLineCount); + parser.skipExact("#"); + bool isMethod = parser.skipName("Method"); + const char* contentEnd; + if (isMethod) { + contentEnd = fContentStart; + } else if (parser.skipName("DefinedBy")) { + contentEnd = fContentEnd; + while (parser.fChar < contentEnd && ' ' >= contentEnd[-1]) { + --contentEnd; + } + if (parser.fChar < contentEnd - 1 && ')' == contentEnd[-1] && '(' == contentEnd[-2]) { + contentEnd -= 2; + } + } else { + return parser.reportError<bool>("unexpected crosscheck marktype"); + } + return crossCheckInside(parser.fChar, contentEnd, includeToken); } bool Definition::crossCheck(const Definition& includeToken) const { @@ -414,6 +442,9 @@ bool Definition::crossCheckInside(const char* start, const char* end, if (inc.startsWith("friend")) { inc.skipWord("friend"); } + if (inc.startsWith("SK_API")) { + inc.skipWord("SK_API"); + } do { bool defEof; bool incEof; @@ -763,6 +794,13 @@ const Definition* RootDefinition::find(const string& ref) const { if (leafIter != fLeaves.end()) { return &leafIter->second; } + if (string::npos == ref.find("()")) { + string withParens = ref + "()"; + const auto parensIter = fLeaves.find(withParens); + if (parensIter != fLeaves.end()) { + return &parensIter->second; + } + } const auto branchIter = fBranches.find(ref); if (branchIter != fBranches.end()) { const RootDefinition* rootDef = branchIter->second; @@ -1006,7 +1044,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy fMarkup.emplace_front(markType, defStart, fLineCount, fParent); definition = &fMarkup.front(); definition->fName = typeNameBuilder[0]; - definition->fFiddle = normalized_name(typeNameBuilder[0]); + definition->fFiddle = fParent->fFiddle; definition->fContentStart = fChar; definition->fContentEnd = this->trimmedBracketEnd(fMC, OneLine::kYes); this->skipToEndBracket(fMC); @@ -1139,6 +1177,54 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy return true; } +void BmhParser::reportDuplicates(const Definition& def, const string& dup) const { + if (MarkType::kExample == def.fMarkType && dup == def.fFiddle) { + TextParser reporter(&def); + reporter.reportError("duplicate example name"); + } + for (auto& child : def.fChildren ) { + reportDuplicates(*child, dup); + } +} + +static void find_examples(const Definition& def, vector<string>* exampleNames) { + if (MarkType::kExample == def.fMarkType) { + exampleNames->push_back(def.fFiddle); + } + for (auto& child : def.fChildren ) { + find_examples(*child, exampleNames); + } +} + +bool BmhParser::checkExamples() const { + vector<string> exampleNames; + for (const auto& topic : fTopicMap) { + if (topic.second->fParent) { + continue; + } + find_examples(*topic.second, &exampleNames); + } + std::sort(exampleNames.begin(), exampleNames.end()); + string* last = nullptr; + string reported; + bool checkOK = true; + for (auto& nameIter : exampleNames) { + if (last && *last == nameIter && reported != *last) { + reported = *last; + SkDebugf("%s\n", reported.c_str()); + for (const auto& topic : fTopicMap) { + if (topic.second->fParent) { + continue; + } + this->reportDuplicates(*topic.second, reported); + } + checkOK = false; + } + last = &nameIter; + } + return checkOK; +} + bool BmhParser::childOf(MarkType markType) const { auto childError = [this](MarkType markType) -> bool { string errStr = "expected "; @@ -1162,26 +1248,32 @@ bool BmhParser::childOf(MarkType markType) const { } string BmhParser::className(MarkType markType) { + const char* end = this->lineEnd(); + const char* mc = this->strnchr(fMC, end); + string classID; + TextParser::Save savePlace(this); + this->skipSpace(); + const char* wordStart = fChar; + this->skipToNonAlphaNum(); + const char* wordEnd = fChar; + classID = string(wordStart, wordEnd - wordStart); + if (!mc) { + savePlace.restore(); + } string builder; const Definition* parent = this->parentSpace(); - if (parent && (parent != fParent || MarkType::kClass != markType)) { + if (parent && parent->fName != classID) { builder += parent->fName; } - const char* end = this->lineEnd(); - const char* mc = this->strnchr(fMC, end); if (mc) { - this->skipSpace(); - const char* wordStart = fChar; - this->skipToNonAlphaNum(); - const char* wordEnd = fChar; if (mc + 1 < fEnd && fMC == mc[1]) { // if ## if (markType != fParent->fMarkType) { return this->reportError<string>("unbalanced method"); } - if (builder.length() > 0 && wordEnd > wordStart) { + if (builder.length() > 0 && classID.size() > 0) { if (builder != fParent->fName) { builder += "::"; - builder += string(wordStart, wordEnd - wordStart); + builder += classID; if (builder != fParent->fName) { return this->reportError<string>("name mismatch"); } @@ -1241,6 +1333,49 @@ bool BmhParser::collectExternals() { return true; } +static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) { + if (MarkType::kExample == def.fMarkType) { + string result; + if (!def.exampleToScript(&result)) { + return false; + } + if (result.length() > 0) { + if (*continuation) { + fprintf(fiddleOut, ",\n"); + } else { + *continuation = true; + } + fprintf(fiddleOut, "%s", result.c_str()); + } + return true; + } + for (auto& child : def.fChildren ) { + if (!dump_examples(fiddleOut, *child, continuation)) { + return false; + } + } + return true; +} + +bool BmhParser::dumpExamples(const char* fiddleJsonFileName) const { + FILE* fiddleOut = fopen(fiddleJsonFileName, "wb"); + if (!fiddleOut) { + SkDebugf("could not open output file %s\n", fiddleJsonFileName); + return false; + } + fprintf(fiddleOut, "{\n"); + bool continuation = false; + for (const auto& topic : fTopicMap) { + if (topic.second->fParent) { + continue; + } + dump_examples(fiddleOut, *topic.second, &continuation); + } + fprintf(fiddleOut, "\n}\n"); + fclose(fiddleOut); + return true; +} + int BmhParser::endHashCount() const { const char* end = fLine + this->lineLength(); int count = 0; @@ -1976,30 +2111,6 @@ DEFINE_bool2(spellcheck, s, false, "Spell-check. (Requires -b)"); DEFINE_bool2(tokens, t, false, "Output include tokens. (Requires -i)"); DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)"); -static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) { - if (MarkType::kExample == def.fMarkType) { - string result; - if (!def.exampleToScript(&result)) { - return false; - } - if (result.length() > 0) { - if (*continuation) { - fprintf(fiddleOut, ",\n"); - } else { - *continuation = true; - } - fprintf(fiddleOut, "%s", result.c_str()); - } - return true; - } - for (auto& child : def.fChildren ) { - if (!dump_examples(fiddleOut, *child, continuation)) { - return false; - } - } - return true; -} - static int count_children(const Definition& def, MarkType markType) { int count = 0; if (markType == def.fMarkType) { @@ -2145,23 +2256,14 @@ int main(int argc, char** const argv) { int examples = 0; int methods = 0; int topics = 0; - FILE* fiddleOut; if (!done && !FLAGS_examples.isEmpty()) { - fiddleOut = fopen(FLAGS_examples[0], "wb"); - if (!fiddleOut) { - SkDebugf("could not open output file %s\n", FLAGS_examples[0]); + // check to see if examples have duplicate names + if (!bmhParser.checkExamples()) { return -1; } - fprintf(fiddleOut, "{\n"); - bool continuation = false; - for (const auto& topic : bmhParser.fTopicMap) { - if (topic.second->fParent) { - continue; - } - dump_examples(fiddleOut, *topic.second, &continuation); + if (!bmhParser.dumpExamples(FLAGS_examples[0])) { + return -1; } - fprintf(fiddleOut, "\n}\n"); - fclose(fiddleOut); } for (const auto& topic : bmhParser.fTopicMap) { if (topic.second->fParent) { diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index fae41c4ddd..0f0693fd77 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -40,6 +40,7 @@ using std::vector; enum class KeyWord { kNone, + kSK_API, kBool, kChar, kClass, @@ -148,6 +149,7 @@ enum class Bracket { kSlashSlash, kPound, kColon, + kDebugCode, // parens get special treatment so SkDEBUGCODE( isn't treated as method }; enum class Punctuation { // catch-all for misc symbols tracked in C @@ -760,7 +762,7 @@ public: bool checkMethod() const; void setCanonicalFiddle(); - bool crossCheck(const char* tokenName, const Definition& includeToken) const; + bool crossCheck2(const Definition& includeToken) const; bool crossCheck(const Definition& includeToken) const; bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const; bool exampleToScript(string* result) const; @@ -1287,6 +1289,8 @@ public: bool addDefinition(const char* defStart, bool hasEnd, MarkType markType, const vector<string>& typeNameBuilder); + bool checkExamples() const; + bool dumpExamples(const char* fiddleJsonFileName) const; bool childOf(MarkType markType) const; string className(MarkType markType); bool collectExternals(); @@ -1316,6 +1320,7 @@ public: } bool popParentStack(Definition* definition); + void reportDuplicates(const Definition& def, const string& dup) const; void reset() override { INHERITED::resetCommon(); @@ -1540,6 +1545,7 @@ public: fRootTopic = nullptr; fInBrace = nullptr; fIncludeWord = nullptr; + fLastObject = nullptr; fPrev = '\0'; fInChar = false; fInCharCommentString = false; @@ -1602,6 +1608,7 @@ protected: unordered_map<string, Definition> fIUnionMap; Definition* fRootTopic; Definition* fInBrace; + Definition* fLastObject; const char* fIncludeWord; char fPrev; bool fInChar; @@ -1646,6 +1653,11 @@ public: list<Definition>::iterator fDefEnd; }; + struct ParentPair { + const Definition* fParent; + const ParentPair* fPrev; + }; + IncludeWriter() : IncludeParser() {} ~IncludeWriter() override {} @@ -1670,7 +1682,7 @@ public: const int start, const int run, int lastWrite, const char last, const char* data); void methodOut(const Definition* method, const Definition& child); - bool populate(Definition* def, RootDefinition* root); + bool populate(Definition* def, ParentPair* parentPair, RootDefinition* root); bool populate(BmhParser& bmhParser); void reset() override { @@ -1680,6 +1692,7 @@ public: fEnumDef = nullptr; fMethodDef = nullptr; fStructDef = nullptr; + fAttrDeprecated = nullptr; fAnonymousEnumCount = 1; fInStruct = false; } @@ -1700,6 +1713,7 @@ private: const Definition* fEnumDef; const Definition* fMethodDef; const Definition* fStructDef; + const Definition* fAttrDeprecated; const char* fContinuation; // used to construct paren-qualified method name int fAnonymousEnumCount; int fEnumItemValueTab; diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp index 6aed93737f..21a47d6e8a 100644 --- a/tools/bookmaker/includeParser.cpp +++ b/tools/bookmaker/includeParser.cpp @@ -25,6 +25,7 @@ struct IncludeKey { const IncludeKey kKeyWords[] = { { "", KeyWord::kNone, KeyProperty::kNone }, + { "SK_API", KeyWord::kSK_API, KeyProperty::kModifier }, { "bool", KeyWord::kBool, KeyProperty::kNumber }, { "char", KeyWord::kChar, KeyProperty::kNumber }, { "class", KeyWord::kClass, KeyProperty::kObject }, @@ -236,7 +237,6 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { if (this->internalName(token)) { continue; } - const char* methodID = bmhParser.fMaps[(int) token.fMarkType].fName; if (!def) { string paramName = className + "::"; paramName += string(token.fContentStart, @@ -304,11 +304,27 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) { } } if (!def) { + if ("SK_ATTR_DEPRECATED" == token.fName) { + break; + } + if (0 == token.fName.find("SkDEBUGCODE")) { + break; + } + } + 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); + } + if (!def) { SkDebugf("method missing from bmh: %s\n", fullName.c_str()); break; } - if (def->crossCheck(methodID, token)) { + if (def->crossCheck2(token)) { def->fVisited = true; + if (MarkType::kDefinedBy == def->fMarkType) { + def->fParent->fVisited = true; + } } else { SkDebugf("method differs from bmh: %s\n", fullName.c_str()); } @@ -912,11 +928,13 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) { iter = std::next(iter); ++lastPublic; } + fLastObject = nullptr; while (childIter != includeDef->fChildren.end() && (*childIter)->fParentIndex < lastPublic) { Definition* child = *childIter; if (!this->parseObject(child, markupDef)) { return false; } + fLastObject = child; childIter = std::next(childIter); } while (childIter != includeDef->fChildren.end()) { @@ -1292,10 +1310,18 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) { case Definition::Type::kBracket: switch (child->fBracket) { case Bracket::kParen: + if (fLastObject) { + TextParser checkDeprecated(child->fFileName, fLastObject->fTerminator + 1, + child->fStart, fLastObject->fLineCount); + checkDeprecated.skipWhiteSpace(); + if (checkDeprecated.startsWith("SK_ATTR_DEPRECATED")) { + break; + } + } if (!this->parseMethod(child, markupDef)) { return this->reportError<bool>("failed to parse method"); } - break; + break; case Bracket::kSlashSlash: case Bracket::kSlashStar: // comments are picked up by parsing objects first @@ -1336,6 +1362,9 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) { case Bracket::kAngle: // pick up templated function pieces when method is found break; + case Bracket::kDebugCode: + // todo: handle this + break; default: return this->reportError<bool>("unhandled bracket"); } @@ -1457,6 +1486,11 @@ bool IncludeParser::parseChar() { case '(': case '[': case '{': { + if (fIncludeWord && '(' == test && fChar - fIncludeWord >= 10 && + !strncmp("SkDEBUGCODE", fIncludeWord, 10)) { + this->pushBracket(Bracket::kDebugCode); + break; + } if (fInCharCommentString) { break; } @@ -1555,6 +1589,8 @@ bool IncludeParser::parseChar() { } else { fInFunction = '}' != test; } + } else if (')' == test && Bracket::kDebugCode == this->topBracket()) { + this->popBracket(); } else { return reportError<bool>("malformed close bracket"); } diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index 81fb3cc255..af2fb89fb8 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -268,6 +268,8 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child commentStart = privateDef->fContentStart; commentLen = (int) (privateDef->fContentEnd - privateDef->fContentStart); } + // 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); if (!currentEnumItem->fShort) { this->writeCommentHeader(); @@ -508,6 +510,7 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child) } this->indentToColumn(column); int partLen = (int) (partEnd - partStart); + // FIXME : detect this earlier; assert if #Return is empty SkASSERT(partLen > 0 && partLen < 200); fIndent = column; this->rewriteBlock(partLen, partStart); @@ -673,6 +676,8 @@ void IncludeWriter::structSizeMembers(Definition& child) { inMethod = false; } else if (Punctuation::kLeftBrace == token.fPunctuation) { inMethod = false; + } else if (Punctuation::kSemicolon == token.fPunctuation) { + inMethod = false; } else { SkASSERT(0); // incomplete } @@ -735,7 +740,8 @@ void IncludeWriter::structSizeMembers(Definition& child) { } } -bool IncludeWriter::populate(Definition* def, RootDefinition* root) { +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 // find associated bmh object // write any associated comments in Doxygen form @@ -762,7 +768,8 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { } if (fContinuation) { if (Definition::Type::kKeyWord == child.fType) { - if (KeyWord::kFriend == child.fKeyWord || KeyWord::kBool == child.fKeyWord) { + if (KeyWord::kFriend == child.fKeyWord || KeyWord::kBool == child.fKeyWord || + KeyWord::kSK_API == child.fKeyWord) { continue; } } @@ -875,14 +882,27 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { continue; } this->methodOut(method, child); + if (fAttrDeprecated) { + fStart = fAttrDeprecated->fContentStart; + fAttrDeprecated = nullptr; + } continue; } if (Definition::Type::kKeyWord == child.fType) { const Definition* structDef = nullptr; switch (child.fKeyWord) { case KeyWord::kStruct: + case KeyWord::kClass: // if struct contains members, compute their name and comment tabs - inStruct = fInStruct = child.fChildren.size() > 0; + if (child.fChildren.size() > 0) { + const ParentPair* testPair = &pair; + while ((testPair = testPair->fPrev)) { + if (KeyWord::kClass == testPair->fParent->fKeyWord) { + inStruct = fInStruct = true; + break; + } + } + } if (fInStruct) { fIndent += 4; fStructDef = root->find(child.fName); @@ -892,11 +912,10 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { this->structSizeMembers(child); fIndent -= 4; } - case KeyWord::kClass: if (child.fChildren.size() > 0) { const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 : child.fContentStart; - this->writeBlock((int) (bodyEnd - fStart), fStart); + this->writeBlockTrim((int) (bodyEnd - fStart), fStart); fStart = child.fContentStart; if (child.fName == root->fName) { if (Definition* parent = root->fParent) { @@ -942,6 +961,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { 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 = codeBlock->fTerminator; const char* commentEnd = nextBlock->fStart; @@ -962,6 +982,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { case KeyWord::kStatic: case KeyWord::kInt: case KeyWord::kUint32_t: + case KeyWord::kUnsigned: case KeyWord::kSize_t: case KeyWord::kFloat: case KeyWord::kBool: @@ -974,6 +995,8 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { case KeyWord::kPrivate: case KeyWord::kProtected: case KeyWord::kFriend: + case KeyWord::kInline: + case KeyWord::kSK_API: case KeyWord::kTypedef: break; default: @@ -986,7 +1009,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { this->writeBlock((int) (fStart - child.fStart), child.fStart); this->lf(2); fIndent += 4; - if (!this->populate(&child, const_cast<Definition*>(structDef)->asRoot())) { + if (!this->populate(&child, &pair, const_cast<Definition*>(structDef)->asRoot())) { return false; } // output any remaining definitions at current indent level @@ -1001,10 +1024,10 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { fDeferComment = nullptr; } else { if (fInEnum && KeyWord::kClass == child.fChildren[0]->fKeyWord) { - if (!this->populate(child.fChildren[0], root)) { + if (!this->populate(child.fChildren[0], &pair, root)) { return false; } - } else if (!this->populate(&child, root)) { + } else if (!this->populate(&child, &pair, root)) { return false; } } @@ -1023,9 +1046,12 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { fDeferComment = nullptr; fInEnum = false; continue; - } + } + if (fAttrDeprecated) { + continue; + } fDeferComment = nullptr; - if (!this->populate(&child, root)) { + if (!this->populate(&child, &pair, root)) { return false; } continue; @@ -1039,6 +1065,12 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) { if (child.fMemberStart) { memberStart = &child; } + const char attrDeprecated[] = "SK_ATTR_DEPRECATED"; + const size_t attrDeprecatedLen = sizeof(attrDeprecated) - 1; + if (attrDeprecatedLen == child.fContentEnd - child.fContentStart && + !strncmp(attrDeprecated, child.fStart, attrDeprecatedLen)) { + fAttrDeprecated = &child; + } continue; } if (Definition::Type::kPunctuation == child.fType) { @@ -1086,7 +1118,7 @@ bool IncludeWriter::populate(BmhParser& bmhParser) { root->clearVisited(); fStart = includeMapper.second.fContentStart; fEnd = includeMapper.second.fContentEnd; - allPassed &= this->populate(&includeMapper.second, root); + allPassed &= this->populate(&includeMapper.second, nullptr, root); this->writeBlock((int) (fEnd - fStart), fStart); fIndent = 0; this->lfcr(); @@ -1409,7 +1441,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data) { case '\'': // possessive apostrophe isn't treated as delimiting punctation case '=': case '!': // assumed not to be punctuation, but a programming symbol - case '&': case '>': case '<': case '{': case '}': case '/': case '*': + case '&': case '>': case '<': case '{': case '}': case '/': case '*': case '[': case ']': word = Word::kMixed; embeddedSymbol = true; break; @@ -1442,6 +1474,10 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data) { } hasSymbol |= embeddedSymbol; break; + case '+': + // hackery to allow C++ + SkASSERT('C' == last || '+' == last); // FIXME: don't allow + outside of #Formula + 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': |