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