aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/bookmaker
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-05-30 09:21:49 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-30 13:46:38 +0000
commit137b87485508e3882968a10559c2cb389dcc93c5 (patch)
tree7f45aec7b2f0252830ef7d417b71e87bfcc9e299 /tools/bookmaker
parent594b64c4851c82597b3a2045062efad42039d461 (diff)
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>
Diffstat (limited to 'tools/bookmaker')
-rw-r--r--tools/bookmaker/bookmaker.cpp66
-rw-r--r--tools/bookmaker/bookmaker.h37
-rw-r--r--tools/bookmaker/definition.cpp23
-rw-r--r--tools/bookmaker/includeParser.cpp17
-rw-r--r--tools/bookmaker/includeWriter.cpp346
-rw-r--r--tools/bookmaker/parserCommon.cpp7
6 files changed, 375 insertions, 121 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index aaf3781974..e773df6da8 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -176,7 +176,7 @@ BmhParser::MarkProps BmhParser::kMarkProps[] = {
, { "Set", MarkType::kSet, R_N, E_N, M(Example) | M(NoExample) }
, { "StdOut", MarkType::kStdOut, R_N, E_N, M(Example) | M(NoExample) }
, { "Struct", MarkType::kStruct, R_Y, E_O, M(Class) | M_ST }
-, { "Substitute", MarkType::kSubstitute, R_N, E_N, M_ST }
+, { "Substitute", MarkType::kSubstitute, R_N, E_N, M(Alias) | M_ST }
, { "Subtopic", MarkType::kSubtopic, R_Y, E_Y, M_CSST }
, { "Table", MarkType::kTable, R_Y, E_N, M(Method) | M_CSST | M_E }
, { "Template", MarkType::kTemplate, R_Y, E_N, M_CSST }
@@ -426,6 +426,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
case MarkType::kDescription:
case MarkType::kStdOut:
// may be one-liner
+ case MarkType::kAlias:
case MarkType::kNoExample:
case MarkType::kParam:
case MarkType::kPhraseDef:
@@ -474,6 +475,19 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
}
fParent->fChildren.push_back(definition);
}
+ if (MarkType::kAlias == markType) {
+ const char* end = definition->fChildren.size() > 0 ?
+ definition->fChildren[0]->fStart : definition->fContentEnd;
+ TextParser parser(definition->fFileName, definition->fContentStart, end,
+ definition->fLineCount);
+ parser.trimEnd();
+ string key = string(parser.fStart, parser.lineLength());
+ if (fAliasMap.end() != fAliasMap.find(key)) {
+ return this->reportError<bool>("duplicate alias");
+ }
+ fAliasMap[key] = definition;
+ definition->fFiddle = definition->fParent->fFiddle;
+ }
break;
} else if (MarkType::kPhraseDef == markType) {
bool hasParams = '(' == this->next();
@@ -563,7 +577,6 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
}
break;
// always treated as one-liners (can't detect misuse easily)
- case MarkType::kAlias:
case MarkType::kAnchor:
case MarkType::kBug:
case MarkType::kDeprecated:
@@ -614,18 +627,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
definition->fContentEnd = link->fContentEnd;
definition->fTerminator = fChar;
definition->fChildren.emplace_back(link);
- } else if (MarkType::kAlias == markType) {
- this->skipWhiteSpace();
- const char* start = fChar;
- this->skipToNonName();
- string alias(start, fChar - start);
- if (fAliasMap.end() != fAliasMap.find(alias)) {
- return this->reportError<bool>("duplicate alias");
- }
- fAliasMap[alias] = definition;
- definition->fFiddle = definition->fParent->fFiddle;
- }
- else if (MarkType::kLine == markType) {
+ } else if (MarkType::kLine == markType) {
const char* nextLF = this->strnchr('\n', this->fEnd);
const char* start = fChar;
const char* end = this->trimmedBracketEnd(fMC);
@@ -663,7 +665,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
fParent->fDetails =
this->skipExact("soon") ? Definition::Details::kSoonToBe_Deprecated :
this->skipExact("testing") ? Definition::Details::kTestingOnly_Experiment :
- this->skipExact("do not use") ? Definition::Details::kDoNotUse_Experiement :
+ this->skipExact("do not use") ? Definition::Details::kDoNotUse_Experiment :
this->skipExact("not ready") ? Definition::Details::kNotReady_Experiment :
Definition::Details::kNone;
this->skipSpace();
@@ -1317,7 +1319,9 @@ bool BmhParser::findDefinitions() {
return this->reportError<bool>("duplicate name");
}
if (hasEnd && expectEnd) {
- SkASSERT(fMC != this->peek());
+ if (fMC == this->peek()) {
+ return this->reportError<bool>("missing body");
+ }
}
if (!this->addDefinition(defStart, hasEnd, markType, typeNameBuilder,
HasTag::kYes)) {
@@ -1847,6 +1851,10 @@ const Definition* BmhParser::parentSpace() const {
return parent;
}
+// A full terminal statement is in the form:
+// \n optional-white-space #MarkType white-space #[# white-space]
+// \n optional-white-space #MarkType white-space Name white-space #[# white-space]
+// MarkType must match definition->fMarkType
const char* BmhParser::checkForFullTerminal(const char* end, const Definition* definition) const {
const char* start = end;
while ('\n' != start[0] && start > fStart) {
@@ -1864,25 +1872,27 @@ const char* BmhParser::checkForFullTerminal(const char* end, const Definition* d
return end;
}
parser.skipWhiteSpace();
- const char* nameStart = parser.fChar;
- if (isupper(nameStart[0])) {
- parser.skipToWhiteSpace();
- if (parser.eof()) {
- return end;
- }
- string defName = string(nameStart, parser.fChar - nameStart);
- size_t defNamePos = definition->fName.rfind(defName);
- if (definition->fName.length() != defNamePos + defName.length()) {
- return end;
+ TextParser startName(fFileName, definition->fStart, definition->fContentStart,
+ definition->fLineCount);
+ if ('#' == startName.next()) {
+ startName.skipToSpace();
+ if (!startName.eof() && startName.skipSpace()) {
+ const char* nameBegin = startName.fChar;
+ startName.skipToWhiteSpace();
+ string name(nameBegin, (int) (startName.fChar - nameBegin));
+ if (fMC != parser.peek() && !parser.skipExact(name.c_str())) {
+ return end;
+ }
+ parser.skipSpace();
}
}
- parser.skipWhiteSpace();
- if (fMC != parser.next()) {
+ if (parser.eof() || fMC != parser.next()) {
return end;
}
if (!parser.eof() && fMC != parser.next()) {
return end;
}
+ SkASSERT(parser.eof());
return start;
}
diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h
index 322aa4c446..1a85621d49 100644
--- a/tools/bookmaker/bookmaker.h
+++ b/tools/bookmaker/bookmaker.h
@@ -811,7 +811,7 @@ public:
kNone,
kSoonToBe_Deprecated,
kTestingOnly_Experiment,
- kDoNotUse_Experiement,
+ kDoNotUse_Experiment,
kNotReady_Experiment,
};
@@ -1107,6 +1107,11 @@ public:
kYes,
};
+ enum class OneLine {
+ kNo,
+ kYes,
+ };
+
ParserCommon() : TextParser()
, fParent(nullptr)
, fDebugOut(false)
@@ -1209,7 +1214,7 @@ public:
SkAssertResult(writeBlockTrim(size, data));
}
- void writeBlockIndent(int size, const char* data);
+ bool writeBlockIndent(int size, const char* data);
void writeBlockSeparator() {
this->writeString(
@@ -1225,7 +1230,12 @@ public:
this->writeSpace();
}
- void writeCommentTrailer() {
+ void writeCommentTrailer(OneLine oneLine) {
+ if (OneLine::kNo == oneLine) {
+ this->lf(1);
+ } else {
+ this->writeSpace();
+ }
this->writeString("*/");
this->lfcr();
}
@@ -2012,6 +2022,11 @@ public:
};
struct Item {
+ void reset() {
+ fName = "";
+ fValue = "";
+ }
+
string fName;
string fValue;
};
@@ -2047,9 +2062,9 @@ public:
bool checkChildCommentLength(const Definition* parent, MarkType childType) const;
void checkEnumLengths(const Definition& child, string enumName, ItemLength* length) const;
- void constOut(const Definition* memberStart, const Definition& child,
- const Definition* bmhConst);
- void descriptionOut(const Definition* def, SkipFirstLine , Phrase );
+ void constOut(const Definition* memberStart, const Definition* bmhConst);
+ void constSizeMembers(const RootDefinition* root);
+ bool descriptionOut(const Definition* def, SkipFirstLine , Phrase );
void enumHeaderOut(RootDefinition* root, const Definition& child);
string enumMemberComment(const Definition* currentEnumItem, const Definition& child) const;
const Definition* enumMemberForComment(const Definition* currentEnumItem) const;
@@ -2080,6 +2095,8 @@ public:
fBmhParser = nullptr;
fEnumDef = nullptr;
fMethodDef = nullptr;
+ fBmhConst = nullptr;
+ fConstDef = nullptr;
fBmhStructDef = nullptr;
fInStruct = false;
fWroteMethod = false;
@@ -2087,6 +2104,7 @@ public:
fPendingMethod = false;
}
+ string resolveAlias(const Definition* );
string resolveMethod(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, Phrase phrase);
@@ -2101,6 +2119,9 @@ private:
const Definition* fBmhMethod;
const Definition* fEnumDef;
const Definition* fMethodDef;
+ const Definition* fBmhConst;
+ const Definition* fConstDef;
+ const Definition* fLastDescription;
Definition* fBmhStructDef;
const char* fContinuation; // used to construct paren-qualified method name
int fAnonymousEnumCount;
@@ -2109,6 +2130,10 @@ private:
int fStructMemberTab;
int fStructValueTab;
int fStructCommentTab;
+ int fStructMemberLength;
+ int fConstValueTab;
+ int fConstCommentTab;
+ int fConstLength;
bool fInStruct;
bool fWroteMethod;
bool fIndentNext;
diff --git a/tools/bookmaker/definition.cpp b/tools/bookmaker/definition.cpp
index 1c6b1ebbe0..18ce808068 100644
--- a/tools/bookmaker/definition.cpp
+++ b/tools/bookmaker/definition.cpp
@@ -814,21 +814,20 @@ bool Definition::hasMatch(string name) const {
}
string Definition::incompleteMessage(DetailsType detailsType) const {
- if (!IncompleteAllowed(fMarkType)) {
- auto iter = std::find_if(fChildren.begin(), fChildren.end(),
- [](const Definition* test) { return IncompleteAllowed(test->fMarkType); });
- SkASSERT(fChildren.end() != iter);
- return (*iter)->incompleteMessage(detailsType);
- }
- string message = MarkType::kExperimental == fMarkType ?
+ SkASSERT(!IncompleteAllowed(fMarkType));
+ auto iter = std::find_if(fChildren.begin(), fChildren.end(),
+ [](const Definition* test) { return IncompleteAllowed(test->fMarkType); });
+ SkASSERT(fChildren.end() != iter);
+ SkASSERT(Details::kNone == (*iter)->fDetails);
+ string message = MarkType::kExperimental == (*iter)->fMarkType ?
"Experimental." : "Deprecated.";
- if (Definition::Details::kDoNotUse_Experiement == fDetails) {
+ if (Details::kDoNotUse_Experiment == fDetails) {
message += " Do not use.";
- } else if (Definition::Details::kNotReady_Experiment == fDetails) {
+ } else if (Details::kNotReady_Experiment == fDetails) {
message += " Not ready for general use.";
- } else if (Definition::Details::kSoonToBe_Deprecated == fDetails) {
- message += " Soon to be deprecated.";
- } else if (Definition::Details::kTestingOnly_Experiment == fDetails) {
+ } else if (Details::kSoonToBe_Deprecated == fDetails) {
+ message = "To be deprecated soon.";
+ } else if (Details::kTestingOnly_Experiment == fDetails) {
message += " For testing only.";
}
if (DetailsType::kPhrase == detailsType) {
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 12bd787eb8..56de4f6f15 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -1276,7 +1276,7 @@ bool IncludeParser::findComments(const Definition& includeDef, Definition* marku
return true;
}
-// caller calls reportError, so just return false here
+// caller just returns, so report error here
bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
SkASSERT(includeDef->fTokens.size() > 0);
// parse class header
@@ -1323,15 +1323,11 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
while (iter != includeDef->fTokens.end()
&& (publicLen != (size_t) (iter->fContentEnd - iter->fStart)
|| strncmp(iter->fStart, publicName, publicLen))) {
+ iter->fPrivate = true;
iter = std::next(iter);
++publicIndex;
}
}
- auto childIter = includeDef->fChildren.begin();
- while (childIter != includeDef->fChildren.end() && (*childIter)->fParentIndex < publicIndex) {
- (*childIter)->fPrivate = true;
- childIter = std::next(childIter);
- }
int keyIndex = publicIndex;
KeyWord currentKey = KeyWord::kPublic;
const char* publicName = kKeyWords[(int) KeyWord::kPublic].fName;
@@ -1340,9 +1336,12 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
size_t protectedLen = strlen(protectedName);
const char* privateName = kKeyWords[(int) KeyWord::kPrivate].fName;
size_t privateLen = strlen(privateName);
+ auto childIter = includeDef->fChildren.begin();
+ std::advance(childIter, publicIndex);
while (childIter != includeDef->fChildren.end()) {
Definition* child = *childIter;
while (child->fParentIndex > keyIndex && iter != includeDef->fTokens.end()) {
+ iter->fPrivate = KeyWord::kPublic != currentKey;
const char* testStart = iter->fStart;
size_t testLen = (size_t) (iter->fContentEnd - testStart);
iter = std::next(iter);
@@ -1365,12 +1364,14 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
if (!this->parseObject(child, markupDef)) {
return false;
}
- } else {
- child->fPrivate = true;
}
fLastObject = child;
childIter = std::next(childIter);
}
+ while (iter != includeDef->fTokens.end()) {
+ iter->fPrivate = KeyWord::kPublic != currentKey;
+ iter = std::next(iter);
+ }
SkASSERT(fParent->fParent);
fParent = fParent->fParent;
return true;
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index 62e8205e3d..f05ef0ece1 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -58,22 +58,24 @@ void IncludeWriter::checkEnumLengths(const Definition& child, string enumName, I
}
}
-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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
prop->fContentEnd - prop->fContentStart) + ')');
this->writeString(bugstr);
this->lfcr();
+ wroteSomething = true;
}
case MarkType::kDeprecated:
case MarkType::kPrivate:
@@ -141,10 +149,11 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
}
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
commentStart = prop->fTerminator;
@@ -190,13 +198,14 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
} 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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
commentStart = prop->fTerminator;
@@ -228,6 +238,7 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart,
Phrase::kNo)) {
this->lfcr();
+ wroteSomething = true;
}
}
for (auto row : prop->fChildren) {
@@ -236,7 +247,7 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
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 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
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 @@ string IncludeWriter::enumMemberComment(const Definition* currentEnumItem,
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 @@ void IncludeWriter::enumMembersOut(Definition& child) {
}
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 @@ void IncludeWriter::methodOut(Definition* method, const Definition& child) {
}
fIndent -= 4;
this->lfcr();
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
fBmhMethod = nullptr;
fMethodDef = nullptr;
fEnumDef = nullptr;
@@ -864,7 +883,7 @@ void IncludeWriter::structOut(const Definition* root, const Definition& child,
}
fIndent -= 4;
this->lfcr();
- this->writeCommentTrailer();
+ this->writeCommentTrailer(OneLine::kNo);
}
bool IncludeWriter::findEnumSubtopic(string undername, const Definition** rootDefPtr) const {
@@ -916,36 +935,18 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
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 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
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 @@ void IncludeWriter::structSizeMembers(const Definition& child) {
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 @@ void IncludeWriter::structSizeMembers(const Definition& child) {
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 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
params.skipToEndBracket('(');
if (params.startsWith(child.fContentStart, childLen)) {
this->methodOut(clonedMethod, child);
+ sawConst = false;
break;
}
++alternate;
@@ -1263,6 +1336,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
return child.reportError<bool>("method not found");
}
this->methodOut(method, child);
+ sawConst = false;
continue;
}
if (Definition::Type::kPunctuation == child.fType &&
@@ -1283,6 +1357,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
continue;
}
this->methodOut(method, child);
+ sawConst = false;
continue;
} else if (fBmhStructDef && fBmhStructDef->fDeprecated) {
fContinuation = nullptr;
@@ -1343,6 +1418,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
continue;
}
this->methodOut(method, child);
+ sawConst = false;
if (fAttrDeprecated) {
startDef = fAttrDeprecated;
fStart = fAttrDeprecated->fContentStart;
@@ -1387,6 +1463,8 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
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 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
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 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
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 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
}
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 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
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 @@ string IncludeWriter::resolveMethod(const char* start, const char* end, bool fir
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 @@ string IncludeWriter::resolveMethod(const char* start, const char* end, bool fir
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 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
}
}
}
+ 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 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
}
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 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
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 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
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);
}
}
diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp
index 3733aed366..652df53e51 100644
--- a/tools/bookmaker/parserCommon.cpp
+++ b/tools/bookmaker/parserCommon.cpp
@@ -102,7 +102,8 @@ bool ParserCommon::parseSetup(const char* path) {
return true;
}
-void ParserCommon::writeBlockIndent(int size, const char* data) {
+bool ParserCommon::writeBlockIndent(int size, const char* data) {
+ bool wroteSomething = false;
while (size && ' ' >= data[size - 1]) {
--size;
}
@@ -113,7 +114,7 @@ void ParserCommon::writeBlockIndent(int size, const char* data) {
--size;
}
if (!size) {
- return;
+ return wroteSomething;
}
if (newLine) {
this->lf(1);
@@ -130,7 +131,9 @@ void ParserCommon::writeBlockIndent(int size, const char* data) {
size -= len;
data += len;
newLine = true;
+ wroteSomething = true;
}
+ return wroteSomething;
}
bool ParserCommon::writeBlockTrim(int size, const char* data) {