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