1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "bmhParser.h"
9 
10     // replace #Method description, #Param, #Return with #Populate
11     // if description, params, return are free of phrase refs
hackFiles()12 bool HackParser::hackFiles() {
13     string filename(fFileName);
14     size_t len = filename.length() - 1;
15     while (len > 0 && (isalnum(filename[len]) || '_' == filename[len] || '.' == filename[len])) {
16         --len;
17     }
18     filename = filename.substr(len + 1);
19     if (filename.substr(0, 2) != "Sk") {
20         return true;
21     }
22     size_t under = filename.find('_');
23     SkASSERT(under);
24     string className = filename.substr(0, under);
25     fOut = fopen(filename.c_str(), "wb");
26     if (!fOut) {
27         SkDebugf("could not open output file %s\n", filename.c_str());
28         return false;
29     }
30     auto mapEntry = fBmhParser.fClassMap.find(className);
31     if (fBmhParser.fClassMap.end() == mapEntry) {
32         remove(filename.c_str());
33         return true;
34     }
35     const Definition* classMarkup = &mapEntry->second;
36     const Definition* root = classMarkup->fParent;
37     SkASSERT(root);
38     SkASSERT(root->fTerminator);
39     SkASSERT('\n' == root->fTerminator[0]);
40     SkASSERT(!root->fParent);
41     fStart = root->fStart;
42     fChar = fStart;
43     fEnd = root->fTerminator;
44     this->replaceWithPop(root);
45     FPRINTF("%.*s", (int) (fEnd - fChar), fChar);
46     if ('\n' != fEnd[-1]) {
47         FPRINTF("\n");
48     }
49     fclose(fOut);
50     if (ParserCommon::WrittenFileDiffers(filename, root->fFileName)) {
51         SkDebugf("wrote %s\n", filename.c_str());
52     } else {
53         remove(filename.c_str());
54     }
55     return true;
56 }
57 
58 // returns true if topic has method
replaceWithPop(const Definition * root)59 void HackParser::replaceWithPop(const Definition* root) {
60     for (auto child : root->fChildren) {
61         if (MarkType::kClass == child->fMarkType || MarkType::kStruct == child->fMarkType
62                 || MarkType::kSubtopic == child->fMarkType) {
63             this->replaceWithPop(child);
64         }
65         if (MarkType::kMethod != child->fMarkType) {
66             continue;
67         }
68         auto& grans = child->fChildren;
69         if (grans.end() != std::find_if(grans.begin(), grans.end(),
70                 [](const Definition* def) {
71                     return MarkType::kPopulate == def->fMarkType
72                         || MarkType::kPhraseRef == def->fMarkType
73                         || MarkType::kFormula == def->fMarkType
74                         || MarkType::kAnchor == def->fMarkType
75                         || MarkType::kList == def->fMarkType
76                         || MarkType::kTable == def->fMarkType;
77                 } )) {
78             continue;
79         }
80         // write #Populate in place of description, #Param(s), #Return (if present)
81         const char* keep = child->fContentStart;
82         const char* next = nullptr;
83         for (auto gran : grans) {
84             if (MarkType::kIn == gran->fMarkType || MarkType::kLine == gran->fMarkType) {
85                 keep = gran->fTerminator;
86                 continue;
87             }
88             if (MarkType::kExample == gran->fMarkType
89                     || MarkType::kNoExample == gran->fMarkType) {
90                 next = gran->fStart;
91                 break;
92             }
93             if (MarkType::kParam == gran->fMarkType
94                     || MarkType::kReturn == gran->fMarkType
95                     || MarkType::kToDo == gran->fMarkType
96                     || MarkType::kComment == gran->fMarkType) {
97                 continue;
98             }
99             SkDebugf("");  // convenient place to set a breakpoint
100         }
101         SkASSERT(next);
102         FPRINTF("%.*s", (int) (keep - fChar), fChar);
103         if ('\n' != keep[-1]) {
104             FPRINTF("\n");
105         }
106         FPRINTF("#Populate\n\n");
107         fChar = next;
108     }
109 }
110