• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 #ifndef mdOut_DEFINED
9 #define mdOut_DEFINED
10 
11 #include "parserCommon.h"
12 
13 class IncludeParser;
14 
15 class MdOut : public ParserCommon {
16 public:
17     struct SubtopicDescriptions {
18         string fSingular;
19         string fPlural;
20         string fOneLiner;
21         string fDetails;
22     };
23 
MdOut(BmhParser & bmh,IncludeParser & inc)24     MdOut(BmhParser& bmh, IncludeParser& inc) : ParserCommon()
25         , fBmhParser(bmh)
26         , fIncludeParser(inc) {
27         this->reset();
28         this->addPopulators();
29         fBmhParser.setUpGlobalSubstitutes();
30         fNames = &fBmhParser.fGlobalNames;
31     }
32 
33     bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
34     bool buildStatus(const char* docDir, const char* mdOutDir);
35     void checkAnchors();
36 
37 private:
38     enum class TableState {
39         kNone,
40         kRow,
41         kColumn,
42     };
43 
44     struct AnchorDef {
45         string fDef;
46         MarkType fMarkType;
47     };
48 
49     struct DefinedState {
DefinedStateDefinedState50         DefinedState(const MdOut& mdOut, const char* refStart, const char* refEnd,
51                 Resolvable resolvable)
52             : fBmhParser(&mdOut.fBmhParser)
53             , fNames(mdOut.fNames)
54             , fGlobals(&mdOut.fBmhParser.fGlobalNames)
55             , fLastDef(mdOut.fLastDef)
56             , fMethod(mdOut.fMethod)
57             , fSubtopic(mdOut.fSubtopic)
58             , fRoot(mdOut.fRoot)
59             , fRefStart(refStart)
60             , fRefEnd(refEnd)
61             , fResolvable(resolvable)
62             , fInProgress(mdOut.fInProgress) {
63             TextParser matrixParser(fLastDef->fFileName, refStart, refEnd, fLastDef->fLineCount);
64             const char* bracket = matrixParser.anyOf("|=\n");
65             fInMatrix = bracket && ('|' == bracket[0] || '=' == bracket[0]);
66         }
67 
backupDefinedState68         void backup() {
69             fPriorWord = fBack2Word;
70             fPriorLink = "";
71             fPriorSeparator = "";
72             fSeparator = fBack2Separator;
73         }
74 
findEndDefinedState75         bool findEnd(const char* start) {
76             if (fEnd < fRefEnd && '~' == fEnd[0]) {
77                 ++fEnd;
78             }
79             do {
80                 while (fEnd < fRefEnd && (isalnum(fEnd[0]) || '-' == fEnd[0] || '_' == fEnd[0])) {
81                     ++fEnd;
82                 }
83                 if (fEnd + 1 >= fRefEnd || '/' != fEnd[0] || start == fEnd || !isalpha(fEnd[-1])
84                         || !isalpha(fEnd[1])) {
85                     break;  // stop unless pattern is xxx/xxx as in I/O
86                 }
87                 ++fEnd; // skip slash
88             } while (true);
89             while (start != fEnd && '-' == fEnd[-1]) {
90                 --fEnd;
91             }
92             return start == fEnd;
93         }
94 
95         bool findLink(string ref, string* linkPtr, bool addParens);
96         bool findLink(string ref, string* linkPtr, unordered_map<string, Definition*>& map);
97         bool hasWordSpace(string wordSpace) const;
98         void setLink();
99 
nextSeparatorDefinedState100         string nextSeparator(const char* start) {
101             fBack2Separator = fPriorSeparator;
102             fPriorSeparator = fSeparator;
103             fEnd = start;
104             return fBack2Separator;
105         }
106 
nextWordDefinedState107         const char* nextWord() {
108             fBack2Word = fPriorWord;
109             fPriorWord = fWord;
110             fPriorLink = fLink;
111             return fEnd;
112         }
113 
114         bool phraseContinues(string phrase, string* priorWord, string* priorLink) const;
115 
setLowerDefinedState116         void setLower() {
117             fAddParens = false;
118             bool allLower = std::all_of(fWord.begin(), fWord.end(), [](char c) {
119                 return islower(c);
120             });
121             bool hasParens = fEnd + 2 <= fRefEnd && "()" == string(fEnd, 2);
122             if (hasParens) {
123                 if (allLower) {
124                     fWord += "()";
125                     fEnd += 2;
126                 }
127             } else if (allLower) {
128                 fAddParens = true;
129             }
130         }
131 
setPriorSpaceWordDefinedState132         bool setPriorSpaceWord(const char** startPtr) {
133             if (!fPriorSpace) {
134                 return false;
135             }
136             string phrase = fPriorWord + fWord;
137             if (this->phraseContinues(phrase, &fPriorWord, &fPriorLink)) {
138                 *startPtr = fEnd;
139                 return true;
140             }
141             fPriorWord = fPriorWord.substr(0, fPriorWord.length() - 1);
142             return false;
143         }
144 
skipParensDefinedState145         void skipParens() {
146             if ("()" == fSeparator.substr(0, 2)) {
147                 string funcRef = fPriorWord + "()";
148                 if (this->findLink(funcRef, &fPriorLink, false)) {
149                     fPriorWord = funcRef;
150                     fSeparator = fSeparator.substr(2);
151                 }
152             }
153         }
154 
skipWhiteSpaceDefinedState155         const char* skipWhiteSpace() {
156             const char* start = fSeparatorStart;
157             bool whiteSpace = start < fRefEnd && ' ' >= start[0];
158             while (start < fRefEnd && !isalpha(start[0]) && '~' != start[0]) {
159                 whiteSpace &= ' ' >= start[0];
160                 ++start;
161             }
162             fPriorSpace = false;
163             fSeparator = string(fSeparatorStart, start - fSeparatorStart);
164             if ("" != fPriorWord && whiteSpace) {
165                 string wordSpace = fPriorWord + ' ';
166                 if (this->hasWordSpace(wordSpace)) {
167                     fPriorWord = wordSpace;
168                     fPriorSpace = true;
169                 }
170             }
171             return start;
172         }
173 
174         string fRef;
175         string fBack2Word;
176         string fBack2Separator;
177         string fPriorWord;
178         string fPriorLink;
179         string fPriorSeparator;
180         string fWord;
181         string fLink;
182         string fSeparator;
183         string fMethodName;
184         BmhParser* fBmhParser;
185         const NameMap* fNames;
186         const NameMap* fGlobals;
187         const Definition* fLastDef;
188         const Definition* fMethod;
189         const Definition* fSubtopic;
190         const Definition* fPriorDef;
191         const RootDefinition* fRoot;
192         const char* fSeparatorStart;
193         const char* fRefStart;
194         const char* fRefEnd;
195         const char* fEnd;
196         Resolvable fResolvable;
197         bool fAddParens;
198         bool fInMatrix;
199         bool fInProgress;
200         bool fPriorSpace;
201     };
202 
203     void addCodeBlock(const Definition* def, string& str) const;
204     void addPopulators();
205     string addReferences(const char* start, const char* end, Resolvable );
206     string anchorDef(string def, string name);
207     string anchorLocalRef(string ref, string name);
208     string anchorRef(string def, string name);
209     bool buildRefFromFile(const char* fileName, const char* outDir);
210     bool checkParamReturnBody(const Definition* def);
211     Definition* checkParentsForMatch(Definition* test, string ref) const;
212     void childrenOut(Definition* def, const char* contentStart);
213     Definition* csParent();
214     const Definition* findParamType();
215     string getMemberTypeName(const Definition* def, string* memberType);
216     static bool HasDetails(const Definition* def);
217     void htmlOut(string );
218     bool isDefined(DefinedState& s);
219     const Definition* isDefined(const TextParser& , Resolvable );
220     string linkName(const Definition* ) const;
221     void markTypeOut(Definition* , const Definition** prior);
mdHeaderOut(int depth)222     void mdHeaderOut(int depth) { mdHeaderOutLF(depth, 2); }
223     void mdHeaderOutLF(int depth, int lf);
224     void parameterHeaderOut(TextParser& paramParser, const Definition** prior, Definition* def);
225     void parameterTrailerOut();
parseFromFile(const char * path)226     bool parseFromFile(const char* path) override { return true; }
227     void populateOne(Definition* def,
228             unordered_map<string, RootDefinition::SubtopicContents>& populator);
229     void populateTables(const Definition* def, RootDefinition* );
230 
populator(string key)231     SubtopicDescriptions& populator(string key) {
232         auto entry = fPopulators.find(key);
233         // FIXME: this should have been detected earlier
234         SkASSERT(fPopulators.end() != entry);
235         return entry->second;
236     }
237 
reset()238     void reset() override {
239         INHERITED::resetCommon();
240         fNames = nullptr;
241         fEnumClass = nullptr;
242         fMethod = nullptr;
243         fRoot = nullptr;
244         fSubtopic = nullptr;
245         fLastParam = nullptr;
246         fTableState = TableState::kNone;
247         fAddRefFailed = false;
248         fHasFiddle = false;
249         fInDescription = false;
250         fInList = false;
251         fResolveAndIndent = false;
252         fLiteralAndIndent = false;
253         fLastDef = nullptr;
254         fParamEnd = nullptr;
255         fInProgress = false;
256     }
257 
resolvable(const Definition * definition)258     Resolvable resolvable(const Definition* definition) const {
259         MarkType markType = definition->fMarkType;
260         if (MarkType::kCode == markType) {
261             for (auto child : definition->fChildren) {
262                 if (MarkType::kLiteral == child->fMarkType) {
263                     return Resolvable::kLiteral;
264                 }
265             }
266         }
267         if ((MarkType::kExample == markType
268                 || MarkType::kFunction == markType) && fHasFiddle) {
269             return Resolvable::kNo;
270         }
271         return BmhParser::kMarkProps[(int) markType].fResolve;
272     }
273 
274     void resolveOut(const char* start, const char* end, Resolvable );
275     void returnHeaderOut(const Definition** prior, Definition* def);
276     void rowOut(string col1, const Definition* col2);
277     void rowOut(const char * name, string description, bool literalName);
278 
279     void subtopicOut(string name);
280     void subtopicsOut(Definition* def);
281     void subtopicOut(string key, const vector<Definition*>& data, const Definition* csParent,
282         const Definition* topicParent, bool showClones);
283     bool subtopicRowOut(string keyName, const Definition* entry);
284     void summaryOut(const Definition* def, MarkType , string name);
285     string tableDataCodeDef(const Definition* def);
286     string tableDataCodeDef(string def, string name);
287     string tableDataCodeLocalRef(string name);
288     string tableDataCodeLocalRef(string ref, string name);
289     string tableDataCodeRef(const Definition* ref);
290     string tableDataCodeRef(string ref, string name);
291     void writeSubtopicTableHeader(string key);
292 
293     vector<const Definition*> fClassStack;
294     unordered_map<string, vector<AnchorDef> > fAllAnchorDefs;
295     unordered_map<string, vector<string> > fAllAnchorRefs;
296     NameMap* fNames;
297     BmhParser& fBmhParser;
298     IncludeParser& fIncludeParser;
299     const Definition* fEnumClass;
300     const Definition* fLastDef;
301     Definition* fMethod;
302     RootDefinition* fRoot;  // used in generating populated tables; always struct or class
303     RootDefinition* fSubtopic; // used in resolving symbols
304     const Definition* fLastParam;
305     TableState fTableState;
306     unordered_map<string, SubtopicDescriptions> fPopulators;
307     unordered_map<string, string> fPhraseParams;
308     const char* fParamEnd;
309     bool fAddRefFailed;
310     bool fHasFiddle;
311     bool fInDescription;   // FIXME: for now, ignore unfound camelCase in description since it may
312                            // be defined in example which at present cannot be linked to
313     bool fInList;
314     bool fLiteralAndIndent;
315     bool fResolveAndIndent;
316     bool fOddRow;
317     bool fHasDetails;
318     bool fInProgress;
319     typedef ParserCommon INHERITED;
320 };
321 
322 #endif
323