blob: 41f85cb2fb49ac6685cde0c4c7f56479fd5c7295 [file] [log] [blame]
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <iostream>
18#include <sstream>
19
20#include "Generator.h"
21#include "Specification.h"
22#include "Utilities.h"
23
24using namespace std;
25
26struct DetailedFunctionEntry {
27 VersionInfo info;
28 string htmlDeclaration;
29};
30
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070031static const char OVERVIEW_HTML_FILE_NAME[] = "overview.html";
32static const char OVERVIEW_JD_FILE_NAME[] = "overview.jd";
33static const char INDEX_HTML_FILE_NAME[] = "index.html";
34static const char INDEX_JD_FILE_NAME[] = "index.jd";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -070035
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070036static void writeHeader(GeneratedFile* file, bool forVerification, const string& title) {
37 if (forVerification) {
38 *file << "<!DOCTYPE html>\n";
39 *file << "<!-- " << AUTO_GENERATED_WARNING << "-->\n";
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -070040 *file << "<html><head>\n"
41 "<title>RenderScript Reference</title>\n"
42 "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070043 "<link rel='stylesheet' "
44 "href='http://fonts.googleapis.com/css?family=Roboto+Condensed'>\n"
45 "<link rel='stylesheet' href='http://fonts.googleapis.com/"
46 "css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold' "
47 "title='roboto'>\n"
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -070048 "<link href='default.css' rel='stylesheet' type='text/css'>\n"
49 "<link href='fullscreen.css' rel='stylesheet' class='fullscreen' "
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070050 "type='text/css'>\n"
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -070051 "<body class='gc-documentation develop reference'>\n\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070052 *file << "<h1>" << title << "</h1>\n";
53 } else {
54 *file << "page.title=RenderScript " << title << "\n\n";
55 *file << "@jd:body\n\n";
56 }
Jean-Luc Brouillet918944e2015-04-30 11:12:40 -070057 *file << "<div class='renderscript'>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -070058}
59
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070060static void writeFooter(GeneratedFile* file, bool forVerification) {
Jean-Luc Brouillet918944e2015-04-30 11:12:40 -070061 *file << "</div>\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070062 if (forVerification) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -070063 *file << "</body></html>\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070064 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -070065}
66
67// If prefix starts input, copy it to stream and remove it from input.
68static void skipPrefix(ostringstream* stream, string* input, const string& prefix) {
69 size_t size = prefix.size();
70 if (input->compare(0, size, prefix) != 0) {
71 return;
72 }
73 input->erase(0, size);
74 *stream << prefix;
75}
76
77// Merge b into a. Returns true if successful
78static bool mergeVersionInfo(VersionInfo* a, const VersionInfo& b) {
79 if (a->intSize != b.intSize) {
80 cerr << "Error. We don't currently support versions that differ based on int size\n";
81 return false;
82 }
83 if (b.minVersion != 0 && a->maxVersion == b.minVersion - 1) {
84 a->maxVersion = b.maxVersion;
85 } else if (b.maxVersion != 0 && a->minVersion == b.maxVersion + 1) {
86 a->minVersion = b.minVersion;
87 } else {
88 cerr << "Error. This code currently assume that all versions are contiguous. Don't know "
89 "how to merge versions (" << a->minVersion << " - " << a->maxVersion << ") and ("
90 << b.minVersion << " - " << b.maxVersion << ")\n";
91 return false;
92 }
93 return true;
94}
95
96static string getHtmlStringForType(const ParameterDefinition& parameter) {
97 string s = parameter.rsType;
98 ostringstream stream;
99 skipPrefix(&stream, &s, "const ");
100 skipPrefix(&stream, &s, "volatile ");
101 bool endsWithAsterisk = s.size() > 0 && s[s.size() - 1] == '*';
102 if (endsWithAsterisk) {
103 s.erase(s.size() - 1, 1);
104 }
105
106 string anchor = systemSpecification.getHtmlAnchor(s);
107 if (anchor.empty()) {
108 // Not a RenderScript specific type.
109 return parameter.rsType;
110 } else {
111 stream << anchor;
112 }
113 if (endsWithAsterisk) {
114 stream << "*";
115 }
116 return stream.str();
117}
118
119static string getDetailedHtmlDeclaration(const FunctionPermutation& permutation) {
120 ostringstream stream;
121 auto ret = permutation.getReturn();
122 if (ret) {
123 stream << getHtmlStringForType(*ret);
124 } else {
125 stream << "void";
126 }
127 stream << " " << permutation.getName() << "(";
128 bool needComma = false;
129 for (auto p : permutation.getParams()) {
130 if (needComma) {
131 stream << ", ";
132 }
133 stream << getHtmlStringForType(*p);
134 if (p->isOutParameter) {
135 stream << "*";
136 }
137 if (!p->specName.empty()) {
138 stream << " " << p->specName;
139 }
140 needComma = true;
141 }
142 stream << ");\n";
143 return stream.str();
144}
145
146/* Some functions (like max) have changed implementations but not their
147 * declaration. We need to unify these so that we don't end up with entries
148 * like:
149 * char max(char a, char b); Removed from API level 20
150 * char max(char a, char b); Added to API level 20
151 */
152static bool getUnifiedFunctionPrototypes(Function* function,
153 map<string, DetailedFunctionEntry>* entries) {
154 for (auto f : function->getSpecifications()) {
155 DetailedFunctionEntry entry;
156 entry.info = f->getVersionInfo();
157 for (auto p : f->getPermutations()) {
158 entry.htmlDeclaration = getDetailedHtmlDeclaration(*p);
159 const string s = stripHtml(entry.htmlDeclaration);
160 auto i = entries->find(s);
161 if (i == entries->end()) {
162 entries->insert(pair<string, DetailedFunctionEntry>(s, entry));
163 } else {
164 if (!mergeVersionInfo(&i->second.info, entry.info)) {
165 return false;
166 }
167 }
168 }
169 }
170 return true;
171}
172
173// Convert words starting with @ into HTML references. Returns false if error.
174static bool convertDocumentationRefences(string* s) {
175 bool success = true;
176 size_t end = 0;
177 for (;;) {
178 size_t start = s->find('@', end);
179 if (start == string::npos) {
180 break;
181 }
182 // Find the end of the identifier
183 end = start;
184 char c;
185 do {
186 c = (*s)[++end];
187 } while (isalnum(c) || c == '_');
188
189 const string id = s->substr(start + 1, end - start - 1);
190 string anchor = systemSpecification.getHtmlAnchor(id);
191 if (anchor.empty()) {
192 cerr << "Error: Can't convert the documentation reference @" << id << "\n";
193 success = false;
194 }
195 s->replace(start, end - start, anchor);
196 }
197 return success;
198}
199
200static bool generateHtmlParagraphs(GeneratedFile* file, const vector<string>& description) {
201 bool inParagraph = false;
202 for (auto s : description) {
203 // Empty lines in the .spec marks paragraphs.
204 if (s.empty()) {
205 if (inParagraph) {
206 *file << "</p>\n";
207 inParagraph = false;
208 }
209 } else {
210 if (!inParagraph) {
211 *file << "<p> ";
212 inParagraph = true;
213 }
214 }
215 if (!convertDocumentationRefences(&s)) {
216 return false;
217 }
218 *file << s << "\n";
219 }
220 if (inParagraph) {
221 *file << "</p>\n";
222 }
223 return true;
224}
225
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700226static void writeSummaryTableStart(GeneratedFile* file, const string& label, bool labelIsHeading) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700227 if (labelIsHeading) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700228 *file << "<h2 style='margin-bottom: 0px;'>" << label << "</h2>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700229 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700230 *file << "<table class='jd-sumtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700231 if (!labelIsHeading) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700232 *file << " <tr><th colspan='2'>" << label << "</th></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700233 }
234}
235
236static void writeSummaryTableEnd(GeneratedFile* file) {
237 *file << "</tbody></table>\n";
238}
239
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700240enum DeprecatedSelector {
241 DEPRECATED_ONLY,
242 NON_DEPRECATED_ONLY,
243 ALL,
244};
245
246static void writeSummaryTableEntry(ostream* stream, Definition* definition,
247 DeprecatedSelector deprecatedSelector) {
248 if (definition->hidden()) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700249 return;
250 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700251 const bool deprecated = definition->deprecated();
252 if ((deprecatedSelector == DEPRECATED_ONLY && !deprecated) ||
253 (deprecatedSelector == NON_DEPRECATED_ONLY && deprecated)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700254 return;
255 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700256
257 *stream << " <tr class='alt-color api apilevel-1'>\n";
258 *stream << " <td class='jd-linkcol'>\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700259 *stream << " <a href='" << definition->getUrl() << "'>" << definition->getName()
260 << "</a>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700261 *stream << " </td>\n";
262 *stream << " <td class='jd-descrcol' width='100%'>\n";
263 *stream << " ";
264 if (deprecated) {
265 *stream << "<b>Deprecated</b>. ";
266 }
267 *stream << definition->getSummary() << "\n";
268 *stream << " </td>\n";
269 *stream << " </tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700270}
271
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700272static void writeSummaryTable(GeneratedFile* file, const ostringstream* entries, const char* name,
273 DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
274 string s = entries->str();
275 if (!s.empty()) {
276 string prefix;
277 if (deprecatedSelector == DEPRECATED_ONLY) {
278 prefix = "Deprecated ";
279 }
280 writeSummaryTableStart(file, prefix + name, labelAsHeader);
281 *file << s;
282 writeSummaryTableEnd(file);
283 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700284}
285
286static void writeSummaryTables(GeneratedFile* file, const map<string, Constant*>& constants,
287 const map<string, Type*>& types,
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700288 const map<string, Function*>& functions,
289 DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
290 ostringstream constantStream;
291 for (auto e : constants) {
292 writeSummaryTableEntry(&constantStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700293 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700294 writeSummaryTable(file, &constantStream, "Constants", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700295
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700296 ostringstream typeStream;
297 for (auto e : types) {
298 writeSummaryTableEntry(&typeStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700299 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700300 writeSummaryTable(file, &typeStream, "Types", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700301
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700302 ostringstream functionStream;
303 for (auto e : functions) {
304 writeSummaryTableEntry(&functionStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700305 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700306 writeSummaryTable(file, &functionStream, "Functions", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700307}
308
Stephen Hinesca51c782015-08-25 23:43:34 -0700309static void writeHtmlVersionTag(GeneratedFile* file, VersionInfo info,
310 bool addSpacing) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700311 ostringstream stream;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700312 if (info.intSize == 32) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700313 stream << "When compiling for 32 bits. ";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700314 } else if (info.intSize == 64) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700315 stream << "When compiling for 64 bits. ";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700316 }
317
318 if (info.minVersion > 1 || info.maxVersion) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700319 const char* mid =
320 "<a "
321 "href='http://developer.android.com/guide/topics/manifest/"
322 "uses-sdk-element.html#ApiLevels'>API level ";
323 if (info.minVersion <= 1) {
324 // No minimum
325 if (info.maxVersion > 0) {
Jean-Luc Brouilletffc17102015-08-13 22:47:06 -0700326 stream << "Removed from " << mid << info.maxVersion + 1 << " and higher";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700327 }
328 } else {
329 if (info.maxVersion == 0) {
330 // No maximum
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700331 stream << "Added in " << mid << info.minVersion;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700332 } else {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700333 stream << mid << info.minVersion << " - " << info.maxVersion;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700334 }
335 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700336 stream << "</a>";
337 }
Stephen Hinesca51c782015-08-25 23:43:34 -0700338 string s = stream.str();
339 // Remove any trailing whitespace
340 while (s.back() == ' ') {
341 s.pop_back();
342 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700343 if (!s.empty()) {
Stephen Hinesca51c782015-08-25 23:43:34 -0700344 *file << (addSpacing ? " " : "") << s << "\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700345 }
346}
347
Jean-Luc Brouillet36e2be52015-04-30 14:41:24 -0700348static void writeDetailedTypeSpecification(GeneratedFile* file, const TypeSpecification* spec) {
349 switch (spec->getKind()) {
350 case SIMPLE: {
351 Type* type = spec->getType();
352 *file << "<p>A typedef of: " << spec->getSimpleType()
Stephen Hinesca51c782015-08-25 23:43:34 -0700353 << makeAttributeTag(spec->getAttribute(), "", type->getDeprecatedApiLevel(),
Jean-Luc Brouillet36e2be52015-04-30 14:41:24 -0700354 type->getDeprecatedMessage())
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700355 << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
Stephen Hinesca51c782015-08-25 23:43:34 -0700356 writeHtmlVersionTag(file, spec->getVersionInfo(), false);
357 *file << "</p>\n";
358 break;
359 }
360 case RS_OBJECT: {
361 *file << "<p>";
362 writeHtmlVersionTag(file, spec->getVersionInfo(), false);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700363 *file << "</p>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700364 break;
Jean-Luc Brouillet36e2be52015-04-30 14:41:24 -0700365 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700366 case ENUM: {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700367 *file << "<p>An enum with the following values:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n";
Stephen Hinesca51c782015-08-25 23:43:34 -0700368 writeHtmlVersionTag(file, spec->getVersionInfo(), false);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700369 *file << "</p>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700370
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700371 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouillet36e2be52015-04-30 14:41:24 -0700372 const vector<string>& values = spec->getValues();
373 const vector<string>& valueComments = spec->getValueComments();
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700374 for (size_t i = 0; i < values.size(); i++) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700375 *file << " <tr><th>" << values[i] << "</th><td>";
376 if (valueComments.size() > i) {
377 *file << valueComments[i];
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700378 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700379 *file << "</td></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700380 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700381 *file << " </tbody></table><br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700382 break;
383 }
384 case STRUCT: {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700385 *file << "<p>A structure with the following fields:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
Stephen Hinesca51c782015-08-25 23:43:34 -0700386 writeHtmlVersionTag(file, spec->getVersionInfo(), false);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700387 *file << "</p>\n";
388
389 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouillet36e2be52015-04-30 14:41:24 -0700390 const vector<string>& fields = spec->getFields();
391 const vector<string>& fieldComments = spec->getFieldComments();
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700392 for (size_t i = 0; i < fields.size(); i++) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700393 *file << " <tr><th>" << fields[i] << "</th><td>";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700394 if (fieldComments.size() > i && !fieldComments[i].empty()) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700395 *file << fieldComments[i];
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700396 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700397 *file << "</td></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700398 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700399 *file << " </tbody></table><br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700400 break;
401 }
402 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700403}
404
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700405static void writeDetailedConstantSpecification(GeneratedFile* file, ConstantSpecification* c) {
406 *file << " <tr><td>";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700407 *file << "Value: " << c->getValue() << "\n";
Stephen Hinesca51c782015-08-25 23:43:34 -0700408 writeHtmlVersionTag(file, c->getVersionInfo(), true);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700409 *file << " </td></tr>\n";
410 *file << "<br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700411}
412
413static bool writeOverviewForFile(GeneratedFile* file, const SpecFile& specFile) {
414 bool success = true;
415 *file << "<h2>" << specFile.getBriefDescription() << "</h2>\n";
416 if (!generateHtmlParagraphs(file, specFile.getFullDescription())) {
417 success = false;
418 }
419
420 // Write the summary tables.
421 // file << "<h2>Summary</h2>\n";
Jean-Luc Brouillet7c078542015-03-23 16:16:08 -0700422 writeSummaryTables(file, specFile.getDocumentedConstants(), specFile.getDocumentedTypes(),
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700423 specFile.getDocumentedFunctions(), NON_DEPRECATED_ONLY, false);
424
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700425 return success;
426}
427
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700428static bool generateOverview(const string& directory, bool forVerification) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700429 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700430 if (!file.start(directory, forVerification ? OVERVIEW_HTML_FILE_NAME : OVERVIEW_JD_FILE_NAME)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700431 return false;
432 }
433 bool success = true;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700434
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700435 writeHeader(&file, forVerification, "Runtime API Reference");
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700436
437 for (auto specFile : systemSpecification.getSpecFiles()) {
438 if (!writeOverviewForFile(&file, *specFile)) {
439 success = false;
440 }
441 }
442
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700443 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700444 file.close();
445 return success;
446}
447
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700448static bool generateAlphabeticalIndex(const string& directory, bool forVerification) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700449 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700450 if (!file.start(directory, forVerification ? INDEX_HTML_FILE_NAME : INDEX_JD_FILE_NAME)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700451 return false;
452 }
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700453 writeHeader(&file, forVerification, "Index");
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700454
455 writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700456 systemSpecification.getFunctions(), NON_DEPRECATED_ONLY, true);
457
458 writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
459 systemSpecification.getFunctions(), DEPRECATED_ONLY, true);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700460
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700461 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700462 file.close();
463 return true;
464}
465
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700466static void writeDeprecatedWarning(GeneratedFile* file, Definition* definition) {
467 if (definition->deprecated()) {
468 *file << " <p><b>Deprecated.</b> ";
469 string s = definition->getDeprecatedMessage();
470 convertDocumentationRefences(&s);
471 if (!s.empty()) {
472 *file << s;
473 } else {
474 *file << "Do not use.";
475 }
476 *file << "</p>\n";
477 }
478}
479
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700480static bool writeDetailedConstant(GeneratedFile* file, Constant* constant) {
481 if (constant->hidden()) {
482 return true;
483 }
484 const string& name = constant->getName();
485
Jean-Luc Brouillet918944e2015-04-30 11:12:40 -0700486 *file << "<a name='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700487 *file << "<div class='jd-details'>\n";
488 *file << " <h4 class='jd-details-title'>\n";
489 *file << " <span class='sympad'>" << name << "</span>\n";
490 *file << " <span class='normal'>: " << constant->getSummary() << "</span>\n";
491 *file << " </h4>\n";
492
493 *file << " <div class='jd-details-descr'>\n";
494 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700495 auto specifications = constant->getSpecifications();
496 bool addSeparator = specifications.size() > 1;
497 for (auto spec : specifications) {
498 if (addSeparator) {
499 *file << " <h5 class='jd-tagtitle'>Variant:</h5>\n";
500 }
501 writeDetailedConstantSpecification(file, spec);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700502 }
503 *file << " </tbody></table>\n";
504 *file << " </div>\n";
505
506 *file << " <div class='jd-tagdata jd-tagdescr'>\n";
507
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700508 writeDeprecatedWarning(file, constant);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700509 if (!generateHtmlParagraphs(file, constant->getDescription())) {
510 return false;
511 }
512 *file << " </div>\n";
513
514 *file << "</div>\n";
515 *file << "\n";
516 return true;
517}
518
519static bool writeDetailedType(GeneratedFile* file, Type* type) {
520 if (type->hidden()) {
521 return true;
522 }
523 const string& name = type->getName();
524
Jean-Luc Brouillet918944e2015-04-30 11:12:40 -0700525 *file << "<a name='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700526 *file << "<div class='jd-details'>\n";
527 *file << " <h4 class='jd-details-title'>\n";
528 *file << " <span class='sympad'>" << name << "</span>\n";
529 *file << " <span class='normal'>: " << type->getSummary() << "</span>\n";
530 *file << " </h4>\n";
531
532 *file << " <div class='jd-details-descr'>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700533 for (auto spec : type->getSpecifications()) {
534 writeDetailedTypeSpecification(file, spec);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700535 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700536
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700537 writeDeprecatedWarning(file, type);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700538 if (!generateHtmlParagraphs(file, type->getDescription())) {
539 return false;
540 }
541
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700542 *file << " </div>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700543 *file << "</div>\n";
544 *file << "\n";
545 return true;
546}
547
548static bool writeDetailedFunction(GeneratedFile* file, Function* function) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700549 if (function->hidden()) {
550 return true;
551 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700552 const string& name = function->getName();
553
Jean-Luc Brouillet918944e2015-04-30 11:12:40 -0700554 *file << "<a name='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700555 *file << "<div class='jd-details'>\n";
556 *file << " <h4 class='jd-details-title'>\n";
557 *file << " <span class='sympad'>" << name << "</span>\n";
558 *file << " <span class='normal'>: " << function->getSummary() << "</span>\n";
559 *file << " </h4>\n";
560
561 *file << " <div class='jd-details-descr'>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700562 map<string, DetailedFunctionEntry> entries;
563 if (!getUnifiedFunctionPrototypes(function, &entries)) {
564 return false;
565 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700566 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700567 for (auto i : entries) {
568 *file << " <tr>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700569 *file << " <td>" << i.second.htmlDeclaration << "</td>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700570 *file << " <td>";
Stephen Hinesca51c782015-08-25 23:43:34 -0700571 writeHtmlVersionTag(file, i.second.info, true);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700572 *file << " </td>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700573 *file << " </tr>\n";
574 }
575 *file << " </tbody></table>\n";
576 *file << " </div>\n";
577
578 if (function->someParametersAreDocumented()) {
579 *file << " <div class='jd-tagdata'>";
580 *file << " <h5 class='jd-tagtitle'>Parameters</h5>\n";
581 *file << " <table class='jd-tagtable'><tbody>\n";
582 for (ParameterEntry* p : function->getParameters()) {
583 *file << " <tr><th>" << p->name << "</th><td>" << p->documentation << "</td></tr>\n";
584 }
585 *file << " </tbody></table>\n";
586 *file << " </div>\n";
587 }
588
589 string ret = function->getReturnDocumentation();
590 if (!ret.empty()) {
591 *file << " <div class='jd-tagdata'>";
592 *file << " <h5 class='jd-tagtitle'>Returns</h5>\n";
593 *file << " <table class='jd-tagtable'><tbody>\n";
594 *file << " <tr><td>" << ret << "</td></tr>\n";
595 *file << " </tbody></table>\n";
596 *file << " </div>\n";
597 }
598
599 *file << " <div class='jd-tagdata jd-tagdescr'>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700600 writeDeprecatedWarning(file, function);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700601 if (!generateHtmlParagraphs(file, function->getDescription())) {
602 return false;
603 }
604 *file << " </div>\n";
605
606 *file << "</div>\n";
607 *file << "\n";
608 return true;
609}
610
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700611static bool writeDetailedDocumentationFile(const string& directory, const SpecFile& specFile,
612 bool forVerification) {
613 if (!specFile.hasSpecifications()) {
614 // This is true for rs_core.spec
615 return true;
616 }
617
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700618 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700619 const string fileName = stringReplace(specFile.getSpecFileName(), ".spec",
620 forVerification ? ".html" : ".jd");
621 if (!file.start(directory, fileName)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700622 return false;
623 }
624 bool success = true;
625
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700626 string title = specFile.getBriefDescription();
627 writeHeader(&file, forVerification, title);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700628
629 file << "<h2>Overview</h2>\n";
630 if (!generateHtmlParagraphs(&file, specFile.getFullDescription())) {
631 success = false;
632 }
633
634 // Write the summary tables.
635 file << "<h2>Summary</h2>\n";
Jean-Luc Brouillet7c078542015-03-23 16:16:08 -0700636 const auto& constants = specFile.getDocumentedConstants();
637 const auto& types = specFile.getDocumentedTypes();
638 const auto& functions = specFile.getDocumentedFunctions();
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700639
640 writeSummaryTables(&file, constants, types, functions, NON_DEPRECATED_ONLY, false);
641 writeSummaryTables(&file, constants, types, functions, DEPRECATED_ONLY, false);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700642
643 // Write the full details of each constant, type, and function.
644 if (!constants.empty()) {
645 file << "<h2>Constants</h2>\n";
646 for (auto i : constants) {
647 if (!writeDetailedConstant(&file, i.second)) {
648 success = false;
649 }
650 }
651 }
652 if (!types.empty()) {
653 file << "<h2>Types</h2>\n";
654 for (auto i : types) {
655 if (!writeDetailedType(&file, i.second)) {
656 success = false;
657 }
658 }
659 }
660 if (!functions.empty()) {
661 file << "<h2>Functions</h2>\n";
662 for (auto i : functions) {
663 if (!writeDetailedFunction(&file, i.second)) {
664 success = false;
665 }
666 }
667 }
668
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700669 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700670 file.close();
671
672 if (!success) {
673 // If in error, write a final message to make it easier to figure out which file failed.
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700674 cerr << fileName << ": Failed due to errors.\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700675 }
676 return success;
677}
678
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700679static void generateSnippet(GeneratedFile* file, const string& fileName, const string& title) {
680 const char offset[] = " ";
681 *file << offset << "<li><a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/"
682 << fileName << "\">\n";
683 *file << offset << " <span class=\"en\">" << title << "</span>\n";
684 *file << offset << "</a></li>\n";
685}
686
687/* Generate a partial file of links that should be cut & pasted into the proper section of the
688 * guide_toc.cs file.
689 */
690static bool generateAndroidTableOfContentSnippet(const string& directory) {
691 GeneratedFile file;
692 if (!file.start(directory, "guide_toc.cs")) {
693 return false;
694 }
695 file << "<!-- Copy and paste the following lines into the RenderScript section of\n";
696 file << " platform/frameworks/base/docs/html/guide/guide_toc.cs\n\n";
697
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700698 const char offset[] = " ";
699 file << offset << "<li class=\"nav-section\">\n";
700 file << offset << " <div class=\"nav-section-header\">\n";
701 file << offset << " <a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/" <<
702 OVERVIEW_HTML_FILE_NAME << "\">\n";
703 file << offset << " <span class=\"en\">Runtime API Reference</span>\n";
704 file << offset << " </a></div>\n";
705 file << offset << " <ul>\n";
706
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700707 for (auto specFile : systemSpecification.getSpecFiles()) {
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700708 if (specFile->hasSpecifications()) {
709 const string fileName = stringReplace(specFile->getSpecFileName(), ".spec", ".html");
710 generateSnippet(&file, fileName, specFile->getBriefDescription());
711 }
712 }
713 generateSnippet(&file, INDEX_HTML_FILE_NAME, "Index");
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700714
715 file << offset << " </ul>\n";
716 file << offset << "</li>\n";
717
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700718 return true;
719}
720
721bool generateDocumentation(const string& directory, bool forVerification) {
722 bool success = generateOverview(directory, forVerification) &&
723 generateAlphabeticalIndex(directory, forVerification) &&
724 generateAndroidTableOfContentSnippet(directory);
725 for (auto specFile : systemSpecification.getSpecFiles()) {
726 if (!writeDetailedDocumentationFile(directory, *specFile, forVerification)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700727 success = false;
728 }
729 }
730 return success;
731}