new batch of docs

new batch of docs

Docs-Preview: https://skia.org/?cl=141244
Bug: skia:
Change-Id: I5a285778baaee2734495374adeb7359d524e47e3
Reviewed-on: https://skia-review.googlesource.com/141244
Reviewed-by: Cary Clark <caryclark@skia.org>
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index d6594ea..eca7296 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -16,6 +16,7 @@
     { "",           KeyWord::kNone,         KeyProperty::kNone           },
     { "SK_API",     KeyWord::kSK_API,       KeyProperty::kModifier       },
     { "SK_BEGIN_REQUIRE_DENSE", KeyWord::kSK_BEGIN_REQUIRE_DENSE, KeyProperty::kModifier },
+    { "alignas",    KeyWord::kAlignAs,      KeyProperty::kModifier       },
     { "bool",       KeyWord::kBool,         KeyProperty::kNumber         },
     { "char",       KeyWord::kChar,         KeyProperty::kNumber         },
     { "class",      KeyWord::kClass,        KeyProperty::kObject         },
@@ -578,6 +579,9 @@
                 this->dumpMember(token);
                 continue;
             break;
+            case MarkType::kTypedef:
+                this->dumpTypedef(token, classDef.fName);
+            break;
             default:
                 SkASSERT(0);
         }
@@ -878,9 +882,10 @@
     this->lf(2);
 }
 
-bool IncludeParser::dumpGlobals() {
-    if (fIDefineMap.empty() && fIFunctionMap.empty() && fIEnumMap.empty() && fITemplateMap.empty()
-            && fITypedefMap.empty() && fIUnionMap.empty()) {
+bool IncludeParser::dumpGlobals(string* globalFileName, long int* globalTell) {
+    bool hasGlobals = !fIDefineMap.empty() || !fIFunctionMap.empty() || !fIEnumMap.empty()
+            || !fITemplateMap.empty()|| !fITypedefMap.empty() || !fIUnionMap.empty();
+    if (!hasGlobals) {
         return true;
     }
     size_t lastBSlash = fFileName.rfind('\\');
@@ -896,6 +901,7 @@
     lastSlash += 1;
     string globalsName = fFileName.substr(lastSlash, lastDotH - lastSlash);
     string fileName = globalsName + "_Reference.bmh";
+    *globalFileName = fileName;
     fOut = fopen(fileName.c_str(), "wb");
     if (!fOut) {
         SkDebugf("could not open output file %s\n", globalsName.c_str());
@@ -1007,9 +1013,10 @@
         }
         this->dumpCommonTail(*def);
     }
+    *globalTell = ftell(fOut);
     this->writeEndTag("Topic", topicName);
     this->lfAlways(1);
-    fclose(fOut);
+//    fclose(fOut);     // defer closing in case class needs to be also written here
     SkDebugf("wrote %s\n", fileName.c_str());
     return true;
 }
@@ -1038,6 +1045,45 @@
             || 0 == token.fName.find("private_");
 }
 
