blob: 434c8029771154b262f2f5747f2fdb712c25b852 [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();
Cary Clarkcb6bef02018-11-29 12:05:25 -050030 fNames = &fBmhParser.fGlobalNames;
Cary Clark2da9fb82018-11-01 09:29:36 -040031 }
32
33 bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
34 bool buildStatus(const char* docDir, const char* mdOutDir);
35 void checkAnchors();
36
37private:
38 enum class TableState {
39 kNone,
40 kRow,
41 kColumn,
42 };
43
44 struct AnchorDef {
45 string fDef;
46 MarkType fMarkType;
47 };
48
Cary Clark77b3f3a2018-11-07 14:59:03 -050049 struct DefinedState {
50 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
68 void backup() {
69 fPriorWord = fBack2Word;
70 fPriorLink = "";
71 fPriorSeparator = "";
72 fSeparator = fBack2Separator;
73 }
74
75 bool findEnd(const char* start) {
Cary Clarkcb6bef02018-11-29 12:05:25 -050076 if (fEnd < fRefEnd && '~' == fEnd[0]) {
77 ++fEnd;
78 }
Cary Clark77b3f3a2018-11-07 14:59:03 -050079 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
100 string nextSeparator(const char* start) {
101 fBack2Separator = fPriorSeparator;
102 fPriorSeparator = fSeparator;
103 fEnd = start;
104 return fBack2Separator;
105 }
106
107 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
116 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
132 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
145 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
155 const char* skipWhiteSpace() {
156 const char* start = fSeparatorStart;
157 bool whiteSpace = start < fRefEnd && ' ' >= start[0];
Cary Clarkcb6bef02018-11-29 12:05:25 -0500158 while (start < fRefEnd && !isalpha(start[0]) && '~' != start[0]) {
Cary Clark77b3f3a2018-11-07 14:59:03 -0500159 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
Cary Clark2da9fb82018-11-01 09:29:36 -0400203 void addCodeBlock(const Definition* def, string& str) const;
204 void addPopulators();
Cary Clark2da9fb82018-11-01 09:29:36 -0400205 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();
Cary Clark77b3f3a2018-11-07 14:59:03 -0500214 const Definition* findParamType();
Cary Clark2da9fb82018-11-01 09:29:36 -0400215 string getMemberTypeName(const Definition* def, string* memberType);
216 static bool HasDetails(const Definition* def);
Cary Clark2da9fb82018-11-01 09:29:36 -0400217 void htmlOut(string );
Cary Clark77b3f3a2018-11-07 14:59:03 -0500218 bool isDefined(DefinedState& s);
219 const Definition* isDefined(const TextParser& , Resolvable );
Cary Clark2da9fb82018-11-01 09:29:36 -0400220 string linkName(const Definition* ) const;
Cary Clark2da9fb82018-11-01 09:29:36 -0400221 void markTypeOut(Definition* , const Definition** prior);
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();
226 bool parseFromFile(const char* path) override { return true; }
Cary Clark2da9fb82018-11-01 09:29:36 -0400227 void populateOne(Definition* def,
228 unordered_map<string, RootDefinition::SubtopicContents>& populator);
229 void populateTables(const Definition* def, RootDefinition* );
230
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
238 void reset() override {
239 INHERITED::resetCommon();
Cary Clarkcb6bef02018-11-29 12:05:25 -0500240 fNames = nullptr;
Cary Clark2da9fb82018-11-01 09:29:36 -0400241 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
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