aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/bookmaker
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-06-07 09:59:07 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-07 14:22:38 +0000
commit0d225395faf27690c724619af35243985bf6e2df (patch)
tree4d5486c91ab2eeb52861030a8b0e7dc23c7e451f /tools/bookmaker
parentd07dc361bccbb0d1b07f47de42aceca3cff5c39c (diff)
generate SkColor include
bookmaker can now generate SkColor.h This required adding support for #define, typedef, global constexpr, and fixing various bugs, like forward declared structs between comments. Docs-Preview: https://skia.org/?cl=131260 Bug: skia:6898 TBR=caryclark@google.com Change-Id: I6bee0c6f5c3a6820b04472a318abde8a2523dbbb Reviewed-on: https://skia-review.googlesource.com/131260 Reviewed-by: Cary Clark <caryclark@skia.org> Commit-Queue: Cary Clark <caryclark@skia.org> Auto-Submit: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'tools/bookmaker')
-rw-r--r--tools/bookmaker/bookmaker.cpp12
-rw-r--r--tools/bookmaker/bookmaker.h226
-rw-r--r--tools/bookmaker/includeParser.cpp207
-rw-r--r--tools/bookmaker/includeWriter.cpp454
-rw-r--r--tools/bookmaker/mdOut.cpp2
-rw-r--r--tools/bookmaker/parserCommon.cpp15
-rw-r--r--tools/bookmaker/spellCheck.cpp2
7 files changed, 569 insertions, 349 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index e773df6da8..794e2007e8 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -145,6 +145,7 @@ BmhParser::MarkProps BmhParser::kMarkProps[] = {
, { "Example", MarkType::kExample, R_O, E_N, M_CSST | M_E | M_MD }
, { "Experimental", MarkType::kExperimental, R_Y, E_N, M_CS | M_MDCM | M_E }
, { "External", MarkType::kExternal, R_Y, E_N, 0 }
+, { "File", MarkType::kFile, R_Y, E_N, M(Topic) }
, { "Formula", MarkType::kFormula, R_F, E_N, M(Column) | M(Description)
| M_E | M_ST | M_MDCM }
, { "Function", MarkType::kFunction, R_O, E_N, M(Example) | M(NoExample) }
@@ -523,6 +524,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
// not one-liners
case MarkType::kCode:
case MarkType::kExample:
+ case MarkType::kFile:
case MarkType::kFormula:
case MarkType::kFunction:
case MarkType::kLegend:
@@ -1242,6 +1244,15 @@ void BmhParser::setWrapper(Definition* def) const {
}
}
+RootDefinition* BmhParser::findBmhObject(MarkType markType, string typeName) {
+ const auto& mapIter = std::find_if(fMaps.begin(), fMaps.end(),
+ [markType](DefinitionMap& defMap){ return markType == defMap.fMarkType; } );
+ if (mapIter == fMaps.end()) {
+ return nullptr;
+ }
+ return &(*mapIter->fMap)[typeName];
+}
+
// FIXME: some examples may produce different output on different platforms
// if the text output can be different, think of how to author that
@@ -2211,6 +2222,7 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kDetails:
case MarkType::kDuration:
case MarkType::kExperimental:
+ case MarkType::kFile:
case MarkType::kHeight:
case MarkType::kIllustration:
case MarkType::kImage:
diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h
index 1a85621d49..c727983c0f 100644
--- a/tools/bookmaker/bookmaker.h
+++ b/tools/bookmaker/bookmaker.h
@@ -72,6 +72,7 @@ enum class KeyWord {
kStruct,
kTemplate,
kTypedef,
+ kTypename,
kUint16_t,
kUint32_t,
kUint64_t,
@@ -103,6 +104,7 @@ enum class MarkType {
kExample,
kExperimental,
kExternal,
+ kFile,
kFormula,
kFunction,
kHeight,
@@ -1112,10 +1114,31 @@ public:
kYes,
};
+ enum class IndentKind {
+ kConstOut,
+ kEnumChild,
+ kEnumChild2,
+ kEnumHeader,
+ kEnumHeader2,
+ kMethodOut,
+ kStructMember,
+ };
+
+ struct IndentState {
+ IndentState(IndentKind kind, int indent)
+ : fKind(kind)
+ , fIndent(indent) {
+ }
+
+ IndentKind fKind;
+ int fIndent;
+ };
+
ParserCommon() : TextParser()
, fParent(nullptr)
, fDebugOut(false)
, fValidate(false)
+ , fReturnOnWrite(false)
{
}
@@ -1127,8 +1150,21 @@ public:
fParent = def;
}
+ void indentIn(IndentKind kind) {
+ fIndent += 4;
+ fIndentStack.emplace_back(kind, fIndent);
+ }
+
+ void indentOut() {
+ SkASSERT(fIndent >= 4);
+ SkASSERT(fIndentStack.back().fIndent == fIndent);
+ fIndent -= 4;
+ fIndentStack.pop_back();
+ }
+
void indentToColumn(int column) {
SkASSERT(column >= fColumn);
+ SkASSERT(!fReturnOnWrite);
if (fDebugOut) {
SkDebugf("%*s", column - fColumn, "");
}
@@ -1165,6 +1201,7 @@ public:
}
void nl() {
+ SkASSERT(!fReturnOnWrite);
fLinefeeds = 0;
fSpaces = 0;
fColumn = 0;
@@ -1245,6 +1282,7 @@ public:
// 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) {
+ SkASSERT(!fReturnOnWrite);
SkASSERT(!fPendingLF);
SkASSERT(!fLinefeeds);
SkASSERT(fColumn > 0);
@@ -1262,6 +1300,7 @@ public:
unordered_map<string, sk_sp<SkData>> fRawData;
unordered_map<string, vector<char>> fLFOnly;
+ vector<IndentState> fIndentStack;
Definition* fParent;
FILE* fOut;
int fLinefeeds; // number of linefeeds last written, zeroed on non-space
@@ -1276,6 +1315,7 @@ public:
bool fValidate; // set true to check anchor defs and refs
bool fOutdentNext; // set at end of embedded struct to prevent premature outdent
bool fWroteSomething; // used to detect empty content; an alternative source is preferable
+ bool fReturnOnWrite; // used to detect non-empty content; allowing early return
private:
typedef TextParser INHERITED;
@@ -1351,67 +1391,14 @@ public:
BmhParser(bool skip) : ParserCommon()
, fMaps {
- { nullptr, MarkType::kNone }
- , { nullptr, MarkType::kAnchor }
- , { nullptr, MarkType::kAlias }
- , { nullptr, MarkType::kBug }
- , { &fClassMap, MarkType::kClass }
- , { nullptr, MarkType::kCode }
- , { nullptr, MarkType::kColumn }
- , { nullptr, MarkType::kComment }
+ { &fClassMap, MarkType::kClass }
, { &fConstMap, MarkType::kConst }
, { &fDefineMap, MarkType::kDefine }
- , { nullptr, MarkType::kDefinedBy }
- , { nullptr, MarkType::kDeprecated }
- , { nullptr, MarkType::kDescription }
- , { nullptr, MarkType::kDetails }
- , { nullptr, MarkType::kDuration }
, { &fEnumMap, MarkType::kEnum }
, { &fClassMap, MarkType::kEnumClass }
- , { nullptr, MarkType::kExample }
- , { nullptr, MarkType::kExperimental }
- , { nullptr, MarkType::kExternal }
- , { nullptr, MarkType::kFormula }
- , { nullptr, MarkType::kFunction }
- , { nullptr, MarkType::kHeight }
- , { nullptr, MarkType::kIllustration }
- , { nullptr, MarkType::kImage }
- , { nullptr, MarkType::kIn }
- , { nullptr, MarkType::kLegend }
- , { nullptr, MarkType::kLine }
- , { nullptr, MarkType::kLink }
- , { nullptr, MarkType::kList }
- , { nullptr, MarkType::kLiteral }
- , { nullptr, MarkType::kMarkChar }
- , { nullptr, MarkType::kMember }
, { &fMethodMap, MarkType::kMethod }
- , { nullptr, MarkType::kNoExample }
- , { nullptr, MarkType::kNoJustify }
- , { nullptr, MarkType::kOutdent }
- , { nullptr, MarkType::kParam }
- , { nullptr, MarkType::kPhraseDef }
- , { nullptr, MarkType::kPhraseParam }
- , { nullptr, MarkType::kPhraseRef }
- , { nullptr, MarkType::kPlatform }
- , { nullptr, MarkType::kPopulate }
- , { nullptr, MarkType::kPrivate }
- , { nullptr, MarkType::kReturn }
- , { nullptr, MarkType::kRow }
- , { nullptr, MarkType::kSeeAlso }
- , { nullptr, MarkType::kSet }
- , { nullptr, MarkType::kStdOut }
, { &fClassMap, MarkType::kStruct }
- , { nullptr, MarkType::kSubstitute }
- , { nullptr, MarkType::kSubtopic }
- , { nullptr, MarkType::kTable }
- , { nullptr, MarkType::kTemplate }
- , { nullptr, MarkType::kText }
- , { nullptr, MarkType::kToDo }
- , { nullptr, MarkType::kTopic }
, { &fTypedefMap, MarkType::kTypedef }
- , { nullptr, MarkType::kUnion }
- , { nullptr, MarkType::kVolatile }
- , { nullptr, MarkType::kWidth }
}
, fSkip(skip) {
this->reset();
@@ -1434,15 +1421,7 @@ public:
bool endTableColumn(const char* end, const char* terminator);
bool exampleToScript(Definition*, ExampleOptions, string* result ) const;
string extractText(const Definition* , TrimExtract ) const;
-
- RootDefinition* findBmhObject(MarkType markType, string typeName) const {
- auto map = fMaps[(int) markType].fMap;
- if (!map) {
- return nullptr;
- }
- return &(*map)[typeName];
- }
-
+ RootDefinition* findBmhObject(MarkType markType, string typeName);
bool findDefinitions();
Definition* findExample(string name) const;
MarkType getMarkType(MarkLookup lookup) const;
@@ -1505,7 +1484,7 @@ public:
MarkType fMarkType;
};
- DefinitionMap fMaps[Last_MarkType + 1];
+ vector<DefinitionMap> fMaps;
static MarkProps kMarkProps[Last_MarkType + 1];
forward_list<RootDefinition> fTopics;
@@ -1550,67 +1529,15 @@ public:
IncludeParser() : ParserCommon()
, fMaps {
- { nullptr, MarkType::kNone }
- , { nullptr, MarkType::kAnchor }
- , { nullptr, MarkType::kAlias }
- , { nullptr, MarkType::kBug }
- , { nullptr, MarkType::kClass }
- , { nullptr, MarkType::kCode }
- , { nullptr, MarkType::kColumn }
- , { nullptr, MarkType::kComment }
- , { &fIConstMap, MarkType::kConst }
+ { &fIConstMap, MarkType::kConst }
, { &fIDefineMap, MarkType::kDefine }
- , { nullptr, MarkType::kDefinedBy }
- , { nullptr, MarkType::kDeprecated }
- , { nullptr, MarkType::kDescription }
- , { nullptr, MarkType::kDetails }
- , { nullptr, MarkType::kDuration }
, { &fIEnumMap, MarkType::kEnum }
, { &fIEnumMap, MarkType::kEnumClass }
- , { nullptr, MarkType::kExample }
- , { nullptr, MarkType::kExperimental }
- , { nullptr, MarkType::kExternal }
- , { nullptr, MarkType::kFormula }
- , { nullptr, MarkType::kFunction }
- , { nullptr, MarkType::kHeight }
- , { nullptr, MarkType::kIllustration }
- , { nullptr, MarkType::kImage }
- , { nullptr, MarkType::kIn }
- , { nullptr, MarkType::kLegend }
- , { nullptr, MarkType::kLine }
- , { nullptr, MarkType::kLink }
- , { nullptr, MarkType::kList }
- , { nullptr, MarkType::kLiteral }
- , { nullptr, MarkType::kMarkChar }
- , { nullptr, MarkType::kMember }
- , { nullptr, MarkType::kMethod }
- , { nullptr, MarkType::kNoExample }
- , { nullptr, MarkType::kNoJustify }
- , { nullptr, MarkType::kOutdent }
- , { nullptr, MarkType::kParam }
- , { nullptr, MarkType::kPhraseDef }
- , { nullptr, MarkType::kPhraseParam }
- , { nullptr, MarkType::kPhraseRef }
- , { nullptr, MarkType::kPlatform }
- , { nullptr, MarkType::kPopulate }
- , { nullptr, MarkType::kPrivate }
- , { nullptr, MarkType::kReturn }
- , { nullptr, MarkType::kRow }
- , { nullptr, MarkType::kSeeAlso }
- , { nullptr, MarkType::kSet }
- , { nullptr, MarkType::kStdOut }
, { &fIStructMap, MarkType::kStruct }
- , { nullptr, MarkType::kSubstitute }
- , { nullptr, MarkType::kSubtopic }
- , { nullptr, MarkType::kTable }
, { &fITemplateMap, MarkType::kTemplate }
- , { nullptr, MarkType::kText }
- , { nullptr, MarkType::kToDo }
- , { nullptr, MarkType::kTopic }
, { &fITypedefMap, MarkType::kTypedef }
, { &fIUnionMap, MarkType::kUnion }
- , { nullptr, MarkType::kVolatile }
- , { nullptr, MarkType::kWidth } }
+ }
{
this->reset();
}
@@ -1645,33 +1572,8 @@ public:
bool dumpTokens();
bool dumpTokens(string skClassName);
bool findComments(const Definition& includeDef, Definition* markupDef);
-
Definition* findIncludeObject(const Definition& includeDef, MarkType markType,
- string typeName) {
- typedef Definition* DefinitionPtr;
- unordered_map<string, Definition*>* map = fMaps[(int) markType].fInclude;
- if (!map) {
- return reportError<DefinitionPtr>("invalid mark type");
- }
- string name = this->uniqueName(*map, typeName);
- Definition& markupDef = *(*map)[name];
- if (markupDef.fStart) {
- return reportError<DefinitionPtr>("definition already defined");
- }
- markupDef.fFileName = fFileName;
- markupDef.fStart = includeDef.fStart;
- markupDef.fContentStart = includeDef.fStart;
- markupDef.fName = name;
- markupDef.fContentEnd = includeDef.fContentEnd;
- markupDef.fTerminator = includeDef.fTerminator;
- markupDef.fParent = fParent;
- markupDef.fLineCount = includeDef.fLineCount;
- markupDef.fMarkType = markType;
- markupDef.fKeyWord = includeDef.fKeyWord;
- markupDef.fType = Definition::Type::kMark;
- return &markupDef;
- }
-
+ string typeName);
static KeyWord FindKey(const char* start, const char* end);
bool isClone(const Definition& token);
bool isConstructor(const Definition& token, string className);
@@ -1725,9 +1627,12 @@ public:
void reset() override {
INHERITED::resetCommon();
fRootTopic = nullptr;
+ fConstExpr = nullptr;
fInBrace = nullptr;
fIncludeWord = nullptr;
fLastObject = nullptr;
+ fPriorEnum = nullptr;
+ fPriorObject = nullptr;
fAttrDeprecated = nullptr;
fPrev = '\0';
fInChar = false;
@@ -1738,7 +1643,6 @@ public:
fInFunction = false;
fInString = false;
fFailed = false;
- fPriorEnum = nullptr;
}
void setBracketShortCuts(Bracket bracket) {
@@ -1905,7 +1809,7 @@ protected:
static const char gAttrDeprecated[];
static const size_t kAttrDeprecatedLen;
- DefinitionMap fMaps[Last_MarkType + 1];
+ vector<DefinitionMap> fMaps;
unordered_map<string, Definition> fIncludeMap;
list<Definition> fGlobals;
unordered_map<string, IClassDefinition> fIClassMap;
@@ -1918,9 +1822,11 @@ protected:
unordered_map<string, Definition*> fITypedefMap;
unordered_map<string, Definition*> fIUnionMap;
Definition* fRootTopic;
+ Definition* fConstExpr;
Definition* fInBrace;
Definition* fLastObject;
Definition* fPriorEnum;
+ Definition* fPriorObject;
const Definition* fAttrDeprecated;
int fPriorIndex;
const char* fIncludeWord;
@@ -2077,7 +1983,18 @@ public:
vector<IterState>& iterStack, IterState** iterState, Preprocessor* );
void enumSizeItems(const Definition& child);
bool findEnumSubtopic(string undername, const Definition** ) const;
+ void firstBlock(int size, const char* data);
+ bool firstBlockTrim(int size, const char* data);
Definition* findMemberCommentBlock(const vector<Definition*>& bmhChildren, string name) const;
+ Definition* findMethod(string name, RootDefinition* ) const;
+
+ void indentDeferred(IndentKind kind) {
+ if (fIndentNext) {
+ this->indentIn(kind);
+ fIndentNext = false;
+ }
+ }
+
int lookupMethod(const PunctuationState punctuation, const Word word,
const int start, const int run, int lastWrite,
const char* data, bool hasIndirection);
@@ -2091,37 +2008,46 @@ public:
void reset() override {
INHERITED::resetCommon();
- fBmhMethod = nullptr;
fBmhParser = nullptr;
+ fDeferComment = nullptr;
+ fBmhMethod = nullptr;
fEnumDef = nullptr;
fMethodDef = nullptr;
fBmhConst = nullptr;
fConstDef = nullptr;
+ fLastDescription = nullptr;
+ fStartSetter = nullptr;
fBmhStructDef = nullptr;
+ fContinuation = nullptr;
fInStruct = false;
fWroteMethod = false;
fIndentNext = false;
fPendingMethod = false;
+ fFirstWrite = false;
+ fStructEnded = 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);
+ void setStart(const char* start, const Definition * );
+ void setStartBack(const char* start, const Definition * );
Definition* structMemberOut(const Definition* memberStart, const Definition& child);
void structOut(const Definition* root, const Definition& child,
const char* commentStart, const char* commentEnd);
void structSizeMembers(const Definition& child);
private:
+ vector<const Definition* > fICSStack;
BmhParser* fBmhParser;
Definition* fDeferComment;
- Definition* fLastComment;
const Definition* fBmhMethod;
const Definition* fEnumDef;
const Definition* fMethodDef;
const Definition* fBmhConst;
const Definition* fConstDef;
const Definition* fLastDescription;
+ const Definition* fStartSetter;
Definition* fBmhStructDef;
const char* fContinuation; // used to construct paren-qualified method name
int fAnonymousEnumCount;
@@ -2134,10 +2060,12 @@ private:
int fConstValueTab;
int fConstCommentTab;
int fConstLength;
- bool fInStruct;
+ bool fInStruct; // set if struct is inside class
bool fWroteMethod;
bool fIndentNext;
bool fPendingMethod;
+ bool fFirstWrite; // set to write file information just after includes
+ bool fStructEnded; // allow resetting indent after struct is complete
typedef IncludeParser INHERITED;
};
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 56de4f6f15..16c99af520 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -46,6 +46,7 @@ const IncludeKey kKeyWords[] = {
{ "struct", KeyWord::kStruct, KeyProperty::kObject },
{ "template", KeyWord::kTemplate, KeyProperty::kObject },
{ "typedef", KeyWord::kTypedef, KeyProperty::kObject },
+ { "typename", KeyWord::kTypename, KeyProperty::kObject },
{ "uint16_t", KeyWord::kUint16_t, KeyProperty::kNumber },
{ "uint32_t", KeyWord::kUint32_t, KeyProperty::kNumber },
{ "uint64_t", KeyWord::kUint64_t, KeyProperty::kNumber },
@@ -1276,6 +1277,36 @@ bool IncludeParser::findComments(const Definition& includeDef, Definition* marku
return true;
}
+Definition* IncludeParser::findIncludeObject(const Definition& includeDef, MarkType markType,
+ string typeName) {
+ typedef Definition* DefinitionPtr;
+ auto mapIter = std::find_if(fMaps.begin(), fMaps.end(),
+ [markType](DefinitionMap& defMap){ return markType == defMap.fMarkType; } );
+ if (mapIter == fMaps.end()) {
+ return nullptr;
+ }
+ if (mapIter->fInclude->end() == mapIter->fInclude->find(typeName)) {
+ return reportError<DefinitionPtr>("invalid mark type");
+ }
+ string name = this->uniqueName(*mapIter->fInclude, typeName);
+ Definition& markupDef = *(*mapIter->fInclude)[name];
+ if (markupDef.fStart) {
+ return reportError<DefinitionPtr>("definition already defined");
+ }
+ markupDef.fFileName = fFileName;
+ markupDef.fStart = includeDef.fStart;
+ markupDef.fContentStart = includeDef.fStart;
+ markupDef.fName = name;
+ markupDef.fContentEnd = includeDef.fContentEnd;
+ markupDef.fTerminator = includeDef.fTerminator;
+ markupDef.fParent = fParent;
+ markupDef.fLineCount = includeDef.fLineCount;
+ markupDef.fMarkType = markType;
+ markupDef.fKeyWord = includeDef.fKeyWord;
+ markupDef.fType = Definition::Type::kMark;
+ return &markupDef;
+}
+
// caller just returns, so report error here
bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
SkASSERT(includeDef->fTokens.size() > 0);
@@ -1431,32 +1462,11 @@ bool IncludeParser::parseComment(string filename, const char* start, const char*
}
bool IncludeParser::parseConst(Definition* child, Definition* markupDef) {
- // todo: hard code to constexpr for now
- TextParser constParser(child);
- if (!constParser.skipExact("static")) {
- return false;
- }
- constParser.skipWhiteSpace();
- if (!constParser.skipExact("constexpr")) {
- return false;
- }
- constParser.skipWhiteSpace();
- const char* typeStart = constParser.fChar;
- constParser.skipToSpace();
- KeyWord constType = FindKey(typeStart, constParser.fChar);
- if (KeyWord::kNone == constType) {
- // todo: this could be a non-keyword, ... do we need to look for type?
- return false;
- }
- constParser.skipWhiteSpace();
- const char* nameStart = constParser.fChar;
- constParser.skipToSpace();
- string nameStr = string(nameStart, constParser.fChar - nameStart);
if (!markupDef) {
fGlobals.emplace_back(MarkType::kConst, child->fContentStart, child->fContentEnd,
child->fLineCount, fParent, '\0');
Definition* globalMarkupChild = &fGlobals.back();
- string globalUniqueName = this->uniqueName(fIConstMap, nameStr);
+ string globalUniqueName = this->uniqueName(fIConstMap, child->fName);
globalMarkupChild->fName = globalUniqueName;
if (!this->findComments(*child, globalMarkupChild)) {
return false;
@@ -1467,10 +1477,10 @@ bool IncludeParser::parseConst(Definition* child, Definition* markupDef) {
markupDef->fTokens.emplace_back(MarkType::kConst, child->fContentStart, child->fContentEnd,
child->fLineCount, markupDef, '\0');
Definition* markupChild = &markupDef->fTokens.back();
- markupChild->fName = nameStr;
+ markupChild->fName = child->fName;
markupChild->fTerminator = markupChild->fContentEnd;
IClassDefinition& classDef = fIClassMap[markupDef->fName];
- classDef.fConsts[nameStr] = markupChild;
+ classDef.fConsts[child->fName] = markupChild;
return true;
}
@@ -1935,10 +1945,12 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
}
bool IncludeParser::parseObjects(Definition* parent, Definition* markupDef) {
- for (auto& child : parent->fChildren) {
+ fPriorObject = nullptr;
+ for (auto child : parent->fChildren) {
if (!this->parseObject(child, markupDef)) {
return false;
}
+ fPriorObject = child;
}
return true;
}
@@ -1957,6 +1969,8 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
}
break;
case KeyWord::kStatic:
+ case KeyWord::kConst:
+ case KeyWord::kConstExpr:
if (!this->parseConst(child, markupDef)) {
return child->reportError<bool>("failed to parse const or constexpr");
}
@@ -2022,6 +2036,9 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
}
}
}
+ if (fPriorObject && MarkType::kConst == fPriorObject->fMarkType) {
+ break;
+ }
if (!this->parseMethod(child, markupDef)) {
return child->reportError<bool>("failed to parse method");
}
@@ -2124,6 +2141,7 @@ bool IncludeParser::parseTypedef(Definition* child, Definition* markupDef) {
return false;
}
fITypedefMap[globalUniqueName] = globalMarkupChild;
+ child->fName = nameStr;
return true;
}
markupDef->fTokens.emplace_back(MarkType::kTypedef, child->fContentStart, child->fContentEnd,
@@ -2133,6 +2151,7 @@ bool IncludeParser::parseTypedef(Definition* child, Definition* markupDef) {
markupChild->fTerminator = markupChild->fContentEnd;
IClassDefinition& classDef = fIClassMap[markupDef->fName];
classDef.fTypedefs[nameStr] = markupChild;
+ child->fName = markupDef->fName + "::" + nameStr;
return true;
}
@@ -2253,6 +2272,10 @@ bool IncludeParser::parseChar() {
if (':' == test && (fInBrace || ':' == fChar[-1] || ':' == fChar[1])) {
break;
}
+ if (fConstExpr) {
+ fConstExpr->fContentEnd = fParent->fTokens.back().fContentEnd;
+ fConstExpr = nullptr;
+ }
if (!fInBrace) {
if (!this->checkForWord()) {
return false;
@@ -2368,7 +2391,6 @@ bool IncludeParser::parseChar() {
case '&':
case ',':
case '+':
- case '=':
case '-':
case '!':
if (fInCharCommentString || fInBrace) {
@@ -2378,6 +2400,95 @@ bool IncludeParser::parseChar() {
return false;
}
break;
+ case '=':
+ if (fInCharCommentString || fInBrace) {
+ break;
+ }
+ if (!this->checkForWord()) {
+ return false;
+ }
+ {
+ const Definition& lastToken = fParent->fTokens.back();
+ if (lastToken.fType != Definition::Type::kWord) {
+ break;
+ }
+ string name(lastToken.fContentStart, lastToken.length());
+ if ("SK_" != name.substr(0, 3) && 'k' != name[0]) {
+ break;
+ }
+ // find token on start of line
+ auto lineIter = fParent->fTokens.end();
+ do {
+ --lineIter;
+ } while (lineIter->fContentStart > fLine);
+ if (lineIter->fContentStart < fLine) {
+ ++lineIter;
+ }
+ Definition* lineStart = &*lineIter;
+ // walk tokens looking for [template <typename T>] [static] [const | constexpr]
+ bool sawConst = false;
+ bool sawStatic = false;
+ bool sawTemplate = false;
+ bool sawType = false;
+ while (&lastToken != &*lineIter) {
+ if (KeyWord::kTemplate == lineIter->fKeyWord) {
+ if (sawConst || sawStatic || sawTemplate) {
+ sawConst = false;
+ break;
+ }
+ if (&lastToken == &*++lineIter) {
+ break;
+ }
+ if (KeyWord::kTypename != lineIter->fKeyWord) {
+ break;
+ }
+ if (&lastToken == &*++lineIter) {
+ break;
+ }
+ if (Definition::Type::kWord != lineIter->fType) {
+ break;
+ }
+ sawTemplate = true;
+ } else if (KeyWord::kStatic == lineIter->fKeyWord) {
+ if (sawConst || sawStatic) {
+ sawConst = false;
+ break;
+ }
+ sawStatic = true;
+ } else if (KeyWord::kConst == lineIter->fKeyWord
+ || KeyWord::kConstExpr == lineIter->fKeyWord) {
+ if (sawConst) {
+ sawConst = false;
+ break;
+ }
+ sawConst = true;
+ } else {
+ if (sawType) {
+ sawType = false;
+ break;
+ }
+ if (Definition::Type::kKeyWord == lineIter->fType
+ && KeyProperty::kNumber
+ == kKeyWords[(int) lineIter->fKeyWord].fProperty) {
+ sawType = true;
+ } else if (Definition::Type::kWord == lineIter->fType) {
+ string typeName(lineIter->fContentStart, lineIter->length());
+ if ("Sk" != name.substr(0, 2)) {
+ sawType = true;
+ }
+ }
+ }
+ ++lineIter;
+ }
+ if (sawType && sawConst) {
+ // if found, name first
+ lineStart->fName = name;
+ lineStart->fMarkType = MarkType::kConst;
+ fParent->fChildren.emplace_back(lineStart);
+ fConstExpr = lineStart;
+ }
+ }
+ break;
case ';':
if (fInCharCommentString || fInBrace) {
break;
@@ -2385,6 +2496,10 @@ bool IncludeParser::parseChar() {
if (!this->checkForWord()) {
return false;
}
+ if (fConstExpr) {
+ fConstExpr->fContentEnd = fParent->fTokens.back().fContentEnd;
+ fConstExpr = nullptr;
+ }
if (Definition::Type::kKeyWord == fParent->fType
&& KeyProperty::kObject == (kKeyWords[(int) fParent->fKeyWord].fProperty)) {
bool parentIsClass = KeyWord::kClass == fParent->fKeyWord;
@@ -2527,43 +2642,6 @@ bool IncludeParser::parseChar() {
fPriorEnum = priorEnum;
}
}
- } else { // check for static constexpr not following an enum
- // find first token on line
- auto backTokenWalker = fParent->fTokens.end();
- while (fParent->fTokens.begin() != backTokenWalker
- && (fParent->fTokens.end() == backTokenWalker
- || backTokenWalker->fStart > fLine)) {
- std::advance(backTokenWalker, -1);
- }
- if (fParent->fTokens.end() != backTokenWalker
- && backTokenWalker->fStart < fLine) {
- std::advance(backTokenWalker, 1);
- }
- // look for static constexpr
- Definition* start = &*backTokenWalker;
- bool foundExpected = true;
- for (KeyWord expected : {KeyWord::kStatic, KeyWord::kConstExpr}){
- const Definition* test = &*backTokenWalker;
- if (expected != test->fKeyWord) {
- foundExpected = false;
- break;
- }
- if (backTokenWalker == fParent->fTokens.end()) {
- break;
- }
- std::advance(backTokenWalker, 1);
- }
- if (foundExpected) {
- std::advance(backTokenWalker, 1);
- const char* nameStart = backTokenWalker->fStart;
- std::advance(backTokenWalker, 1);
- TextParser parser(fFileName, nameStart, backTokenWalker->fStart, fLineCount);
- parser.skipToNonAlphaNum();
- start->fMarkType = MarkType::kConst;
- start->fName = string(nameStart, parser.fChar - nameStart);
- start->fContentEnd = backTokenWalker->fContentEnd;
- fParent->fChildren.emplace_back(start);
- }
}
}
this->addPunctuation(Punctuation::kSemicolon);
@@ -2604,9 +2682,6 @@ done:
}
void IncludeParser::validate() const {
- for (int index = 0; index <= (int) Last_MarkType; ++index) {
- SkASSERT(fMaps[index].fMarkType == (MarkType) index);
- }
IncludeParser::ValidateKeyWords();
}
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index f05ef0ece1..53930c6c13 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -61,16 +61,27 @@ void IncludeWriter::checkEnumLengths(const Definition& child, string enumName, I
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->firstBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
this->lf(2);
- this->writeCommentHeader();
- fIndent += 4;
- if (!this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo)) {
- return memberStart->reportError<void>("expected description for const");
+ this->indentDeferred(IndentKind::kConstOut);
+ if (fStructEnded) {
+ fIndent = fICSStack.size() * 4;
+ fStructEnded = false;
+ }
+ // comment may be legitimately empty; typedef may not have separate comment (for now)
+ fReturnOnWrite = true;
+ bool commentHasLength = this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo);
+ fReturnOnWrite = false;
+ if (commentHasLength) {
+ this->writeCommentHeader();
+ fIndent += 4;
+ if (!this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo)) {
+ return memberStart->reportError<void>("expected description for const");
+ }
+ fIndent -= 4;
+ this->writeCommentTrailer(OneLine::kNo);
}
- fIndent -= 4;
- this->writeCommentTrailer(OneLine::kNo);
- fStart = memberStart->fContentStart;
+ this->setStart(memberStart->fContentStart, memberStart);
}
bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine,
@@ -86,6 +97,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
bool breakOut = false;
SkDEBUGCODE(bool wroteCode = false);
if (def->fDeprecated) {
+ if (fReturnOnWrite) {
+ return true;
+ }
string message = def->incompleteMessage(Definition::DetailsType::kSentence);
this->writeString(message);
this->lfcr();
@@ -103,6 +117,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (commentLen > 0) {
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->lf(2);
wroteSomething = true;
}
@@ -120,13 +137,18 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
commentLen = (int) (prop->fContentEnd - commentStart);
SkASSERT(commentLen > 0);
if (literal) {
- if (!literalOutdent) {
+ if (!fReturnOnWrite && !literalOutdent) {
fIndent += 4;
}
wroteSomething |= this->writeBlockIndent(commentLen, commentStart);
- this->lf(2);
- if (!literalOutdent) {
- fIndent -= 4;
+ if (fReturnOnWrite) {
+ return true;
+ }
+ if (!fReturnOnWrite) {
+ this->lf(2);
+ if (!literalOutdent) {
+ fIndent -= 4;
+ }
}
SkDEBUGCODE(wroteCode = true);
}
@@ -136,6 +158,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
commentStart = prop->fTerminator;
break;
case MarkType::kBug: {
+ if (fReturnOnWrite) {
+ return true;
+ }
string bugstr("(see skbug.com/" + string(prop->fContentStart,
prop->fContentEnd - prop->fContentStart) + ')');
this->writeString(bugstr);
@@ -148,6 +173,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (commentLen > 0) {
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->lfcr();
wroteSomething = true;
}
@@ -162,6 +190,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
commentLen = (int) (prop->fContentEnd - commentStart);
if (commentLen > 0) {
wroteSomething |= this->writeBlockIndent(commentLen, commentStart);
+ if (wroteSomething && fReturnOnWrite) {
+ return true;
+ }
const char* end = commentStart + commentLen;
while (end > commentStart && ' ' == end[-1]) {
--end;
@@ -181,6 +212,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
commentLen = (int) (prop->fContentEnd - commentStart);
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->lfcr();
wroteSomething = true;
}
@@ -192,6 +226,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
commentLen = prop->fStart - commentStart;
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
if (commentLen > 1 && '\n' == prop->fStart[-1] &&
'\n' == prop->fStart[-2]) {
this->lf(1);
@@ -207,17 +244,23 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
}
wroteSomething |= this->writeBlockIndent(prop->length(), prop->fContentStart);
fIndent = saveIndent;
+ if (wroteSomething && fReturnOnWrite) {
+ return true;
+ }
commentStart = prop->fTerminator;
commentLen = (int) (def->fContentEnd - commentStart);
- 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();
+ if (!fReturnOnWrite) {
+ 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;
+ case MarkType::kDetails:
case MarkType::kIn:
case MarkType::kLine:
case MarkType::kToDo:
@@ -225,6 +268,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (commentLen > 0) {
SkASSERT(commentLen < 1000);
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->lfcr();
wroteSomething = true;
}
@@ -237,6 +283,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart,
Phrase::kNo)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->lfcr();
wroteSomething = true;
}
@@ -245,6 +294,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
SkASSERT(MarkType::kRow == row->fMarkType);
for (auto column : row->fChildren) {
SkASSERT(MarkType::kColumn == column->fMarkType);
+ if (fReturnOnWrite) {
+ return true;
+ }
this->writeString("-");
this->writeSpace();
wroteSomething |= this->descriptionOut(column, SkipFirstLine::kNo, Phrase::kNo);
@@ -260,6 +312,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
case MarkType::kPhraseRef: {
commentLen = prop->fStart - commentStart;
if (commentLen > 0) {
+ if (fReturnOnWrite) {
+ return true;
+ }
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
@@ -286,6 +341,9 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
continue;
}
int localLength = child->fStart - start;
+ if (fReturnOnWrite) {
+ return true;
+ }
this->rewriteBlock(localLength, start, defIsPhrase);
start += localLength;
length -= localLength;
@@ -304,12 +362,17 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
wroteSomething = true;
}
if (length > 0) {
+ if (fReturnOnWrite) {
+ return true;
+ }
this->rewriteBlock(length, start, defIsPhrase);
}
commentStart = prop->fContentStart;
commentLen = (int) (def->fContentEnd - commentStart);
- if ('\n' == commentStart[0] && '\n' == commentStart[1]) {
- this->lf(2);
+ if (!fReturnOnWrite) {
+ if ('\n' == commentStart[0] && '\n' == commentStart[1]) {
+ this->lf(2);
+ }
}
} break;
default:
@@ -320,11 +383,19 @@ bool IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs
break;
}
}
+ if (!breakOut) {
+ commentLen = (int) (def->fContentEnd - commentStart);
+ }
SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500) || def->fDeprecated);
if (commentLen > 0) {
- this->rewriteBlock(commentLen, commentStart, phrase);
- wroteSomething = true;
+ if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, phrase)) {
+ if (fReturnOnWrite) {
+ return true;
+ }
+ wroteSomething = true;
+ }
}
+ SkASSERT(!fReturnOnWrite || !wroteSomething);
return wroteSomething;
}
@@ -332,14 +403,11 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
const Definition* enumDef = nullptr;
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
child.fContentStart;
- this->writeBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
+ this->firstBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
this->lf(2);
- if (fIndentNext) {
- fIndent += 4;
- fIndentNext = false;
- }
+ this->indentDeferred(IndentKind::kEnumHeader);
fDeferComment = nullptr;
- fStart = child.fContentStart;
+ this->setStart(child.fContentStart, &child);
const auto& nameDef = child.fTokens.front();
string fullName;
if (nullptr != nameDef.fContentEnd) {
@@ -400,7 +468,8 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
if (!wroteHeader &&
!this->contentFree((int) (commentEnd - commentStart), commentStart)) {
if (fIndentNext) {
- fIndent += 4;
+ // FIXME: how can I tell where fIdentNext gets cleared?
+ this->indentIn(IndentKind::kEnumChild);
}
this->writeCommentHeader();
this->writeString("\\enum");
@@ -408,7 +477,7 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
this->writeSpace();
this->writeString(fullName.c_str());
}
- fIndent += 4;
+ this->indentIn(IndentKind::kEnumChild2);
this->lfcr();
wroteHeader = true;
}
@@ -451,7 +520,7 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
SkASSERT(codeBlock);
SkASSERT(foundConst);
if (wroteHeader) {
- fIndent -= 4;
+ this->indentOut();
this->lfcr();
this->writeCommentTrailer(OneLine::kNo);
}
@@ -464,9 +533,9 @@ void IncludeWriter::enumHeaderOut(RootDefinition* root, const Definition& child)
++bodyEnd;
this->lfcr();
this->writeBlock((int) (bodyEnd - fStart), fStart); // write include "enum Name {"
- fIndent += 4;
+ this->indentIn(IndentKind::kEnumHeader2);
this->singleLF();
- fStart = bodyEnd;
+ this->setStart(bodyEnd, braceHolder);
fEnumDef = enumDef;
}
@@ -509,7 +578,7 @@ IncludeWriter::ItemState IncludeWriter::enumMemberName(
item->fName = string(parser.fChar, (int) (last->fEnd - parser.fChar));
*currentEnumItem = this->matchMemberName(item->fName, child);
if (token) {
- fStart = token->fContentEnd;
+ this->setStart(token->fContentEnd, token);
TextParser enumLine(token->fFileName, last->fEnd, token->fContentStart, token->fLineCount);
const char* end = enumLine.anyOf(",}=");
SkASSERT(end);
@@ -636,7 +705,7 @@ void IncludeWriter::enumMembersOut(Definition& child) {
if (ItemState::kNone != state) {
this->enumMemberOut(currentEnumItem, child, item, preprocessor);
item.reset();
- fStart = token.fContentStart;
+ this->setStartBack(token.fContentStart, &token);
state = ItemState::kNone;
last.fStart = nullptr;
}
@@ -653,7 +722,7 @@ void IncludeWriter::enumMembersOut(Definition& child) {
if (ItemState::kValue == state || ItemState::kComment == state) {
this->enumMemberOut(currentEnumItem, child, item, preprocessor);
}
- fIndent -= 4;
+ this->indentOut();
}
bool IncludeWriter::enumPreprocessor(Definition* token, MemberPass pass,
@@ -661,13 +730,13 @@ bool IncludeWriter::enumPreprocessor(Definition* token, MemberPass pass,
if (token && Definition::Type::kBracket == token->fType) {
if (Bracket::kSlashSlash == token->fBracket) {
if (MemberPass::kOut == pass) {
- fStart = token->fContentEnd;
+ this->setStart(token->fContentEnd, token);
}
return true; // ignore old inline comments
}
if (Bracket::kSlashStar == token->fBracket) {
if (MemberPass::kOut == pass) {
- fStart = token->fContentEnd + 1;
+ this->setStart(token->fContentEnd + 1, token);
}
return true; // ignore old inline comments
}
@@ -808,7 +877,7 @@ const Definition* IncludeWriter::matchMemberName(string matchName, const Definit
// walk children and output complete method doxygen description
void IncludeWriter::methodOut(Definition* method, const Definition& child) {
if (fPendingMethod) {
- fIndent -= 4;
+ this->indentOut();
fPendingMethod = false;
}
fBmhMethod = method;
@@ -817,7 +886,7 @@ void IncludeWriter::methodOut(Definition* method, const Definition& child) {
fDeferComment = nullptr;
Definition* csParent = method->csParent();
if (csParent && (0 == fIndent || fIndentNext)) {
- fIndent += 4;
+ this->indentIn(IndentKind::kMethodOut);
fIndentNext = false;
}
this->writeCommentHeader();
@@ -922,15 +991,64 @@ Definition* IncludeWriter::findMemberCommentBlock(const vector<Definition*>& bmh
return nullptr;
}
+Definition* IncludeWriter::findMethod(string name, RootDefinition* root) const {
+ if (root) {
+ return root->find(name, RootDefinition::AllowParens::kNo);
+ }
+ auto methodIter = fBmhParser->fMethodMap.find(name);
+ if (fBmhParser->fMethodMap.end() == methodIter) {
+ return nullptr;
+ }
+ return &methodIter->second;
+}
+
+
+void IncludeWriter::firstBlock(int size, const char* data) {
+ SkAssertResult(this->firstBlockTrim(size, data));
+}
+
+bool IncludeWriter::firstBlockTrim(int size, const char* data) {
+ bool result = this->writeBlockTrim(size, data);
+ if (fFirstWrite) {
+ auto fileInfo = std::find_if(fRootTopic->fChildren.begin(), fRootTopic->fChildren.end(),
+ [](const Definition* def){ return MarkType::kFile == def->fMarkType; } );
+ if (fRootTopic->fChildren.end() != fileInfo) {
+ this->writeCommentHeader();
+ this->writeString("\\file");
+ this->writeSpace();
+ size_t lastSlash = fFileName.rfind('/');
+ if (string::npos == lastSlash) {
+ lastSlash = fFileName.rfind('\\');
+ }
+ string fileName = fFileName.substr(lastSlash + 1);
+ this->writeString(fileName);
+ this->lf(2);
+ fIndent += 4;
+ this->descriptionOut(*fileInfo, SkipFirstLine::kNo, Phrase::kNo);
+ fIndent -= 4;
+ this->writeCommentTrailer(OneLine::kNo);
+ }
+ fFirstWrite = false;
+ }
+ return result;
+}
+
+void IncludeWriter::setStart(const char* start, const Definition* def) {
+ SkASSERT(start >= fStart);
+ this->setStartBack(start, def);
+}
+
+void IncludeWriter::setStartBack(const char* start, const Definition* def) {
+ fStartSetter = def;
+ fStart = start;
+}
+
Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const Definition& child) {
- const char* blockStart = !fWroteMethod && fDeferComment ? fLastComment->fContentEnd : fStart;
+ const char* blockStart = !fWroteMethod && fDeferComment ? fDeferComment->fContentEnd : fStart;
const char* blockEnd = fWroteMethod && fDeferComment ? fDeferComment->fStart - 1 :
memberStart->fStart;
- this->writeBlockTrim((int) (blockEnd - blockStart), blockStart);
- if (fIndentNext) {
- fIndent += 4;
- fIndentNext = false;
- }
+ this->firstBlockTrim((int) (blockEnd - blockStart), blockStart);
+ this->indentDeferred(IndentKind::kStructMember);
fWroteMethod = false;
string name(child.fContentStart, (int) (child.fContentEnd - child.fContentStart));
Definition* commentBlock = this->findMemberCommentBlock(fBmhStructDef->fChildren, name);
@@ -1203,9 +1321,16 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
bool eatOperator = false;
bool sawConst = false;
bool staticOnly = false;
+ bool sawTypedef = false;
const Definition* requireDense = nullptr;
const Definition* startDef = nullptr;
for (auto& child : def->fTokens) {
+ if (131 == child.fLineCount) {
+ SkDebugf("");
+ }
+ if (KeyWord::kInline == child.fKeyWord) {
+ continue;
+ }
if (KeyWord::kOperator == child.fKeyWord && method &&
Definition::MethodType::kOperator == method->fMethodType) {
eatOperator = true;
@@ -1226,7 +1351,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
continue;
}
startDef = &child;
- fStart = child.fContentStart + 1;
+ this->setStart(child.fContentStart + 1, &child);
memberEnd = nullptr;
}
if (child.fPrivate) {
@@ -1295,11 +1420,10 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
++alternate;
string alternateMethod = methodName + '_' + to_string(alternate);
- clonedMethod = root->find(alternateMethod,
- RootDefinition::AllowParens::kNo);
+ clonedMethod = this->findMethod(alternateMethod, root);
} while (clonedMethod);
if (!clonedMethod) {
- return this->reportError<bool>("cloned method not found");
+ return child.reportError<bool>("cloned method not found");
}
clonedMethod = nullptr;
continue;
@@ -1327,7 +1451,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
--continueEnd;
}
methodName += string(fContinuation, continueEnd - fContinuation);
- method = root->find(methodName, RootDefinition::AllowParens::kNo);
+ method = this->findMethod(methodName, root);
if (!method) {
if (fBmhStructDef && fBmhStructDef->fDeprecated) {
fContinuation = nullptr;
@@ -1347,7 +1471,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (inConstructor) {
continue;
}
- method = root->find(methodName + "()", RootDefinition::AllowParens::kNo);
+ method = this->findMethod(methodName + "()", root);
if (method && MarkType::kDefinedBy == method->fMarkType) {
method = method->fParent;
}
@@ -1369,7 +1493,6 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (!fDeferComment) {
fDeferComment = &child;
}
- fLastComment = &child;
continue;
}
if (MarkType::kMethod == child.fMarkType) {
@@ -1399,11 +1522,12 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
this->writeBlock(blockSize, fStart);
}
startDef = &child;
- fStart = child.fContentStart;
+ this->setStart(child.fContentStart, &child);
auto mapFind = fBmhParser->fMethodMap.find(child.fName);
if (fBmhParser->fMethodMap.end() != mapFind) {
inConstructor = false;
method = &mapFind->second;
+ methodName = child.fName;
} else {
methodName = root->fName + "::" + child.fName;
inConstructor = root->fName == child.fName;
@@ -1421,26 +1545,17 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
sawConst = false;
if (fAttrDeprecated) {
startDef = fAttrDeprecated;
- fStart = fAttrDeprecated->fContentStart;
+ this->setStartBack(fAttrDeprecated->fContentStart, fAttrDeprecated);
fAttrDeprecated = nullptr;
}
continue;
}
if (Definition::Type::kKeyWord == child.fType) {
- if (fIndentNext) {
- // 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
- }
switch (child.fKeyWord) {
case KeyWord::kStruct:
case KeyWord::kClass:
+ fICSStack.push_back(&child);
+ fStructEnded = false;
fStructMemberTab = 0;
// if struct contains members, compute their name and comment tabs
if (child.fChildren.size() > 0) {
@@ -1486,18 +1601,32 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
child.fContentStart;
this->writeBlockTrim((int) (bodyEnd - fStart), fStart);
if (fPendingMethod) {
- fIndent -= 4;
+ this->indentOut();
fPendingMethod = false;
}
startDef = requireDense ? requireDense : &child;
- fStart = requireDense ? requireDense->fContentStart : child.fContentStart;
+ if (requireDense) {
+ startDef = requireDense;
+ this->setStart(requireDense->fContentStart, requireDense);
+ } else {
+ startDef = &child;
+ this->setStart(child.fContentStart, &child);
+ }
requireDense = nullptr;
- if (!fInStruct && child.fName != root->fName) {
+ if (!fInStruct && (!root || child.fName != root->fName)) {
root = &fBmhParser->fClassMap[child.fName];
fRootTopic = root->fParent;
SkASSERT(!root->fVisited);
root->clearVisited();
+#if 0
+ // this seems better balanced; but real problem is probably fInStruct
+ if (fIndentStack.size() > 0) {
+ this->indentOut();
+ }
+ SkASSERT(!fIndent);
+#else
fIndent = 0;
+#endif
fBmhStructDef = root;
}
if (child.fName == root->fName) {
@@ -1515,20 +1644,6 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
} else {
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 (!fBmhStructDef) {
- this->lf(2);
- fIndent = 0;
- this->writeBlock((int) (fStart - bodyEnd), bodyEnd);
- this->lfcr();
- continue;
- }
- #endif
Definition* priorBlock = fBmhStructDef;
Definition* codeBlock = nullptr;
Definition* nextBlock = nullptr;
@@ -1576,7 +1691,22 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
fDeferComment = nullptr;
} else {
- ; // empty forward reference, nothing to do here
+ // empty forward reference
+ bool writeTwo = '\n' == child.fContentStart[-1]
+ && '\n' == child.fContentStart[-2];
+ if (writeTwo) {
+ const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
+ child.fContentStart;
+ this->writeBlockTrim((int) (bodyEnd - fStart), fStart);
+ this->lf(writeTwo ? 2 : 1);
+ fIndent = 0;
+ this->writeBlockTrim(child.length() + 1, child.fContentStart);
+ writeTwo = '\n' == child.fContentEnd[1]
+ && '\n' == child.fContentStart[2];
+ this->lf(writeTwo ? 2 : 1);
+ fStart = child.fContentEnd + 1;
+ fDeferComment = nullptr;
+ }
}
break;
case KeyWord::kEnum: {
@@ -1591,6 +1721,14 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
memberStart = &child;
staticOnly = true;
}
+ if (MarkType::kConst == child.fMarkType) {
+ auto constIter = fBmhParser->fConstMap.find(child.fName);
+ if (fBmhParser->fConstMap.end() != constIter) {
+ const RootDefinition& bmhConst = constIter->second;
+ this->constOut(&child, &bmhConst);
+ fDeferComment = nullptr;
+ }
+ }
break;
case KeyWord::kStatic:
if (!memberStart) {
@@ -1622,7 +1760,13 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
case KeyWord::kInline:
case KeyWord::kSK_API:
case KeyWord::kTemplate:
+ break;
case KeyWord::kTypedef:
+#if 01
+ SkASSERT(!memberStart);
+ memberStart = &child;
+ sawTypedef = true;
+#endif
break;
case KeyWord::kSK_BEGIN_REQUIRE_DENSE:
requireDense = &child;
@@ -1642,6 +1786,8 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
return false;
}
if (KeyWord::kClass == child.fKeyWord || KeyWord::kStruct == child.fKeyWord) {
+ fICSStack.pop_back();
+ fStructEnded = true;
if (fInStruct) {
fInStruct = false;
do {
@@ -1649,8 +1795,14 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
root = const_cast<RootDefinition*>(root->fParent->asRoot());
} while (MarkType::kTopic == root->fMarkType ||
MarkType::kSubtopic == root->fMarkType);
+#if 0
+ }
+ if (MarkType::kStruct == root->fMarkType ||
+ MarkType::kClass == root->fMarkType) {
+#else
SkASSERT(MarkType::kStruct == root->fMarkType ||
- MarkType::kClass == root->fMarkType);
+ MarkType::kClass == root->fMarkType);
+#endif
fPendingMethod = false;
if (startDef) {
fPendingMethod = find_start(startDef, fStart);
@@ -1671,7 +1823,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
this->writeString("};");
this->lf(2);
startDef = child.fParent;
- fStart = child.fParent->fContentEnd;
+ this->setStart(child.fParent->fContentEnd, child.fParent);
SkASSERT(';' == fStart[0]);
++fStart;
fDeferComment = nullptr;
@@ -1692,6 +1844,13 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (!this->populate(&child, &pair, root)) {
return false;
}
+ if (KeyWord::kClass == def->fKeyWord || KeyWord::kStruct == def->fKeyWord) {
+ if (def->iRootParent() && (!fStartSetter
+ || MarkType::kMethod != fStartSetter->fMarkType)) {
+ this->setStart(child.fContentEnd, &child);
+ fDeferComment = nullptr;
+ }
+ }
continue;
}
if (Definition::Type::kWord == child.fType) {
@@ -1701,20 +1860,19 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
std::advance(iter, child.fParentIndex - 1);
memberStart = &*iter;
staticOnly = false;
- if (!fStructMemberTab) {
- SkASSERT(KeyWord::kStruct == def->fParent->fKeyWord);
- fIndent += 4;
- this->structSizeMembers(*def->fParent);
- fIndent -= 4;
-// SkASSERT(!fIndentNext);
- fIndentNext = true;
- }
+ }
+ if (!fStructMemberTab) {
+ SkASSERT(KeyWord::kStruct == def->fParent->fKeyWord);
+ fIndent += 4;
+ this->structSizeMembers(*def->fParent);
+ fIndent -= 4;
+ fIndentNext = true;
}
SkASSERT(fBmhStructDef);
if (!fBmhStructDef->fDeprecated) {
memberEnd = this->structMemberOut(memberStart, child);
startDef = &child;
- fStart = child.fContentEnd + 1;
+ this->setStart(child.fContentEnd + 1, &child);
fDeferComment = nullptr;
}
} else if (MarkType::kNone == child.fMarkType && sawConst
@@ -1755,10 +1913,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
}
}
- } else {
- SkDebugf(""); // FIXME: support global constexpr
}
-
}
if (child.fMemberStart) {
memberStart = &child;
@@ -1786,11 +1941,8 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
// find member / value / comment tabs
// look for a one-to-one correspondence between bmh and include
this->constSizeMembers(root);
+ fDeferComment = nullptr;
}
- 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(),
@@ -1819,10 +1971,29 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
this->writeSpace();
this->rewriteBlock(lineDef->length(), lineDef->fContentStart, Phrase::kYes);
}
- fStart = child.fContentStart + 1;
+ this->setStart(child.fContentStart + 1, &child);
fDeferComment = nullptr;
fBmhConst = nullptr;
sawConst = false;
+ } else if (sawTypedef) {
+ const Definition* bmhTypedef = nullptr;
+ if (root) {
+ SkDEBUGCODE(auto classIter = fBmhParser->fClassMap.find(root->fName));
+ SkASSERT(fBmhParser->fClassMap.end() != classIter);
+ RootDefinition& classDef = fBmhParser->fClassMap[root->fName];
+ auto leafIter = classDef.fLeaves.find(memberStart->fName);
+ if (classDef.fLeaves.end() != leafIter) {
+ bmhTypedef = &leafIter->second;
+ }
+ }
+ if (!bmhTypedef) {
+ auto typedefIter = fBmhParser->fTypedefMap.find(memberStart->fName);
+ SkASSERT(fBmhParser->fTypedefMap.end() != typedefIter);
+ bmhTypedef = &typedefIter->second;
+ }
+ this->constOut(memberStart, bmhTypedef);
+ fDeferComment = nullptr;
+ sawTypedef = false;
}
memberStart = nullptr;
staticOnly = false;
@@ -1862,20 +2033,35 @@ bool IncludeWriter::populate(BmhParser& bmhParser) {
SkDebugf("could not open output file %s\n", fileName.c_str());
return false;
}
- if (bmhParser.fClassMap.end() == bmhParser.fClassMap.find(skClassName)) {
- return this->reportError<bool>("could not find bmh class");
- }
+ RootDefinition* root =
+ bmhParser.fClassMap.end() == bmhParser.fClassMap.find(skClassName) ?
+ nullptr : &bmhParser.fClassMap[skClassName];
fBmhParser = &bmhParser;
- RootDefinition* root = &bmhParser.fClassMap[skClassName];
- fRootTopic = root->fParent;
- root->clearVisited();
+ if (root) {
+ fRootTopic = root->fParent;
+ root->clearVisited();
+ } else {
+ SkASSERT("Sk" == skClassName.substr(0, 2));
+ string topicName = skClassName.substr(2);
+ auto topicIter = bmhParser.fTopicMap.find(topicName);
+ SkASSERT(bmhParser.fTopicMap.end() != topicIter);
+ fRootTopic = topicIter->second->asRoot();
+ fFirstWrite = true; // write file information after includes
+ }
fFileName = includeMapper.second.fFileName;
- fStart = includeMapper.second.fContentStart;
+ this->setStartBack(includeMapper.second.fContentStart, &includeMapper.second);
fEnd = includeMapper.second.fContentEnd;
fAnonymousEnumCount = 1;
allPassed &= this->populate(&includeMapper.second, nullptr, root);
this->writeBlock((int) (fEnd - fStart), fStart);
+#if 0
+ if (fIndentStack.size() > 0) {
+ this->indentOut();
+ }
+ SkASSERT(!fIndent);
+#else
fIndent = 0;
+#endif
this->lfcr();
this->writePending();
fclose(fOut);
@@ -1932,26 +2118,27 @@ string IncludeWriter::resolveMethod(const char* start, const char* end, bool fir
break;
}
}
- SkASSERT(parent);
- auto defRef = parent->find(parent->fName + "::" + methodname,
- 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 (parent) {
+ auto defRef = parent->find(parent->fName + "::" + methodname,
+ 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 + "()";
+ }
}
}
}
@@ -2168,7 +2355,7 @@ int IncludeWriter::lookupMethod(const PunctuationState punctuation, const Word w
if (' ' == data[lastWrite]) {
this->writeSpace();
}
- this->writeBlockTrim(wordStart - lastWrite, &data[lastWrite]);
+ this->firstBlockTrim(wordStart - lastWrite, &data[lastWrite]);
if (' ' == data[wordStart - 1]) {
this->writeSpace();
}
@@ -2199,7 +2386,7 @@ int IncludeWriter::lookupReference(const PunctuationState punctuation, const Wor
if (' ' == data[lastWrite]) {
this->writeSpace();
}
- this->writeBlockTrim(start - lastWrite, &data[lastWrite]);
+ this->firstBlockTrim(start - lastWrite, &data[lastWrite]);
if (' ' == data[start - 1]) {
this->writeSpace();
}
@@ -2224,6 +2411,9 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
if (0 == size) {
return Wrote::kNone;
}
+ if (fReturnOnWrite) {
+ return Wrote::kChars;
+ }
int run = 0;
Word word = Word::kStart;
PunctuationState punctuation = Phrase::kNo == phrase ?
diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp
index 0c88727c88..0d28f9db01 100644
--- a/tools/bookmaker/mdOut.cpp
+++ b/tools/bookmaker/mdOut.cpp
@@ -1434,6 +1434,8 @@ void MdOut::markTypeOut(Definition* def, const Definition** prior) {
break;
case MarkType::kExternal:
break;
+ case MarkType::kFile:
+ break;
case MarkType::kFormula:
break;
case MarkType::kFunction:
diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp
index 652df53e51..8a58b2642b 100644
--- a/tools/bookmaker/parserCommon.cpp
+++ b/tools/bookmaker/parserCommon.cpp
@@ -116,6 +116,9 @@ bool ParserCommon::writeBlockIndent(int size, const char* data) {
if (!size) {
return wroteSomething;
}
+ if (fReturnOnWrite) {
+ return true;
+ }
if (newLine) {
this->lf(1);
}
@@ -137,7 +140,8 @@ bool ParserCommon::writeBlockIndent(int size, const char* data) {
}
bool ParserCommon::writeBlockTrim(int size, const char* data) {
- if (fOutdentNext) {
+ SkASSERT(size >= 0);
+ if (!fReturnOnWrite && fOutdentNext) {
fIndent -= 4;
fOutdentNext = false;
}
@@ -149,9 +153,14 @@ bool ParserCommon::writeBlockTrim(int size, const char* data) {
--size;
}
if (size <= 0) {
- fLastChar = '\0';
+ if (!fReturnOnWrite) {
+ fLastChar = '\0';
+ }
return false;
}
+ if (fReturnOnWrite) {
+ return true;
+ }
SkASSERT(size < 16000);
if (size > 3 && !strncmp("#end", data, 4)) {
fMaxLF = 1;
@@ -182,6 +191,7 @@ bool ParserCommon::writeBlockTrim(int size, const char* data) {
}
void ParserCommon::writePending() {
+ SkASSERT(!fReturnOnWrite);
fPendingLF = SkTMin(fPendingLF, fMaxLF);
bool wroteLF = false;
while (fLinefeeds < fPendingLF) {
@@ -214,6 +224,7 @@ void ParserCommon::writePending() {
}
void ParserCommon::writeString(const char* str) {
+ SkASSERT(!fReturnOnWrite);
const size_t len = strlen(str);
SkASSERT(len > 0);
SkASSERT(' ' < str[0]);
diff --git a/tools/bookmaker/spellCheck.cpp b/tools/bookmaker/spellCheck.cpp
index be17855f9b..acf9e242a3 100644
--- a/tools/bookmaker/spellCheck.cpp
+++ b/tools/bookmaker/spellCheck.cpp
@@ -187,6 +187,8 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kExternal:
break;
+ case MarkType::kFile:
+ break;
case MarkType::kFormula:
fInFormula = true;
break;