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>
This commit is contained in:
Cary Clark 2018-06-07 09:59:07 -04:00 committed by Skia Commit-Bot
parent d07dc361bc
commit 0d225395fa
12 changed files with 619 additions and 384 deletions

View File

@ -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.

View File

@ -2012,8 +2012,8 @@ By translating canvas by returned offset, Image appears stationary.
typedef std::function<void(GrBackendTexture)> 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.
##
# ------------------------------------------------------------------------------

View File

@ -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"
]

View File

@ -2,6 +2,7 @@ SkColor Reference
===
# <a name='Color'>Color</a>
Types, consts, functions, and macros for colors.
## Overview
@ -203,7 +204,7 @@ zero, fully transparent, to one, fully opaque.
typedef uint8_t <a href='#SkAlpha'>SkAlpha</a>;
</pre>
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.
## <a name='SkColor'>Typedef SkColor</a>
@ -761,8 +762,14 @@ modulo 360, where zero degrees is red.
## <a name='HSV_Saturation'>HSV Saturation</a>
<a href='#HSV_Saturation'>Saturation</a> represents the intensity of the color. <a href='#HSV_Saturation'>Saturation</a> varies from zero,
with no <a href='#HSV_Hue'>Hue</a> contribution; to one, with full <a href='#HSV_Hue'>Hue</a> contribution.
## <a name='HSV_Value'>HSV Value</a>
<a href='#HSV_Value'>Value</a> represents the lightness of the color. <a href='#HSV_Value'>Value</a> varies from zero, black; to
one, full brightness.
<a name='SkRGBToHSV'></a>
## SkRGBToHSV
@ -771,9 +778,9 @@ void <a href='#SkRGBToHSV'>SkRGBToHSV</a>(<a href='undocumented#U8CPU'>U8CPU</a>
</pre>
Converts RGB to its <a href='#HSV'>HSV</a> components.
<a href='#SkRGBToHSV_hsv'>hsv</a>[0] contains <a href='#HSV_Hue'>Hue</a>, a value from zero to less than 360.
<a href='#SkRGBToHSV_hsv'>hsv</a>[1] contains <a href='#HSV_Saturation'>Saturation</a>, a value from zero to one.
<a href='#SkRGBToHSV_hsv'>hsv</a>[2] contains <a href='#HSV_Value'>Value</a>, a value from zero to one.
<a href='#SkRGBToHSV_hsv'>hsv</a>[0] contains <a href='#HSV_Hue'>HSV Hue</a>, a value from zero to less than 360.
<a href='#SkRGBToHSV_hsv'>hsv</a>[1] contains <a href='#HSV_Saturation'>HSV Saturation</a>, a value from zero to one.
<a href='#SkRGBToHSV_hsv'>hsv</a>[2] contains <a href='#HSV_Value'>HSV Value</a>, a value from zero to one.
### Parameters
@ -809,9 +816,9 @@ void <a href='#SkColorToHSV'>SkColorToHSV</a>(<a href='#SkColor'>SkColor</a> col
</pre>
Converts ARGB to its <a href='#HSV'>HSV</a> components. <a href='#Alpha'>Alpha</a> in ARGB is ignored.
<a href='#SkColorToHSV_hsv'>hsv</a>[0] contains <a href='#HSV_Hue'>Hue</a>, and is assigned a value from zero to less than 360.
<a href='#SkColorToHSV_hsv'>hsv</a>[1] contains <a href='#HSV_Saturation'>Saturation</a>, a value from zero to one.
<a href='#SkColorToHSV_hsv'>hsv</a>[2] contains <a href='#HSV_Value'>Value</a>, a value from zero to one.
<a href='#SkColorToHSV_hsv'>hsv</a>[0] contains <a href='#HSV_Hue'>HSV Hue</a>, and is assigned a value from zero to less than 360.
<a href='#SkColorToHSV_hsv'>hsv</a>[1] contains <a href='#HSV_Saturation'>HSV Saturation</a>, a value from zero to one.
<a href='#SkColorToHSV_hsv'>hsv</a>[2] contains <a href='#HSV_Value'>HSV Value</a>, a value from zero to one.
### Parameters
@ -841,9 +848,9 @@ Converts ARGB to its <a href='#HSV'>HSV</a> components. <a href='#Alpha'>Alpha</
</pre>
Converts <a href='#HSV'>HSV</a> components to an ARGB color. <a href='#Alpha'>Alpha</a> is passed through unchanged.
<a href='#SkHSVToColor_hsv'>hsv</a>[0] represents <a href='#HSV_Hue'>Hue</a>, an angle from zero to less than 360.
<a href='#SkHSVToColor_hsv'>hsv</a>[1] represents <a href='#HSV_Saturation'>Saturation</a>, and varies from zero to one.
<a href='#SkHSVToColor_hsv'>hsv</a>[2] represents <a href='#HSV_Value'>Value</a>, and varies from zero to one.
<a href='#SkHSVToColor_hsv'>hsv</a>[0] represents <a href='#HSV_Hue'>HSV Hue</a>, an angle from zero to less than 360.
<a href='#SkHSVToColor_hsv'>hsv</a>[1] represents <a href='#HSV_Saturation'>HSV Saturation</a>, and varies from zero to one.
<a href='#SkHSVToColor_hsv'>hsv</a>[2] represents <a href='#HSV_Value'>HSV Value</a>, and varies from zero to one.
Out of range <a href='#SkHSVToColor_hsv'>hsv</a> values are pinned.
@ -877,10 +884,10 @@ ARGB equivalent to <a href='#HSV'>HSV</a>
<a href='#SkColor'>SkColor</a> <a href='#SkHSVToColor'>SkHSVToColor</a>(const <a href='undocumented#SkScalar'>SkScalar</a> hsv[3])
</pre>
Convert <a href='#HSV'>HSV</a> components to an ARGB color. <a href='#Alpha'>Alpha</a> is set to 0xFF.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[0] represents <a href='#HSV_Hue'>Hue</a>, an angle from zero to less than 360.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[1] represents <a href='#HSV_Saturation'>Saturation</a>, and varies from zero to one.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[2] represents <a href='#HSV_Value'>Value</a>, and varies from zero to one.
Converts <a href='#HSV'>HSV</a> components to an ARGB color. <a href='#Alpha'>Alpha</a> is set to 255.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[0] represents <a href='#HSV_Hue'>HSV Hue</a>, an angle from zero to less than 360.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[1] represents <a href='#HSV_Saturation'>HSV Saturation</a>, and varies from zero to one.
<a href='#SkHSVToColor_2_hsv'>hsv</a>[2] represents <a href='#HSV_Value'>HSV Value</a>, and varies from zero to one.
Out of range <a href='#SkHSVToColor_2_hsv'>hsv</a> values are pinned.

View File

@ -2510,8 +2510,8 @@ By translating canvas by returned <a href='#SkImage_makeWithFilter_offset'>offse
typedef std::function<void(GrBackendTexture)> <a href='#SkImage_BackendTextureReleaseProc'>BackendTextureReleaseProc</a>;
</pre>
Defines a function take one parameter of type
<a href='undocumented#GrBackendTexture'>GrBackendTexture</a> with no return value.
Defines a callback function, taking one parameter of type <a href='undocumented#GrBackendTexture'>GrBackendTexture</a> with
no return value. Function is called when back-end texture is to be released.
<a name='SkImage_MakeBackendTextureFromSkImage'></a>
## MakeBackendTextureFromSkImage

View File

@ -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:

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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;
}
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<void>("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<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 ?

View File

@ -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:

View File

@ -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]);

View File

@ -187,6 +187,8 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kExternal:
break;
case MarkType::kFile:
break;
case MarkType::kFormula:
fInFormula = true;
break;