blob: e5f238aabac785c2615321d5217dbc97cf6e7eca [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 Brouilletc5184e22015-03-13 13:51:24 -070057}
58
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070059static void writeFooter(GeneratedFile* file, bool forVerification) {
60 if (forVerification) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -070061 *file << "</body></html>\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -070062 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -070063}
64
65// If prefix starts input, copy it to stream and remove it from input.
66static void skipPrefix(ostringstream* stream, string* input, const string& prefix) {
67 size_t size = prefix.size();
68 if (input->compare(0, size, prefix) != 0) {
69 return;
70 }
71 input->erase(0, size);
72 *stream << prefix;
73}
74
75// Merge b into a. Returns true if successful
76static bool mergeVersionInfo(VersionInfo* a, const VersionInfo& b) {
77 if (a->intSize != b.intSize) {
78 cerr << "Error. We don't currently support versions that differ based on int size\n";
79 return false;
80 }
81 if (b.minVersion != 0 && a->maxVersion == b.minVersion - 1) {
82 a->maxVersion = b.maxVersion;
83 } else if (b.maxVersion != 0 && a->minVersion == b.maxVersion + 1) {
84 a->minVersion = b.minVersion;
85 } else {
86 cerr << "Error. This code currently assume that all versions are contiguous. Don't know "
87 "how to merge versions (" << a->minVersion << " - " << a->maxVersion << ") and ("
88 << b.minVersion << " - " << b.maxVersion << ")\n";
89 return false;
90 }
91 return true;
92}
93
94static string getHtmlStringForType(const ParameterDefinition& parameter) {
95 string s = parameter.rsType;
96 ostringstream stream;
97 skipPrefix(&stream, &s, "const ");
98 skipPrefix(&stream, &s, "volatile ");
99 bool endsWithAsterisk = s.size() > 0 && s[s.size() - 1] == '*';
100 if (endsWithAsterisk) {
101 s.erase(s.size() - 1, 1);
102 }
103
104 string anchor = systemSpecification.getHtmlAnchor(s);
105 if (anchor.empty()) {
106 // Not a RenderScript specific type.
107 return parameter.rsType;
108 } else {
109 stream << anchor;
110 }
111 if (endsWithAsterisk) {
112 stream << "*";
113 }
114 return stream.str();
115}
116
117static string getDetailedHtmlDeclaration(const FunctionPermutation& permutation) {
118 ostringstream stream;
119 auto ret = permutation.getReturn();
120 if (ret) {
121 stream << getHtmlStringForType(*ret);
122 } else {
123 stream << "void";
124 }
125 stream << " " << permutation.getName() << "(";
126 bool needComma = false;
127 for (auto p : permutation.getParams()) {
128 if (needComma) {
129 stream << ", ";
130 }
131 stream << getHtmlStringForType(*p);
132 if (p->isOutParameter) {
133 stream << "*";
134 }
135 if (!p->specName.empty()) {
136 stream << " " << p->specName;
137 }
138 needComma = true;
139 }
140 stream << ");\n";
141 return stream.str();
142}
143
144/* Some functions (like max) have changed implementations but not their
145 * declaration. We need to unify these so that we don't end up with entries
146 * like:
147 * char max(char a, char b); Removed from API level 20
148 * char max(char a, char b); Added to API level 20
149 */
150static bool getUnifiedFunctionPrototypes(Function* function,
151 map<string, DetailedFunctionEntry>* entries) {
152 for (auto f : function->getSpecifications()) {
153 DetailedFunctionEntry entry;
154 entry.info = f->getVersionInfo();
155 for (auto p : f->getPermutations()) {
156 entry.htmlDeclaration = getDetailedHtmlDeclaration(*p);
157 const string s = stripHtml(entry.htmlDeclaration);
158 auto i = entries->find(s);
159 if (i == entries->end()) {
160 entries->insert(pair<string, DetailedFunctionEntry>(s, entry));
161 } else {
162 if (!mergeVersionInfo(&i->second.info, entry.info)) {
163 return false;
164 }
165 }
166 }
167 }
168 return true;
169}
170
171// Convert words starting with @ into HTML references. Returns false if error.
172static bool convertDocumentationRefences(string* s) {
173 bool success = true;
174 size_t end = 0;
175 for (;;) {
176 size_t start = s->find('@', end);
177 if (start == string::npos) {
178 break;
179 }
180 // Find the end of the identifier
181 end = start;
182 char c;
183 do {
184 c = (*s)[++end];
185 } while (isalnum(c) || c == '_');
186
187 const string id = s->substr(start + 1, end - start - 1);
188 string anchor = systemSpecification.getHtmlAnchor(id);
189 if (anchor.empty()) {
190 cerr << "Error: Can't convert the documentation reference @" << id << "\n";
191 success = false;
192 }
193 s->replace(start, end - start, anchor);
194 }
195 return success;
196}
197
198static bool generateHtmlParagraphs(GeneratedFile* file, const vector<string>& description) {
199 bool inParagraph = false;
200 for (auto s : description) {
201 // Empty lines in the .spec marks paragraphs.
202 if (s.empty()) {
203 if (inParagraph) {
204 *file << "</p>\n";
205 inParagraph = false;
206 }
207 } else {
208 if (!inParagraph) {
209 *file << "<p> ";
210 inParagraph = true;
211 }
212 }
213 if (!convertDocumentationRefences(&s)) {
214 return false;
215 }
216 *file << s << "\n";
217 }
218 if (inParagraph) {
219 *file << "</p>\n";
220 }
221 return true;
222}
223
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700224static void writeSummaryTableStart(GeneratedFile* file, const string& label, bool labelIsHeading) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700225 if (labelIsHeading) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700226 *file << "<h2 style='margin-bottom: 0px;'>" << label << "</h2>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700227 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700228 *file << "<table class='jd-sumtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700229 if (!labelIsHeading) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700230 *file << " <tr><th colspan='2'>" << label << "</th></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700231 }
232}
233
234static void writeSummaryTableEnd(GeneratedFile* file) {
235 *file << "</tbody></table>\n";
236}
237
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700238enum DeprecatedSelector {
239 DEPRECATED_ONLY,
240 NON_DEPRECATED_ONLY,
241 ALL,
242};
243
244static void writeSummaryTableEntry(ostream* stream, Definition* definition,
245 DeprecatedSelector deprecatedSelector) {
246 if (definition->hidden()) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700247 return;
248 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700249 const bool deprecated = definition->deprecated();
250 if ((deprecatedSelector == DEPRECATED_ONLY && !deprecated) ||
251 (deprecatedSelector == NON_DEPRECATED_ONLY && deprecated)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700252 return;
253 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700254
255 *stream << " <tr class='alt-color api apilevel-1'>\n";
256 *stream << " <td class='jd-linkcol'>\n";
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700257 *stream << " <a href='" << definition->getUrl() << "'>" << definition->getName()
258 << "</a>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700259 *stream << " </td>\n";
260 *stream << " <td class='jd-descrcol' width='100%'>\n";
261 *stream << " ";
262 if (deprecated) {
263 *stream << "<b>Deprecated</b>. ";
264 }
265 *stream << definition->getSummary() << "\n";
266 *stream << " </td>\n";
267 *stream << " </tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700268}
269
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700270static void writeSummaryTable(GeneratedFile* file, const ostringstream* entries, const char* name,
271 DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
272 string s = entries->str();
273 if (!s.empty()) {
274 string prefix;
275 if (deprecatedSelector == DEPRECATED_ONLY) {
276 prefix = "Deprecated ";
277 }
278 writeSummaryTableStart(file, prefix + name, labelAsHeader);
279 *file << s;
280 writeSummaryTableEnd(file);
281 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700282}
283
284static void writeSummaryTables(GeneratedFile* file, const map<string, Constant*>& constants,
285 const map<string, Type*>& types,
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700286 const map<string, Function*>& functions,
287 DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
288 ostringstream constantStream;
289 for (auto e : constants) {
290 writeSummaryTableEntry(&constantStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700291 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700292 writeSummaryTable(file, &constantStream, "Constants", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700293
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700294 ostringstream typeStream;
295 for (auto e : types) {
296 writeSummaryTableEntry(&typeStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700297 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700298 writeSummaryTable(file, &typeStream, "Types", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700299
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700300 ostringstream functionStream;
301 for (auto e : functions) {
302 writeSummaryTableEntry(&functionStream, e.second, deprecatedSelector);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700303 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700304 writeSummaryTable(file, &functionStream, "Functions", deprecatedSelector, labelAsHeader);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700305}
306
307static void writeHtmlVersionTag(GeneratedFile* file, VersionInfo info) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700308 ostringstream stream;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700309 if (info.intSize == 32) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700310 stream << "When compiling for 32 bits. ";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700311 } else if (info.intSize == 64) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700312 stream << "When compiling for 64 bits. ";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700313 }
314
315 if (info.minVersion > 1 || info.maxVersion) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700316 const char* mid =
317 "<a "
318 "href='http://developer.android.com/guide/topics/manifest/"
319 "uses-sdk-element.html#ApiLevels'>API level ";
320 if (info.minVersion <= 1) {
321 // No minimum
322 if (info.maxVersion > 0) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700323 stream << "Removed from " << mid << info.maxVersion + 1;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700324 }
325 } else {
326 if (info.maxVersion == 0) {
327 // No maximum
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700328 stream << "Added in " << mid << info.minVersion;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700329 } else {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700330 stream << mid << info.minVersion << " - " << info.maxVersion;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700331 }
332 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700333 stream << "</a>";
334 }
335 const string s = stream.str();
336 if (!s.empty()) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700337 *file << " " << s << "\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700338 }
339}
340
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700341static void writeDetailedTypeSpecification(GeneratedFile* file, const TypeSpecification* type) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700342 switch (type->getKind()) {
343 case SIMPLE:
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700344 *file << "<p>A typedef of: " << type->getSimpleType()
345 << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
346 writeHtmlVersionTag(file, type->getVersionInfo());
347 *file << "</p>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700348 break;
349 case ENUM: {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700350 *file << "<p>An enum with the following values:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n";
351 writeHtmlVersionTag(file, type->getVersionInfo());
352 *file << "</p>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700353
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700354 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700355 const vector<string>& values = type->getValues();
356 const vector<string>& valueComments = type->getValueComments();
357 for (size_t i = 0; i < values.size(); i++) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700358 *file << " <tr><th>" << values[i] << "</th><td>";
359 if (valueComments.size() > i) {
360 *file << valueComments[i];
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700361 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700362 *file << "</td></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700363 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700364 *file << " </tbody></table><br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700365 break;
366 }
367 case STRUCT: {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700368 *file << "<p>A structure with the following fields:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
369 writeHtmlVersionTag(file, type->getVersionInfo());
370 *file << "</p>\n";
371
372 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700373 const vector<string>& fields = type->getFields();
374 const vector<string>& fieldComments = type->getFieldComments();
375 for (size_t i = 0; i < fields.size(); i++) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700376 *file << " <tr><th>" << fields[i] << "</th><td>";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700377 if (fieldComments.size() > i && !fieldComments[i].empty()) {
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700378 *file << fieldComments[i];
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700379 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700380 *file << "</td></tr>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700381 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700382 *file << " </tbody></table><br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700383 break;
384 }
385 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700386}
387
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700388static void writeDetailedConstantSpecification(GeneratedFile* file, ConstantSpecification* c) {
389 *file << " <tr><td>";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700390 *file << "Value: " << c->getValue() << "\n";
391 writeHtmlVersionTag(file, c->getVersionInfo());
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700392 *file << " </td></tr>\n";
393 *file << "<br/>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700394}
395
396static bool writeOverviewForFile(GeneratedFile* file, const SpecFile& specFile) {
397 bool success = true;
398 *file << "<h2>" << specFile.getBriefDescription() << "</h2>\n";
399 if (!generateHtmlParagraphs(file, specFile.getFullDescription())) {
400 success = false;
401 }
402
403 // Write the summary tables.
404 // file << "<h2>Summary</h2>\n";
Jean-Luc Brouillet7c078542015-03-23 16:16:08 -0700405 writeSummaryTables(file, specFile.getDocumentedConstants(), specFile.getDocumentedTypes(),
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700406 specFile.getDocumentedFunctions(), NON_DEPRECATED_ONLY, false);
407
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700408 return success;
409}
410
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700411static bool generateOverview(const string& directory, bool forVerification) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700412 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700413 if (!file.start(directory, forVerification ? OVERVIEW_HTML_FILE_NAME : OVERVIEW_JD_FILE_NAME)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700414 return false;
415 }
416 bool success = true;
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700417
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700418 writeHeader(&file, forVerification, "Runtime API Reference");
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700419
420 for (auto specFile : systemSpecification.getSpecFiles()) {
421 if (!writeOverviewForFile(&file, *specFile)) {
422 success = false;
423 }
424 }
425
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700426 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700427 file.close();
428 return success;
429}
430
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700431static bool generateAlphabeticalIndex(const string& directory, bool forVerification) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700432 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700433 if (!file.start(directory, forVerification ? INDEX_HTML_FILE_NAME : INDEX_JD_FILE_NAME)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700434 return false;
435 }
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700436 writeHeader(&file, forVerification, "Index");
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700437
438 writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700439 systemSpecification.getFunctions(), NON_DEPRECATED_ONLY, true);
440
441 writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
442 systemSpecification.getFunctions(), DEPRECATED_ONLY, true);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700443
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700444 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700445 file.close();
446 return true;
447}
448
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700449static void writeDeprecatedWarning(GeneratedFile* file, Definition* definition) {
450 if (definition->deprecated()) {
451 *file << " <p><b>Deprecated.</b> ";
452 string s = definition->getDeprecatedMessage();
453 convertDocumentationRefences(&s);
454 if (!s.empty()) {
455 *file << s;
456 } else {
457 *file << "Do not use.";
458 }
459 *file << "</p>\n";
460 }
461}
462
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700463static bool writeDetailedConstant(GeneratedFile* file, Constant* constant) {
464 if (constant->hidden()) {
465 return true;
466 }
467 const string& name = constant->getName();
468
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700469 *file << "<a id='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700470 *file << "<div class='jd-details'>\n";
471 *file << " <h4 class='jd-details-title'>\n";
472 *file << " <span class='sympad'>" << name << "</span>\n";
473 *file << " <span class='normal'>: " << constant->getSummary() << "</span>\n";
474 *file << " </h4>\n";
475
476 *file << " <div class='jd-details-descr'>\n";
477 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700478 auto specifications = constant->getSpecifications();
479 bool addSeparator = specifications.size() > 1;
480 for (auto spec : specifications) {
481 if (addSeparator) {
482 *file << " <h5 class='jd-tagtitle'>Variant:</h5>\n";
483 }
484 writeDetailedConstantSpecification(file, spec);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700485 }
486 *file << " </tbody></table>\n";
487 *file << " </div>\n";
488
489 *file << " <div class='jd-tagdata jd-tagdescr'>\n";
490
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700491 writeDeprecatedWarning(file, constant);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700492 if (!generateHtmlParagraphs(file, constant->getDescription())) {
493 return false;
494 }
495 *file << " </div>\n";
496
497 *file << "</div>\n";
498 *file << "\n";
499 return true;
500}
501
502static bool writeDetailedType(GeneratedFile* file, Type* type) {
503 if (type->hidden()) {
504 return true;
505 }
506 const string& name = type->getName();
507
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700508 *file << "<a id='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700509 *file << "<div class='jd-details'>\n";
510 *file << " <h4 class='jd-details-title'>\n";
511 *file << " <span class='sympad'>" << name << "</span>\n";
512 *file << " <span class='normal'>: " << type->getSummary() << "</span>\n";
513 *file << " </h4>\n";
514
515 *file << " <div class='jd-details-descr'>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700516 for (auto spec : type->getSpecifications()) {
517 writeDetailedTypeSpecification(file, spec);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700518 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700519
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700520 writeDeprecatedWarning(file, type);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700521 if (!generateHtmlParagraphs(file, type->getDescription())) {
522 return false;
523 }
524
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700525 *file << " </div>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700526 *file << "</div>\n";
527 *file << "\n";
528 return true;
529}
530
531static bool writeDetailedFunction(GeneratedFile* file, Function* function) {
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700532 if (function->hidden()) {
533 return true;
534 }
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700535 const string& name = function->getName();
536
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700537 *file << "<a id='android_rs:" << name << "'></a>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700538 *file << "<div class='jd-details'>\n";
539 *file << " <h4 class='jd-details-title'>\n";
540 *file << " <span class='sympad'>" << name << "</span>\n";
541 *file << " <span class='normal'>: " << function->getSummary() << "</span>\n";
542 *file << " </h4>\n";
543
544 *file << " <div class='jd-details-descr'>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700545 map<string, DetailedFunctionEntry> entries;
546 if (!getUnifiedFunctionPrototypes(function, &entries)) {
547 return false;
548 }
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700549 *file << " <table class='jd-tagtable'><tbody>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700550 for (auto i : entries) {
551 *file << " <tr>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700552 *file << " <td>" << i.second.htmlDeclaration << "</td>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700553 *file << " <td>";
554 writeHtmlVersionTag(file, i.second.info);
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700555 *file << " </td>\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700556 *file << " </tr>\n";
557 }
558 *file << " </tbody></table>\n";
559 *file << " </div>\n";
560
561 if (function->someParametersAreDocumented()) {
562 *file << " <div class='jd-tagdata'>";
563 *file << " <h5 class='jd-tagtitle'>Parameters</h5>\n";
564 *file << " <table class='jd-tagtable'><tbody>\n";
565 for (ParameterEntry* p : function->getParameters()) {
566 *file << " <tr><th>" << p->name << "</th><td>" << p->documentation << "</td></tr>\n";
567 }
568 *file << " </tbody></table>\n";
569 *file << " </div>\n";
570 }
571
572 string ret = function->getReturnDocumentation();
573 if (!ret.empty()) {
574 *file << " <div class='jd-tagdata'>";
575 *file << " <h5 class='jd-tagtitle'>Returns</h5>\n";
576 *file << " <table class='jd-tagtable'><tbody>\n";
577 *file << " <tr><td>" << ret << "</td></tr>\n";
578 *file << " </tbody></table>\n";
579 *file << " </div>\n";
580 }
581
582 *file << " <div class='jd-tagdata jd-tagdescr'>\n";
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700583 writeDeprecatedWarning(file, function);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700584 if (!generateHtmlParagraphs(file, function->getDescription())) {
585 return false;
586 }
587 *file << " </div>\n";
588
589 *file << "</div>\n";
590 *file << "\n";
591 return true;
592}
593
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700594static bool writeDetailedDocumentationFile(const string& directory, const SpecFile& specFile,
595 bool forVerification) {
596 if (!specFile.hasSpecifications()) {
597 // This is true for rs_core.spec
598 return true;
599 }
600
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700601 GeneratedFile file;
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700602 const string fileName = stringReplace(specFile.getSpecFileName(), ".spec",
603 forVerification ? ".html" : ".jd");
604 if (!file.start(directory, fileName)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700605 return false;
606 }
607 bool success = true;
608
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700609 string title = specFile.getBriefDescription();
610 writeHeader(&file, forVerification, title);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700611
612 file << "<h2>Overview</h2>\n";
613 if (!generateHtmlParagraphs(&file, specFile.getFullDescription())) {
614 success = false;
615 }
616
617 // Write the summary tables.
618 file << "<h2>Summary</h2>\n";
Jean-Luc Brouillet7c078542015-03-23 16:16:08 -0700619 const auto& constants = specFile.getDocumentedConstants();
620 const auto& types = specFile.getDocumentedTypes();
621 const auto& functions = specFile.getDocumentedFunctions();
Jean-Luc Brouillet4a730042015-04-02 16:15:25 -0700622
623 writeSummaryTables(&file, constants, types, functions, NON_DEPRECATED_ONLY, false);
624 writeSummaryTables(&file, constants, types, functions, DEPRECATED_ONLY, false);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700625
626 // Write the full details of each constant, type, and function.
627 if (!constants.empty()) {
628 file << "<h2>Constants</h2>\n";
629 for (auto i : constants) {
630 if (!writeDetailedConstant(&file, i.second)) {
631 success = false;
632 }
633 }
634 }
635 if (!types.empty()) {
636 file << "<h2>Types</h2>\n";
637 for (auto i : types) {
638 if (!writeDetailedType(&file, i.second)) {
639 success = false;
640 }
641 }
642 }
643 if (!functions.empty()) {
644 file << "<h2>Functions</h2>\n";
645 for (auto i : functions) {
646 if (!writeDetailedFunction(&file, i.second)) {
647 success = false;
648 }
649 }
650 }
651
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700652 writeFooter(&file, forVerification);
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700653 file.close();
654
655 if (!success) {
656 // 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 -0700657 cerr << fileName << ": Failed due to errors.\n";
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700658 }
659 return success;
660}
661
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700662static void generateSnippet(GeneratedFile* file, const string& fileName, const string& title) {
663 const char offset[] = " ";
664 *file << offset << "<li><a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/"
665 << fileName << "\">\n";
666 *file << offset << " <span class=\"en\">" << title << "</span>\n";
667 *file << offset << "</a></li>\n";
668}
669
670/* Generate a partial file of links that should be cut & pasted into the proper section of the
671 * guide_toc.cs file.
672 */
673static bool generateAndroidTableOfContentSnippet(const string& directory) {
674 GeneratedFile file;
675 if (!file.start(directory, "guide_toc.cs")) {
676 return false;
677 }
678 file << "<!-- Copy and paste the following lines into the RenderScript section of\n";
679 file << " platform/frameworks/base/docs/html/guide/guide_toc.cs\n\n";
680
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700681 const char offset[] = " ";
682 file << offset << "<li class=\"nav-section\">\n";
683 file << offset << " <div class=\"nav-section-header\">\n";
684 file << offset << " <a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/" <<
685 OVERVIEW_HTML_FILE_NAME << "\">\n";
686 file << offset << " <span class=\"en\">Runtime API Reference</span>\n";
687 file << offset << " </a></div>\n";
688 file << offset << " <ul>\n";
689
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700690 for (auto specFile : systemSpecification.getSpecFiles()) {
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700691 if (specFile->hasSpecifications()) {
692 const string fileName = stringReplace(specFile->getSpecFileName(), ".spec", ".html");
693 generateSnippet(&file, fileName, specFile->getBriefDescription());
694 }
695 }
696 generateSnippet(&file, INDEX_HTML_FILE_NAME, "Index");
Jean-Luc Brouillet6386ceb2015-04-28 15:06:30 -0700697
698 file << offset << " </ul>\n";
699 file << offset << "</li>\n";
700
Jean-Luc Brouillet2217eb72015-04-24 14:41:48 -0700701 return true;
702}
703
704bool generateDocumentation(const string& directory, bool forVerification) {
705 bool success = generateOverview(directory, forVerification) &&
706 generateAlphabeticalIndex(directory, forVerification) &&
707 generateAndroidTableOfContentSnippet(directory);
708 for (auto specFile : systemSpecification.getSpecFiles()) {
709 if (!writeDetailedDocumentationFile(directory, *specFile, forVerification)) {
Jean-Luc Brouilletc5184e22015-03-13 13:51:24 -0700710 success = false;
711 }
712 }
713 return success;
714}