Revise API reference generator for DevSite-based DAC

This CL updates the RenderScript API references generator so that
DevSite headers are generated, and the driving generate.sh now places the
generated files in a Piper client, assuming DevSite-based DAC directory
structure.

Also removed support for verification (i.e. -H) as it is no longer used.

Bug: 62802398
Test: run generate.sh given a Piper client
Test: g4 diff between generated API reference files and the DAC version
Change-Id: Ie9bc7ef5a2cc58f17d07d86872220fa9d2dde213
diff --git a/script_api/GenerateDocumentation.cpp b/script_api/GenerateDocumentation.cpp
index 41f85cb..fde096b 100644
--- a/script_api/GenerateDocumentation.cpp
+++ b/script_api/GenerateDocumentation.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <algorithm>
 #include <iostream>
 #include <sstream>
 
@@ -29,39 +30,41 @@
 };
 
 static const char OVERVIEW_HTML_FILE_NAME[] = "overview.html";
-static const char OVERVIEW_JD_FILE_NAME[] = "overview.jd";
 static const char INDEX_HTML_FILE_NAME[] = "index.html";
-static const char INDEX_JD_FILE_NAME[] = "index.jd";
 
-static void writeHeader(GeneratedFile* file, bool forVerification, const string& title) {
-    if (forVerification) {
-        *file << "<!DOCTYPE html>\n";
-        *file << "<!-- " << AUTO_GENERATED_WARNING << "-->\n";
-        *file << "<html><head>\n"
-                 "<title>RenderScript Reference</title>\n"
-                 "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
-                 "<link rel='stylesheet' "
-                 "href='http://fonts.googleapis.com/css?family=Roboto+Condensed'>\n"
-                 "<link rel='stylesheet' href='http://fonts.googleapis.com/"
-                 "css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold' "
-                 "title='roboto'>\n"
-                 "<link href='default.css' rel='stylesheet' type='text/css'>\n"
-                 "<link href='fullscreen.css' rel='stylesheet' class='fullscreen' "
-                 "type='text/css'>\n"
-                 "<body class='gc-documentation develop reference'>\n\n";
-        *file << "<h1>" << title << "</h1>\n";
-    } else {
-        *file << "page.title=RenderScript " << title << "\n\n";
-        *file << "@jd:body\n\n";
+static void writeHeader(GeneratedFile* file, const string& title,
+                        const SpecFile& specFile) {
+    // Generate DevSite markups
+    *file
+        << "<html devsite>\n"
+           "<!-- " << AUTO_GENERATED_WARNING << "-->\n"
+           "<head>\n"
+           "  <title>RenderScript " << title << "</title>\n"
+           "  <meta name=\"top_category\" value=\"develop\" />\n"
+           "  <meta name=\"subcategory\" value=\"guide\" />\n"
+           "  <meta name=\"book_path\" value=\"/guide/_book.yaml\" />\n"
+           "  <meta name=\"project_path\" value=\"/guide/_project.yaml\" />\n";
+    auto desc = specFile.getFullDescription();
+    if (desc.size()) {
+        *file << "  <meta name=\"description\" content=\"";
+        // Output only the first two lines. Assuming there's no other HTML
+        // markups there
+        // TODO: escape/remove markups
+        for (int i = 0; i < std::min(desc.size(), 2UL); ++i) {
+            if (i) *file << " ";
+            *file << desc[i];
+        }
+        *file << "…\">\n";
     }
+    *file << "</head>\n\n"
+             "<body>\n\n";
     *file << "<div class='renderscript'>\n";
 }
 
-static void writeFooter(GeneratedFile* file, bool forVerification) {
+static void writeFooter(GeneratedFile* file) {
     *file << "</div>\n";
-    if (forVerification) {
-        *file << "</body></html>\n";
-    }
+    *file << "\n\n</body>\n";
+    *file << "</html>\n";
 }
 
 // If prefix starts input, copy it to stream and remove it from input.
@@ -425,14 +428,17 @@
     return success;
 }
 
-static bool generateOverview(const string& directory, bool forVerification) {
+static bool generateOverview(const string& directory) {
     GeneratedFile file;
-    if (!file.start(directory, forVerification ? OVERVIEW_HTML_FILE_NAME : OVERVIEW_JD_FILE_NAME)) {
+    if (!file.start(directory, OVERVIEW_HTML_FILE_NAME)) {
         return false;
     }
     bool success = true;
 
-    writeHeader(&file, forVerification, "Runtime API Reference");
+    // Take the description from the first spec file (rs_core.spec, based on how
+    // currently this generator is called)
+    writeHeader(&file, "Runtime API Reference",
+                *(systemSpecification.getSpecFiles()[0]));
 
     for (auto specFile : systemSpecification.getSpecFiles()) {
         if (!writeOverviewForFile(&file, *specFile)) {
@@ -440,17 +446,17 @@
         }
     }
 
-    writeFooter(&file, forVerification);
+    writeFooter(&file);
     file.close();
     return success;
 }
 
-static bool generateAlphabeticalIndex(const string& directory, bool forVerification) {
+static bool generateAlphabeticalIndex(const string& directory) {
     GeneratedFile file;
-    if (!file.start(directory, forVerification ? INDEX_HTML_FILE_NAME : INDEX_JD_FILE_NAME)) {
+    if (!file.start(directory, INDEX_HTML_FILE_NAME)) {
         return false;
     }
-    writeHeader(&file, forVerification, "Index");
+    writeHeader(&file, "Index", SpecFile(""));
 
     writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
                        systemSpecification.getFunctions(), NON_DEPRECATED_ONLY, true);
@@ -458,7 +464,7 @@
     writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
                        systemSpecification.getFunctions(), DEPRECATED_ONLY, true);
 
-    writeFooter(&file, forVerification);
+    writeFooter(&file);
     file.close();
     return true;
 }
@@ -608,8 +614,8 @@
     return true;
 }
 
-static bool writeDetailedDocumentationFile(const string& directory, const SpecFile& specFile,
-                                           bool forVerification) {
+static bool writeDetailedDocumentationFile(const string& directory,
+                                           const SpecFile& specFile) {
     if (!specFile.hasSpecifications()) {
         // This is true for rs_core.spec
         return true;
@@ -617,14 +623,14 @@
 
     GeneratedFile file;
     const string fileName = stringReplace(specFile.getSpecFileName(), ".spec",
-                                          forVerification ? ".html" : ".jd");
+                                          ".html");
     if (!file.start(directory, fileName)) {
         return false;
     }
     bool success = true;
 
     string title = specFile.getBriefDescription();
-    writeHeader(&file, forVerification, title);
+    writeHeader(&file, title, specFile);
 
     file << "<h2>Overview</h2>\n";
     if (!generateHtmlParagraphs(&file, specFile.getFullDescription())) {
@@ -666,7 +672,7 @@
         }
     }
 
-    writeFooter(&file, forVerification);
+    writeFooter(&file);
     file.close();
 
     if (!success) {
@@ -718,12 +724,12 @@
     return true;
 }
 
-bool generateDocumentation(const string& directory, bool forVerification) {
-    bool success = generateOverview(directory, forVerification) &&
-                   generateAlphabeticalIndex(directory, forVerification) &&
+bool generateDocumentation(const string& directory) {
+    bool success = generateOverview(directory) &&
+                   generateAlphabeticalIndex(directory) &&
                    generateAndroidTableOfContentSnippet(directory);
     for (auto specFile : systemSpecification.getSpecFiles()) {
-        if (!writeDetailedDocumentationFile(directory, *specFile, forVerification)) {
+        if (!writeDetailedDocumentationFile(directory, *specFile)) {
             success = false;
         }
     }
diff --git a/script_api/Generator.cpp b/script_api/Generator.cpp
index f67e473..bcb7b02 100644
--- a/script_api/Generator.cpp
+++ b/script_api/Generator.cpp
@@ -154,7 +154,7 @@
 
 using namespace std;
 
-static bool parseCommandLine(int argc, char* argv[], unsigned int* maxApiLevel, bool* forVerification,
+static bool parseCommandLine(int argc, char* argv[], unsigned int* maxApiLevel,
                              vector<string>* specFileNames) {
     for (int i = 1; i < argc; i++) {
         if (argv[i][0] == '-') {
@@ -171,8 +171,6 @@
                     cerr << "Missing version number after -v\n";
                     return false;
                 }
-            } else if (argv[i][1] == 'H') {
-                *forVerification = true;
             } else {
                 cerr << "Unrecognized flag %s\n" << argv[i] << "\n";
                 return false;
@@ -192,9 +190,9 @@
     // If there's no restriction, generated test files for the very highest version.
     unsigned int maxApiLevel = VersionInfo::kUnreleasedVersion;
     vector<string> specFileNames;
-    bool forVerification = false;
-    if (!parseCommandLine(argc, argv, &maxApiLevel, &forVerification, &specFileNames)) {
-        cout << "Usage: gen_runtime spec_file [spec_file...] [-v version_of_test_files][-H]\n";
+    if (!parseCommandLine(argc, argv, &maxApiLevel, &specFileNames)) {
+        cout << "Usage: gen_runtime spec_file [spec_file...] [-v "
+                "version_of_test_files]\n";
         return -1;
     }
     bool success = true;
@@ -204,7 +202,7 @@
         }
     }
     if (success) {
-        success = systemSpecification.generateFiles(forVerification, maxApiLevel);
+        success = systemSpecification.generateFiles(maxApiLevel);
     }
     return success ? 0 : -2;
 }
diff --git a/script_api/Generator.h b/script_api/Generator.h
index 5d72101..dc61edc 100644
--- a/script_api/Generator.h
+++ b/script_api/Generator.h
@@ -23,11 +23,11 @@
 // Generates the Java and RenderScript test files.  The implementation is in GenerateTestFiles.cpp.
 bool generateTestFiles(const std::string& directory, unsigned int versionOfTestFiles);
 
-/* Generates the documentation files.  The implementation is in GenerateDocumentation.cpp.
- * If forVerification is false (the default), we generate the .jd files needed by the
- * documentation system.  If it's true, we generate complete .html files for local debugging.
+/* Generates the documentation files.  The implementation is in
+ * GenerateDocumentation.cpp. This function generates the .jd files needed by
+ * the documentation system.
  */
-bool generateDocumentation(const std::string& director, bool forVerification);
+bool generateDocumentation(const std::string& director);
 
 /* Generates the RSStubsWhiteList.cpp file.  Also generates script test files that are used
  * when testing slang and that can be used to manually verify the white list.
diff --git a/script_api/Specification.cpp b/script_api/Specification.cpp
index f7d139e..4082a04 100644
--- a/script_api/Specification.cpp
+++ b/script_api/Specification.cpp
@@ -932,9 +932,9 @@
     return maxApiLevel;
 }
 
-bool SystemSpecification::generateFiles(bool forVerification, unsigned int maxApiLevel) const {
+bool SystemSpecification::generateFiles(unsigned int maxApiLevel) const {
     bool success = generateHeaderFiles("include") &&
-                   generateDocumentation("docs", forVerification) &&
+                   generateDocumentation("docs") &&
                    generateTestFiles("test", maxApiLevel) &&
                    generateStubsWhiteList("slangtest", maxApiLevel);
     if (success) {
diff --git a/script_api/Specification.h b/script_api/Specification.h
index 9e1b2ee..8bb99ede7 100644
--- a/script_api/Specification.h
+++ b/script_api/Specification.h
@@ -597,7 +597,7 @@
      */
     bool readSpecFile(const std::string& fileName, unsigned int maxApiLevel);
     // Generate all the files.
-    bool generateFiles(bool forVerification, unsigned int maxApiLevel) const;
+    bool generateFiles(unsigned int maxApiLevel) const;
 
     const std::vector<SpecFile*>& getSpecFiles() const { return mSpecFiles; }
     const std::map<std::string, Constant*>& getConstants() const { return mConstants; }
diff --git a/script_api/generate.sh b/script_api/generate.sh
index c7d105c..894edc8 100755
--- a/script_api/generate.sh
+++ b/script_api/generate.sh
@@ -15,7 +15,21 @@
 # limitations under the License.
 #
 
-CLANG=$ANDROID_BUILD_TOP/prebuilts/clang/host/linux-x86/clang-stable/bin/clang++
+# TODO: $ANDROID_BUILD_TOP/prebuilts/clang/host/linux-x86/clang-stable/bin
+# no longer contains clang on AOSP master. Need a stable way to reach clang
+# binaries here.
+CLANG=$ANDROID_BUILD_TOP/prebuilts/clang/host/linux-x86/clang-4393122/bin/clang++
+
+if [ x"$1" == "x" ]; then
+  echo "Please specify the top-level Piper client directory."
+  exit 1
+fi
+
+DOC_DIR="$1/googledata/devsite/site-android/en/guide/topics/renderscript/"
+if [ ! -d $DOC_DIR ]; then
+  echo "Expecting top-level Piper client directory."
+  exit 2
+fi
 
 cd `dirname $0`
 
@@ -41,8 +55,8 @@
 mv test/* ../../../cts/tests/tests/renderscript/src/android/renderscript/cts/generated/
 rmdir test
 
-rm -f ../../base/docs/html/guide/topics/renderscript/reference/*.jd
-mv docs/*.jd ../../base/docs/html/guide/topics/renderscript/reference/
+rm -f "$DOC_DIR"/reference/*.html
+mv docs/*.html "$DOC_DIR"/reference
 
 # Current API level : 24
 RS_API_LEVEL=24
@@ -55,4 +69,3 @@
 
 mv RSStubsWhiteList.cpp ../../compile/libbcc/lib/
 
-echo "Be sure to update platform/frameworks/base/docs/html/guide/guide_toc.cs if needed."