generate include comments
- formalize how aliases and substitutions work together
- add constexpr, #define, typedef support
- check for correct description order
- write short enum, struct members
R=caryclark@google.com
Docs-Preview: https://skia.org/?cl=129455
Bug: skia:6898
Change-Id: Id60fc2ed02f38a7ba4e5cad5ef493d8c674e6183
Reviewed-on: https://skia-review.googlesource.com/129455
Commit-Queue: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index 62e8205..f05ef0e 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -58,22 +58,24 @@
}
}
-void IncludeWriter::constOut(const Definition* memberStart, const Definition& child,
- const Definition* bmhConst) {
+void IncludeWriter::constOut(const Definition* memberStart, const Definition* bmhConst) {
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
memberStart->fContentStart;
this->writeBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
this->lf(2);
this->writeCommentHeader();
fIndent += 4;
- this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo);
+ if (!this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo)) {
+ return memberStart->reportError<void>("expected description for const");
+ }
fIndent -= 4;
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
fStart = memberStart->fContentStart;
}
-void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine,
+bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine,
Phrase phrase) {
+ bool wroteSomething = false;
const char* commentStart = def->fContentStart;
if (SkipFirstLine::kYes == skipFirstLine) {
TextParser parser(def);
@@ -87,8 +89,12 @@
string message = def->incompleteMessage(Definition::DetailsType::kSentence);
this->writeString(message);
this->lfcr();
+ wroteSomething = true;
}
+ const Definition* lastDescription = def;
for (auto prop : def->fChildren) {
+ fLastDescription = lastDescription;
+ lastDescription = prop;
switch (prop->fMarkType) {
case MarkType::kCode: {
bool literal = false;
@@ -98,6 +104,7 @@
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lf(2);
+ wroteSomething = true;
}
}
size_t childSize = prop->fChildren.size();
@@ -116,14 +123,14 @@
if (!literalOutdent) {
fIndent += 4;
}
- this->writeBlockIndent(commentLen, commentStart);
+ wroteSomething |= this->writeBlockIndent(commentLen, commentStart);
this->lf(2);
if (!literalOutdent) {
fIndent -= 4;
}
- commentStart = prop->fTerminator;
SkDEBUGCODE(wroteCode = true);
}
+ commentStart = prop->fTerminator;
} break;
case MarkType::kDefinedBy:
commentStart = prop->fTerminator;
@@ -133,6 +140,7 @@
prop->fContentEnd - prop->fContentStart) + ')');
this->writeString(bugstr);
this->lfcr();
+ wroteSomething = true;
}
case MarkType::kDeprecated:
case MarkType::kPrivate:
@@ -141,10 +149,11 @@
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
commentStart = prop->fContentStart;
- if (' ' < commentStart[0]) {
+ if (MarkType::kPrivate != prop->fMarkType && ' ' < commentStart[0]) {
commentStart = strchr(commentStart, '\n');
}
if (MarkType::kBug == prop->fMarkType) {
@@ -152,7 +161,7 @@
}
commentLen = (int) (prop->fContentEnd - commentStart);
if (commentLen > 0) {
- this->writeBlockIndent(commentLen, commentStart);
+ wroteSomething |= this->writeBlockIndent(commentLen, commentStart);
const char* end = commentStart + commentLen;
while (end > commentStart && ' ' == end[-1]) {
--end;
@@ -165,8 +174,6 @@
commentLen = (int) (def->fContentEnd - commentStart);
break;
case MarkType::kExperimental:
- this->writeString("EXPERIMENTAL:");
- this->writeSpace();
commentStart = prop->fContentStart;
if (' ' < commentStart[0]) {
commentStart = strchr(commentStart, '\n');
@@ -175,6 +182,7 @@
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
commentStart = prop->fTerminator;
@@ -190,13 +198,14 @@
} else {
this->writeSpace();
}
+ wroteSomething = true;
}
}
int saveIndent = fIndent;
if (fIndent < fColumn + 1) {
fIndent = fColumn + 1;
}
- this->writeBlockIndent(prop->length(), prop->fContentStart);
+ wroteSomething |= this->writeBlockIndent(prop->length(), prop->fContentStart);
fIndent = saveIndent;
commentStart = prop->fTerminator;
commentLen = (int) (def->fContentEnd - commentStart);
@@ -217,6 +226,7 @@
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
commentStart = prop->fTerminator;
@@ -228,6 +238,7 @@
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart,
Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
for (auto row : prop->fChildren) {
@@ -236,7 +247,7 @@
SkASSERT(MarkType::kColumn == column->fMarkType);
this->writeString("-");
this->writeSpace();
- this->descriptionOut(column, SkipFirstLine::kNo, Phrase::kNo);
+ wroteSomething |= this->descriptionOut(column, SkipFirstLine::kNo, Phrase::kNo);
this->lf(1);
}
}
@@ -252,10 +263,11 @@
this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
// ince we don't do line wrapping, always insert LF before phrase
this->lfcr(); // TODO: remove this once rewriteBlock rewraps paragraphs
+ wroteSomething = true;
}
auto iter = fBmhParser->fPhraseMap.find(prop->fName);
if (fBmhParser->fPhraseMap.end() == iter) {
- return this->reportError<void>("missing phrase definition");
+ return this->reportError<bool>("missing phrase definition");
}
Definition* phraseDef = iter->second;
// TODO: given TextParser(commentStart, prop->fStart + up to #) return if
@@ -289,12 +301,16 @@
this->writeSpace();
}
defIsPhrase = Phrase::kYes;
+ wroteSomething = true;
}
if (length > 0) {
this->rewriteBlock(length, start, defIsPhrase);
}
commentStart = prop->fContentStart;
commentLen = (int) (def->fContentEnd - commentStart);
+ if ('\n' == commentStart[0] && '\n' == commentStart[1]) {
+ this->lf(2);
+ }
} break;
default:
commentLen = (int) (prop->fStart - commentStart);
@@ -307,7 +323,9 @@
SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500) || def->fDeprecated);
if (commentLen > 0) {
this->rewriteBlock(commentLen, commentStart, phrase);
+ wroteSomething = true;
}
+ return wroteSomething;
}
void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child) {
@@ -435,7 +453,7 @@
if (wroteHeader) {
fIndent -= 4;
this->lfcr();
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
}
Definition* braceHolder = child.fChildren[0];
if (KeyWord::kClass == braceHolder->fKeyWord) {
@@ -474,7 +492,7 @@
break;
}
if (IncompleteAllowed(constItem->fMarkType)) {
- shortComment = constItem->incompleteMessage(Definition::DetailsType::kPhrase);
+ shortComment = constItem->fParent->incompleteMessage(Definition::DetailsType::kPhrase);
}
}
if (!shortComment.length()) {
@@ -617,6 +635,7 @@
}
if (ItemState::kNone != state) {
this->enumMemberOut(currentEnumItem, child, item, preprocessor);
+ item.reset();
fStart = token.fContentStart;
state = ItemState::kNone;
last.fStart = nullptr;
@@ -840,7 +859,7 @@
}
fIndent -= 4;
this->lfcr();
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
fBmhMethod = nullptr;
fMethodDef = nullptr;
fEnumDef = nullptr;
@@ -864,7 +883,7 @@
}
fIndent -= 4;
this->lfcr();
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
}
bool IncludeWriter::findEnumSubtopic(string undername, const Definition** rootDefPtr) const {
@@ -916,36 +935,18 @@
string name(child.fContentStart, (int) (child.fContentEnd - child.fContentStart));
Definition* commentBlock = this->findMemberCommentBlock(fBmhStructDef->fChildren, name);
if (!commentBlock) {
- return memberStart->reportError<Definition*>("member missing comment block");
+ return memberStart->reportError<Definition*>("member missing comment block 2");
}
-#if 0
- if (!commentBlock->fShort) {
- const char* commentStart = commentBlock->fContentStart;
- ptrdiff_t commentLen = commentBlock->fContentEnd - commentStart;
+ auto lineIter = std::find_if(commentBlock->fChildren.begin(), commentBlock->fChildren.end(),
+ [](const Definition* def){ return MarkType::kLine == def->fMarkType; } );
+ SkASSERT(commentBlock->fChildren.end() != lineIter);
+ const Definition* lineDef = *lineIter;
+ if (fStructMemberLength > 100) {
this->writeCommentHeader();
- bool wroteLineFeed = false;
- fIndent += 4;
- for (auto child : commentBlock->fChildren) {
- commentLen = child->fStart - commentStart;
- wroteLineFeed |= Wrote::kLF == this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
- if (MarkType::kFormula == child->fMarkType) {
- this->writeSpace();
- this->writeBlock((int) (child->fContentEnd - child->fContentStart),
- child->fContentStart);
- }
- commentStart = child->fTerminator;
- }
- commentLen = commentBlock->fContentEnd - commentStart;
- wroteLineFeed |= Wrote::kLF == this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
- fIndent -= 4;
- if (wroteLineFeed || fColumn > 100 - 3 /* space * / */ ) {
- this->lfcr();
- } else {
- this->writeSpace();
- }
- this->writeCommentTrailer();
+ this->writeSpace();
+ this->rewriteBlock(lineDef->length(), lineDef->fContentStart, Phrase::kYes);
+ this->writeCommentTrailer(OneLine::kYes);
}
-#endif
this->lfcr();
this->writeBlock((int) (child.fStart - memberStart->fContentStart),
memberStart->fContentStart);
@@ -967,22 +968,80 @@
valueStart->fContentStart);
}
this->writeString(";");
- /* if (commentBlock->fShort) */ {
+ if (fStructMemberLength <= 100) {
this->indentToColumn(fStructCommentTab);
this->writeString("//!<");
this->writeSpace();
- string extract = fBmhParser->extractText(commentBlock, BmhParser::TrimExtract::kYes);
- this->rewriteBlock(extract.length(), &extract.front(), Phrase::kNo);
+ this->rewriteBlock(lineDef->length(), lineDef->fContentStart, Phrase::kYes);
}
- this->lf(2);
+ this->lf(1);
return valueEnd;
}
+// const and constexpr and #define aren't contained in a braces like struct and enum.
+// use a bmh subtopic to group like ones together, then measure them in the include as if
+// they were formally linked together
+void IncludeWriter::constSizeMembers(const RootDefinition* root) {
+ // fBmhConst->fParent is subtopic containing all grouped const expressions
+ // fConstDef is token of const include name, hopefully on same line as const start
+ string rootPrefix = root ? root->fName + "::" : "";
+ const Definition* test = fConstDef;
+ int tokenIndex = test->fParentIndex;
+ int longestName = 0;
+ int longestValue = 0;
+ int longestComment = 0;
+ const Definition* subtopic = fBmhConst->fParent;
+ SkASSERT(subtopic);
+ SkASSERT(MarkType::kSubtopic == subtopic->fMarkType);
+ // back up to first token on line
+ size_t lineCount = test->fLineCount;
+ const Definition* last;
+ auto tokenIter = test->fParent->fTokens.begin();
+ std::advance(tokenIter, tokenIndex);
+ do {
+ last = test;
+ std::advance(tokenIter, -1);
+ test = &*tokenIter;
+ SkASSERT(test->fParentIndex == --tokenIndex);
+ } while (lineCount == test->fLineCount);
+ test = last;
+ for (auto child : subtopic->fChildren) {
+ if (MarkType::kConst != child->fMarkType) {
+ continue;
+ }
+ // expect found name to be on the left of assign
+ // expect assign
+ // expect semicolon
+ // no parens, no braces
+ while (rootPrefix + test->fName != child->fName) {
+ std::advance(tokenIter, 1);
+ test = &*tokenIter;
+ SkASSERT(lineCount >= test->fLineCount);
+ }
+ ++lineCount;
+ TextParser constText(test);
+ const char* nameEnd = constText.trimmedBracketEnd('=');
+ SkAssertResult(constText.skipToEndBracket('='));
+ const char* valueEnd = constText.trimmedBracketEnd(';');
+ auto lineIter = std::find_if(child->fChildren.begin(), child->fChildren.end(),
+ [](const Definition* def){ return MarkType::kLine == def->fMarkType; });
+ SkASSERT(child->fChildren.end() != lineIter);
+ longestName = SkTMax(longestName, (int) (nameEnd - constText.fStart));
+ longestValue = SkTMax(longestValue, (int) (valueEnd - constText.fChar));
+ longestComment = SkTMax(longestComment, (*lineIter)->length());
+ }
+ // write fStructValueTab, fStructCommentTab
+ fConstValueTab = longestName + fIndent + 1;
+ fConstCommentTab = fConstValueTab + longestValue + 2;
+ fConstLength = fConstCommentTab + longestComment + (int) sizeof("//!<");
+}
+
void IncludeWriter::structSizeMembers(const Definition& child) {
int longestType = 0;
Definition* typeStart = nullptr;
int longestName = 0;
int longestValue = 0;
+ int longestComment = 0;
SkASSERT(child.fChildren.size() == 1 || child.fChildren.size() == 2);
bool inEnum = false;
bool inMethod = false;
@@ -1066,6 +1125,18 @@
longestName = SkTMax(longestName, (int) (token.fContentEnd - token.fContentStart));
typeStart->fMemberStart = true;
inMember = true;
+ string tokenName(token.fContentStart, (int) (token.fContentEnd - token.fContentStart));
+ Definition* commentBlock = this->findMemberCommentBlock(fBmhStructDef->fChildren,
+ tokenName);
+ if (!commentBlock) {
+ return token.reportError<void>("member missing comment block 1");
+ }
+ auto lineIter = std::find_if(commentBlock->fChildren.begin(),
+ commentBlock->fChildren.end(),
+ [](const Definition* def){ return MarkType::kLine == def->fMarkType; } );
+ SkASSERT(commentBlock->fChildren.end() != lineIter);
+ const Definition* lineDef = *lineIter;
+ longestComment = SkTMax(longestComment, lineDef->length());
continue;
}
if (MarkType::kMethod == token.fMarkType) {
@@ -1089,6 +1160,7 @@
fStructCommentTab += longestValue + 3 /* space = space */ ;
fStructValueTab -= 1 /* ; */ ;
}
+ fStructMemberLength = fStructCommentTab + longestComment;
// iterate through struct to ensure that members' comments fit on line
// struct or class may not have any members
(void) this->checkChildCommentLength(fBmhStructDef, MarkType::kMember);
@@ -1218,6 +1290,7 @@
params.skipToEndBracket('(');
if (params.startsWith(child.fContentStart, childLen)) {
this->methodOut(clonedMethod, child);
+ sawConst = false;
break;
}
++alternate;
@@ -1263,6 +1336,7 @@
return child.reportError<bool>("method not found");
}
this->methodOut(method, child);
+ sawConst = false;
continue;
}
if (Definition::Type::kPunctuation == child.fType &&
@@ -1283,6 +1357,7 @@
continue;
}
this->methodOut(method, child);
+ sawConst = false;
continue;
} else if (fBmhStructDef && fBmhStructDef->fDeprecated) {
fContinuation = nullptr;
@@ -1343,6 +1418,7 @@
continue;
}
this->methodOut(method, child);
+ sawConst = false;
if (fAttrDeprecated) {
startDef = fAttrDeprecated;
fStart = fAttrDeprecated->fContentStart;
@@ -1387,6 +1463,8 @@
name = child.fName;
} else if (1 == trial) {
name = root->fName + "::" + child.fName;
+ } else if (2 == trial) {
+ name = root->fName;
} else {
SkASSERT(parent);
name = parent->fName + "::" + child.fName;
@@ -1451,11 +1529,12 @@
continue;
}
#endif
+ Definition* priorBlock = fBmhStructDef;
Definition* codeBlock = nullptr;
Definition* nextBlock = nullptr;
for (auto test : fBmhStructDef->fChildren) {
if (MarkType::kCode == test->fMarkType) {
- SkASSERT(!codeBlock); // FIXME: check enum for correct order earlier
+ SkASSERT(!codeBlock); // FIXME: check enum earlier
codeBlock = test;
continue;
}
@@ -1463,13 +1542,34 @@
nextBlock = test;
break;
}
+ priorBlock = test;
}
- // FIXME: trigger error earlier if inner #Struct or #Class is missing #Code
+ // FIXME: trigger error earlier if inner #Struct or #Class is missing #Code
if (!fBmhStructDef->fDeprecated) {
SkASSERT(codeBlock);
SkASSERT(nextBlock); // FIXME: check enum for correct order earlier
const char* commentStart = codeBlock->fTerminator;
const char* commentEnd = nextBlock->fStart;
+ // FIXME: trigger error if #Code is present but comment is before it earlier
+ SkASSERT(priorBlock); // code always preceded by #Line (I think)
+ TextParser priorComment(priorBlock->fFileName,
+ priorBlock->fTerminator, codeBlock->fStart,
+ priorBlock->fLineCount);
+ priorComment.trimEnd();
+ if (!priorComment.eof()) {
+ return priorBlock->reportError<bool>(
+ "expect no comment before #Code");
+ }
+ TextParser nextComment(codeBlock->fFileName, commentStart,
+ commentEnd, codeBlock->fLineCount);
+ nextComment.trimEnd();
+ if (!priorComment.eof()) {
+ return priorBlock->reportError<bool>(
+ "expect comment after #Code");
+ }
+ if (!nextComment.eof()) {
+
+ }
fIndentNext = true;
this->structOut(root, *fBmhStructDef, commentStart, commentEnd);
}
@@ -1632,10 +1732,33 @@
}
}
if (bmhConst) {
- this->constOut(memberStart, child, bmhConst);
+ this->constOut(memberStart, bmhConst);
fDeferComment = nullptr;
sawConst = false;
}
+ } else if (MarkType::kNone == child.fMarkType && sawConst && !fEnumDef) {
+ string match;
+ if (root) {
+ match = root->fName + "::";
+ match += string(child.fContentStart, child.fContentEnd - child.fContentStart);
+ auto bmhClassIter = fBmhParser->fClassMap.find(root->fName);
+ if (fBmhParser->fClassMap.end() != bmhClassIter) {
+ RootDefinition& bmhClass = bmhClassIter->second;
+ auto constIter = std::find_if(bmhClass.fLeaves.begin(), bmhClass.fLeaves.end(),
+ [match](std::pair<const string, Definition>& leaf){ return match == leaf.second.fName; } );
+ if (bmhClass.fLeaves.end() != constIter) {
+ const Definition& bmhConst = constIter->second;
+ if (MarkType::kConst == bmhConst.fMarkType
+ && MarkType::kSubtopic == bmhConst.fParent->fMarkType) {
+ fBmhConst = &bmhConst;
+ fConstDef = &child;
+ }
+ }
+ }
+ } else {
+ SkDebugf(""); // FIXME: support global constexpr
+ }
+
}
if (child.fMemberStart) {
memberStart = &child;
@@ -1649,8 +1772,59 @@
}
if (Definition::Type::kPunctuation == child.fType) {
if (Punctuation::kSemicolon == child.fPunctuation) {
+ if (sawConst && fBmhConst) { // find bmh documentation. Parent must be subtopic.
+ const Definition* subtopic = fBmhConst->fParent;
+ SkASSERT(subtopic);
+ SkASSERT(MarkType::kSubtopic == subtopic->fMarkType);
+ auto firstConst = std::find_if(subtopic->fChildren.begin(),
+ subtopic->fChildren.end(),
+ [](const Definition* def){ return MarkType::kConst == def->fMarkType;});
+ SkASSERT(firstConst != subtopic->fChildren.end());
+ bool constIsFirst = *firstConst == fBmhConst;
+ if (constIsFirst) { // If first #Const child, output subtopic description.
+ this->constOut(memberStart, subtopic);
+ // find member / value / comment tabs
+ // look for a one-to-one correspondence between bmh and include
+ this->constSizeMembers(root);
+ }
+ const char* blockStart = fDeferComment ? fLastComment->fContentEnd : fStart;
+ const char* blockEnd = fDeferComment ? fDeferComment->fStart - 1 :
+ memberStart->fStart;
+ this->writeBlockTrim((int) (blockEnd - blockStart), blockStart);
+ // after const code, output #Line description as short comment
+ auto lineIter = std::find_if(fBmhConst->fChildren.begin(),
+ fBmhConst->fChildren.end(),
+ [](const Definition* def){ return MarkType::kLine == def->fMarkType; });
+ SkASSERT(fBmhConst->fChildren.end() != lineIter);
+ const Definition* lineDef = *lineIter;
+ if (fConstLength > 100) {
+ this->writeCommentHeader();
+ this->writeSpace();
+ this->rewriteBlock(lineDef->length(), lineDef->fContentStart, Phrase::kYes);
+ this->writeCommentTrailer(OneLine::kYes);
+ }
+ this->lfcr();
+ TextParser constText(memberStart);
+ const char* nameEnd = constText.trimmedBracketEnd('=');
+ SkAssertResult(constText.skipToEndBracket('='));
+ const char* valueEnd = constText.trimmedBracketEnd(';');
+ this->writeBlock((int) (nameEnd - memberStart->fContentStart),
+ memberStart->fContentStart);
+ this->indentToColumn(fConstValueTab);
+ this->writeBlock((int) (valueEnd - constText.fChar), constText.fChar);
+ this->writeString(";");
+ if (fConstLength <= 100) {
+ this->indentToColumn(fConstCommentTab);
+ this->writeString("//!<");
+ this->writeSpace();
+ this->rewriteBlock(lineDef->length(), lineDef->fContentStart, Phrase::kYes);
+ }
+ fStart = child.fContentStart + 1;
+ fDeferComment = nullptr;
+ fBmhConst = nullptr;
+ sawConst = false;
+ }
memberStart = nullptr;
- sawConst = false;
staticOnly = false;
if (inStruct) {
fInStruct = false;
@@ -1763,6 +1937,25 @@
RootDefinition::AllowParens::kNo);
if (defRef && MarkType::kMethod == defRef->fMarkType) {
substitute = methodname + "()";
+ } else {
+ auto defineIter = fBmhParser->fDefineMap.find(methodname);
+ if (fBmhParser->fDefineMap.end() != defineIter) {
+ const RootDefinition& defineDef = defineIter->second;
+ auto codeIter = std::find_if(defineDef.fChildren.begin(),
+ defineDef.fChildren.end(),
+ [](Definition* child){ return MarkType::kCode == child->fMarkType; } );
+ if (defineDef.fChildren.end() != codeIter) {
+ const Definition* codeDef = *codeIter;
+ string codeContents(codeDef->fContentStart, codeDef->length());
+ size_t namePos = codeContents.find(methodname);
+ if (string::npos != namePos) {
+ size_t parenPos = namePos + methodname.length();
+ if (parenPos < codeContents.length() && '(' == codeContents[parenPos]) {
+ substitute = methodname + "()";
+ }
+ }
+ }
+ }
}
}
if (fMethodDef && methodname == fMethodDef->fName) {
@@ -1783,6 +1976,18 @@
return substitute;
}
+string IncludeWriter::resolveAlias(const Definition* def) {
+ for (auto child : def->fChildren) {
+ if (MarkType::kSubstitute == child->fMarkType) {
+ return string(child->fContentStart, (int) (child->fContentEnd - child->fContentStart));
+ }
+ if (MarkType::kAlias == child->fMarkType && def->fName == child->fName) {
+ return this->resolveAlias(child);
+ }
+ }
+ return "";
+}
+
string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
RefType* refType) {
// look up Xxx_Xxx
@@ -1820,6 +2025,9 @@
}
}
}
+ if (!rootDef && fEnumDef && "Sk" + prefixedName == fEnumDef->fFiddle) {
+ rootDef = fEnumDef;
+ }
if (!rootDef && !substitute.length()) {
auto aliasIter = fBmhParser->fAliasMap.find(undername);
if (fBmhParser->fAliasMap.end() != aliasIter) {
@@ -1837,17 +2045,9 @@
}
if (rootDef) {
MarkType rootType = rootDef->fMarkType;
- bool isTopic = MarkType::kSubtopic == rootType || MarkType::kTopic == rootType;
- auto substituteParent = MarkType::kAlias == rootType ? rootDef->fParent :
- isTopic ? rootDef : nullptr;
- if (substituteParent) {
- for (auto child : substituteParent->fChildren) {
- if (MarkType::kSubstitute == child->fMarkType) {
- substitute = string(child->fContentStart,
- (int) (child->fContentEnd - child->fContentStart));
- break;
- }
- }
+ if (MarkType::kSubtopic == rootType || MarkType::kTopic == rootType
+ || MarkType::kAlias == rootType) {
+ substitute = this->resolveAlias(rootDef);
}
if (!substitute.length()) {
string match = rootDef->fName;
@@ -1856,7 +2056,7 @@
match.erase(index, 1);
}
string skmatch = "Sk" + match;
- auto parent = substituteParent ? substituteParent : rootDef;
+ auto parent = MarkType::kAlias == rootType ? rootDef->fParent : rootDef;
for (auto child : parent->fChildren) {
// there may be more than one
// prefer the one mostly closely matching in text
@@ -1910,6 +2110,22 @@
substitute += ' ';
substitute += ConvertRef(rootDef->fName, false);
} else {
+ size_t underpos = undername.find('_');
+ if (string::npos != underpos) {
+ string parentName = undername.substr(0, underpos);
+ string skName = "Sk" + parentName;
+ if (skName == parent->fName) {
+ SkASSERT(start >= fLastDescription->fContentStart);
+ string lastDescription = string(fLastDescription->fContentStart,
+ (int) (start - fLastDescription->fContentStart));
+ size_t lineStart = lastDescription.rfind('\n');
+ SkASSERT(string::npos != lineStart);
+ fLine = fLastDescription->fContentStart + lineStart + 1;
+ fChar = start;
+ fEnd = end;
+ return this->reportError<string>("remove underline");
+ }
+ }
substitute += ConvertRef(undername, first);
}
}