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