+bool IncludeParser::isMember(const Definition& token) const {
+    if ('f' == token.fStart[0] && isupper(token.fStart[1])) {
+        return true;
+    }
+    if (!islower(token.fStart[0])) {
+        return false;
+    }
+    // make an exception for SkTextBlob::RunBuffer, sole struct with members not in fXxxx format
+    if (string::npos != token.fFileName.find("SkTextBlob.h")) {
+        const Definition* structToken = token.fParent;
+        if (!structToken) {
+            return false;
+        }
+        if (KeyWord::kStruct != structToken->fKeyWord) {
+            structToken = token.fParent->fParent;
+            if (!structToken) {
+                return false;
+            }
+            if (KeyWord::kStruct != structToken->fKeyWord) {
+                return false;
+            }
+        }
+        SkASSERT(structToken->fTokens.size() > 0);
+        const Definition& child = structToken->fTokens.front();
+        string structName(child.fContentStart, child.length());
+        if ("RunBuffer" != structName) {
+            return false;
+        }
+        string tokenName(token.fContentStart, token.length());
+        string allowed[] = { "glyphs", "pos", "utf8text", "clusters" };
+        for (auto allow : allowed) {
+            if (allow == tokenName) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 bool IncludeParser::isOperator(const Definition& token) {
     return "operator" == token.fName.substr(0, 8);
 }
@@ -1083,34 +1129,48 @@
 }
 
 bool IncludeParser::dumpTokens() {
-    if (!this->dumpGlobals()) {
+    string globalFileName;
+    long int globalTell = 0;
+    if (!this->dumpGlobals(&globalFileName, &globalTell)) {
         return false;
     }
     for (const auto& member : fIClassMap) {
         if (string::npos != member.first.find("::")) {
             continue;
         }
-        if (!this->dumpTokens(member.first)) {
+        if (!this->dumpTokens(member.first, globalFileName, &globalTell)) {
             return false;
         }
     }
+    if (globalTell) {
+        fclose(fOut);
+    }
     return true;
 }
 
     // dump equivalent markup
-bool IncludeParser::dumpTokens(string skClassName) {
+bool IncludeParser::dumpTokens(string skClassName, string globalFileName, long int* globalTell) {
     string fileName = skClassName + "_Reference.bmh";
-    fOut = fopen(fileName.c_str(), "wb");
-    if (!fOut) {
-        SkDebugf("could not open output file %s\n", fileName.c_str());
-        return false;
+    if (globalFileName != fileName) {
+        fOut = fopen(fileName.c_str(), "wb");
+        if (!fOut) {
+            SkDebugf("could not open output file %s\n", fileName.c_str());
+            return false;
+        }
+    } else {
+        fseek(fOut, *globalTell, SEEK_SET);
+        this->lf(2);
+        this->writeBlockSeparator();
+        *globalTell = 0;
     }
     string prefixName = skClassName.substr(0, 2);
     string topicName = skClassName.length() > 2 && isupper(skClassName[2]) &&
         ("Sk" == prefixName || "Gr" == prefixName) ? skClassName.substr(2) : skClassName;
-    this->writeTagNoLF("Topic", topicName);
-    this->writeEndTag("Alias", topicName + "_Reference");
-    this->lf(2);
+    if (globalFileName != fileName) {
+        this->writeTagNoLF("Topic", topicName);
+        this->writeEndTag("Alias", topicName + "_Reference");
+        this->lf(2);
+    }
     auto& classMap = fIClassMap[skClassName];
     SkASSERT(KeyWord::kClass == classMap.fKeyWord || KeyWord::kStruct == classMap.fKeyWord);
     const char* containerType = KeyWord::kClass == classMap.fKeyWord ? "Class" : "Struct";
@@ -1258,6 +1318,15 @@
     return true;
 }
 
+void IncludeParser::dumpTypedef(const Definition& token, string className) {
+    this->writeTag("Typedef");
+    this->writeSpace();
+    this->writeString(token.fName);
+    this->writeTagTable("Line", "incomplete");
+    this->lf(2);
+    this->dumpComment(token);
+}
+
 bool IncludeParser::findComments(const Definition& includeDef, Definition* markupDef) {
     // add comment preceding class, if any
     const Definition* parent = includeDef.fParent;
@@ -1341,6 +1410,32 @@
     return parent ? parent->fBracket : Bracket::kNone;
 }
 
+bool IncludeParser::inAlignAs() const {
+    if (fParent->fTokens.size() < 2) {
+        return false;
+    }
+    auto reverseIter = fParent->fTokens.end();
+    bool checkForBracket = true;
+    while (fParent->fTokens.begin() != reverseIter) {
+        std::advance(reverseIter, -1);
+        if (checkForBracket) {
+            if (Definition::Type::kBracket != reverseIter->fType) {
+                return false;
+            }
+            if (Bracket::kParen != reverseIter->fBracket) {
+                return false;
+            }
+            checkForBracket = false;
+            continue;
+        }
+        if (Definition::Type::kKeyWord != reverseIter->fType) {
+            return false;
+        }
+        return KeyWord::kAlignAs == reverseIter->fKeyWord;
+    }
+    return false;
+}
+
 // caller just returns, so report error here
 bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
     SkASSERT(includeDef->fTokens.size() > 0);
@@ -1350,6 +1445,14 @@
         // todo : documentation is ignoring this for now
         iter = std::next(iter);
     }
+    bool hasAlignAs = iter->fKeyWord == KeyWord::kAlignAs;
+    if (hasAlignAs) {
+        iter = std::next(iter);
+        if (Definition::Type::kBracket != iter->fType || Bracket::kParen != iter->fBracket) {
+            return includeDef->reportError<bool>("expected alignas argument");
+        }
+        iter = std::next(iter);
+    }
     string nameStr(iter->fStart, iter->fContentEnd - iter->fStart);
     includeDef->fName = nameStr;
     iter = std::next(iter);
@@ -1378,7 +1481,18 @@
 //    if (1 != includeDef->fChildren.size()) {
 //        return false;  // fix me: SkCanvasClipVisitor isn't correctly parsed
 //    }
-    includeDef = includeDef->fChildren.front();
+    auto includeDefIter = includeDef->fChildren.begin();
+    if (hasAlignAs) {
+        SkASSERT(includeDef->fChildren.end() != includeDefIter);
+        SkASSERT(Bracket::kParen == (*includeDefIter)->fBracket);
+        std::advance(includeDefIter, 1);
+    }
+    if (includeDef->fChildren.end() != includeDefIter
+            && Bracket::kAngle == (*includeDefIter)->fBracket) {
+        std::advance(includeDefIter, 1);
+    }
+    includeDef = *includeDefIter;
+    SkASSERT(Bracket::kBrace == includeDef->fBracket);
     iter = includeDef->fTokens.begin();
     // skip until public
     int publicIndex = 0;
@@ -1402,7 +1516,7 @@
     const char* privateName = kKeyWords[(int) KeyWord::kPrivate].fName;
     size_t privateLen = strlen(privateName);
     auto childIter = includeDef->fChildren.begin();
-    while ((*childIter)->fPrivate) {
+    while (includeDef->fChildren.end() != childIter && (*childIter)->fPrivate) {
         std::advance(childIter, 1);
     }
     while (childIter != includeDef->fChildren.end()) {
@@ -1861,9 +1975,6 @@
         tokenIter = operatorCheck;
     }
     string nameStr(tokenIter->fStart, nameEnd - tokenIter->fStart);
-    if (string::npos != nameStr.find("sizeof")) {
-        SkDebugf("");
-    }
     if (addConst) {
         nameStr += "_const";
     }
@@ -2070,7 +2181,7 @@
                             fAttrDeprecated = &*tokenIter;
                             break;
                         }
-                        if ('f' == previousToken.fStart[0] && isupper(previousToken.fStart[1])) {
+                        if (this->isMember(*tokenIter)) {
                             break;
                         }
                         if (Bracket::kPound == child->fParent->fBracket &&
@@ -2391,7 +2502,7 @@
             if (match == this->topBracket()) {
                 this->popBracket();
                 if (!fInFunction) {
-                    fInFunction = ')' == test;
+                    fInFunction = ')' == test && !this->inAlignAs();
                 } else {
                     fInFunction = '}' != test;
                 }
@@ -2587,7 +2698,7 @@
                         fParent->fTokens.begin() != tokenIter; ) {
                     --tokenIter;
                     if (tokenIter->fLineCount == fLineCount) {
-                        if ('f' == tokenIter->fStart[0] && isupper(tokenIter->fStart[1])) {
+                        if (this->isMember(*tokenIter)) {
                             if (namedIter != fParent->fTokens.end()) {
                                 return reportError<bool>("found two named member tokens");
                             }