diff --git a/docs/SkColor_Reference.bmh b/docs/SkColor_Reference.bmh index 50b4eb5590..a92e393853 100644 --- a/docs/SkColor_Reference.bmh +++ b/docs/SkColor_Reference.bmh @@ -1,6 +1,10 @@ #Topic Color #Alias Color_Reference ## +#File +Types, consts, functions, and macros for colors. +## + #Subtopic Overview #Populate ## @@ -47,7 +51,7 @@ zero, fully transparent, to one, fully opaque. typedef uint8_t SkAlpha; ## -8-bit type for an alpha value. 0xFF is 100% opaque, 0x00 is 100% transparent. +8-bit type for an alpha value. 255 is 100% opaque, zero is 100% transparent. #Typedef ## @@ -607,9 +611,13 @@ modulo 360, where zero degrees is red. ## #Subtopic Saturation +Saturation represents the intensity of the color. Saturation varies from zero, +with no Hue contribution; to one, with full Hue contribution. ## #Subtopic Value +Value represents the lightness of the color. Value varies from zero, black; to +one, full brightness. ## #Method void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]) @@ -617,9 +625,9 @@ modulo 360, where zero degrees is red. #Line # converts RGB to HSV ## Converts RGB to its HSV components. -hsv[0] contains Hue, a value from zero to less than 360. -hsv[1] contains Saturation, a value from zero to one. -hsv[2] contains Value, a value from zero to one. +hsv[0] contains HSV_Hue, a value from zero to less than 360. +hsv[1] contains HSV_Saturation, a value from zero to one. +hsv[2] contains HSV_Value, a value from zero to one. #Param red red component value from zero to 255 ## #Param green green component value from zero to 255 ## @@ -653,9 +661,9 @@ hsv[2] contains Value, a value from zero to one. #Line # converts RGB to HSV ## Converts ARGB to its HSV components. Alpha in ARGB is ignored. -hsv[0] contains Hue, and is assigned a value from zero to less than 360. -hsv[1] contains Saturation, a value from zero to one. -hsv[2] contains Value, a value from zero to one. +hsv[0] contains HSV_Hue, and is assigned a value from zero to less than 360. +hsv[1] contains HSV_Saturation, a value from zero to one. +hsv[2] contains HSV_Value, a value from zero to one. #Param color ARGB color to convert ## @@ -688,9 +696,9 @@ hsv[2] contains Value, a value from zero to one. #Line # converts HSV with Alpha to RGB ## Converts HSV components to an ARGB color. Alpha is passed through unchanged. -hsv[0] represents Hue, an angle from zero to less than 360. -hsv[1] represents Saturation, and varies from zero to one. -hsv[2] represents Value, and varies from zero to one. +hsv[0] represents HSV_Hue, an angle from zero to less than 360. +hsv[1] represents HSV_Saturation, and varies from zero to one. +hsv[2] represents HSV_Value, and varies from zero to one. Out of range hsv values are pinned. @@ -728,10 +736,10 @@ Out of range hsv values are pinned. #In Function #Line # converts HSV to RGB ## -Convert HSV components to an ARGB color. Alpha is set to 0xFF. -hsv[0] represents Hue, an angle from zero to less than 360. -hsv[1] represents Saturation, and varies from zero to one. -hsv[2] represents Value, and varies from zero to one. +Converts HSV components to an ARGB color. Alpha is set to 255. +hsv[0] represents HSV_Hue, an angle from zero to less than 360. +hsv[1] represents HSV_Saturation, and varies from zero to one. +hsv[2] represents HSV_Value, and varies from zero to one. Out of range hsv values are pinned. diff --git a/docs/SkImage_Reference.bmh b/docs/SkImage_Reference.bmh index 03dcd16e02..a6a623ff9e 100644 --- a/docs/SkImage_Reference.bmh +++ b/docs/SkImage_Reference.bmh @@ -2012,8 +2012,8 @@ By translating canvas by returned offset, Image appears stationary. typedef std::function BackendTextureReleaseProc; ## -Defines a function take one parameter of type -GrBackendTexture with no return value. +Defines a callback function, taking one parameter of type GrBackendTexture with +no return value. Function is called when back-end texture is to be released. ## # ------------------------------------------------------------------------------ diff --git a/docs/status.json b/docs/status.json index a24da579a5..07563837bb 100644 --- a/docs/status.json +++ b/docs/status.json @@ -4,6 +4,7 @@ "core": [ "SkBitmap.h", "SkCanvas.h", + "SkColor.h", "SkImage.h", "SkImageInfo.h", "SkMatrix.h", @@ -18,6 +19,8 @@ "docs": [ "SkAutoCanvasRestore_Reference.bmh", "SkCanvas_Reference.bmh", + "SkColor_Reference.bmh", + "SkColor4f_Reference.bmh", "SkPaint_Reference.bmh", "SkPoint_Reference.bmh", "SkIRect_Reference.bmh", @@ -37,12 +40,9 @@ "InProgress": { "include": { "core": [ - "SkColor.h" ] }, "docs": [ - "SkColor_Reference.bmh", - "SkColor4f_Reference.bmh", "overview.bmh", "usingBookmaker.bmh" ] diff --git a/site/user/api/SkColor_Reference.md b/site/user/api/SkColor_Reference.md index 7677ebd971..33316148c9 100644 --- a/site/user/api/SkColor_Reference.md +++ b/site/user/api/SkColor_Reference.md @@ -2,6 +2,7 @@ SkColor Reference === # Color +Types, consts, functions, and macros for colors. ## Overview @@ -203,7 +204,7 @@ zero, fully transparent, to one, fully opaque. typedef uint8_t SkAlpha; -8-bit type for an alpha value. 0xFF is 100% opaque, 0x00 is 100% transparent. +8-bit type for an alpha value. 255 is 100% opaque, zero is 100% transparent. ## Typedef SkColor @@ -761,8 +762,14 @@ modulo 360, where zero degrees is red. ## HSV Saturation +Saturation represents the intensity of the color. Saturation varies from zero, +with no Hue contribution; to one, with full Hue contribution. + ## HSV Value +Value represents the lightness of the color. Value varies from zero, black; to +one, full brightness. + ## SkRGBToHSV @@ -771,9 +778,9 @@ void SkRGBToHSV(U8CPU Converts RGB to its HSV components. -hsv[0] contains Hue, a value from zero to less than 360. -hsv[1] contains Saturation, a value from zero to one. -hsv[2] contains Value, a value from zero to one. +hsv[0] contains HSV Hue, a value from zero to less than 360. +hsv[1] contains HSV Saturation, a value from zero to one. +hsv[2] contains HSV Value, a value from zero to one. ### Parameters @@ -809,9 +816,9 @@ void SkColorToHSV(SkColor col Converts ARGB to its HSV components. Alpha in ARGB is ignored. -hsv[0] contains Hue, and is assigned a value from zero to less than 360. -hsv[1] contains Saturation, a value from zero to one. -hsv[2] contains Value, a value from zero to one. +hsv[0] contains HSV Hue, and is assigned a value from zero to less than 360. +hsv[1] contains HSV Saturation, a value from zero to one. +hsv[2] contains HSV Value, a value from zero to one. ### Parameters @@ -841,9 +848,9 @@ Converts ARGB to its HSV components. Alpha Converts HSV components to an ARGB color. Alpha is passed through unchanged. -hsv[0] represents Hue, an angle from zero to less than 360. -hsv[1] represents Saturation, and varies from zero to one. -hsv[2] represents Value, and varies from zero to one. +hsv[0] represents HSV Hue, an angle from zero to less than 360. +hsv[1] represents HSV Saturation, and varies from zero to one. +hsv[2] represents HSV Value, and varies from zero to one. Out of range hsv values are pinned. @@ -877,10 +884,10 @@ ARGB equivalent to HSV SkColor SkHSVToColor(const SkScalar hsv[3]) -Convert HSV components to an ARGB color. Alpha is set to 0xFF. -hsv[0] represents Hue, an angle from zero to less than 360. -hsv[1] represents Saturation, and varies from zero to one. -hsv[2] represents Value, and varies from zero to one. +Converts HSV components to an ARGB color. Alpha is set to 255. +hsv[0] represents HSV Hue, an angle from zero to less than 360. +hsv[1] represents HSV Saturation, and varies from zero to one. +hsv[2] represents HSV Value, and varies from zero to one. Out of range hsv values are pinned. diff --git a/site/user/api/SkImage_Reference.md b/site/user/api/SkImage_Reference.md index 59ea10bfdc..e43d9082ce 100644 --- a/site/user/api/SkImage_Reference.md +++ b/site/user/api/SkImage_Reference.md @@ -2510,8 +2510,8 @@ By translating canvas by returned offse typedef std::function BackendTextureReleaseProc; -Defines a function take one parameter of type -GrBackendTexture with no return value. +Defines a callback function, taking one parameter of type GrBackendTexture with +no return value. Function is called when back-end texture is to be released. ## MakeBackendTextureFromSkImage 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 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> fRawData; unordered_map> fLFOnly; + vector 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 fMaps; static MarkProps kMarkProps[Last_MarkType + 1]; forward_list 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* map = fMaps[(int) markType].fInclude; - if (!map) { - return reportError("invalid mark type"); - } - string name = this->uniqueName(*map, typeName); - Definition& markupDef = *(*map)[name]; - if (markupDef.fStart) { - return reportError("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 fMaps; unordered_map fIncludeMap; list fGlobals; unordered_map fIClassMap; @@ -1918,9 +1822,11 @@ protected: unordered_map fITypedefMap; unordered_map 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& 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& 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 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("invalid mark type"); + } + string name = this->uniqueName(*mapIter->fInclude, typeName); + Definition& markupDef = *(*mapIter->fInclude)[name]; + if (markupDef.fStart) { + return reportError("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("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("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 ] [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("expected description for const"); + this->indentDeferred(IndentKind::kConstOut); + if (fStructEnded) { + fIndent = fICSStack.size() * 4; + fStructEnded = false; } - fIndent -= 4; - this->writeCommentTrailer(OneLine::kNo); - fStart = memberStart->fContentStart; + // 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("expected description for const"); + } + fIndent -= 4; + this->writeCommentTrailer(OneLine::kNo); + } + 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& 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("cloned method not found"); + return child.reportError("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(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("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;