1# Copyright 2019 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15############################################################################### 16# This script adds a HTML snippet to the generated reference docs located at 17# developer.android.com/reference. The snippet renders HTML that adds links to 18# toggle between the Java and Kotlin versions of the page. 19############################################################################### 20 21import getopt 22import os 23import sys 24 25 26# GLOBAL FLAGS 27 28global stubs 29global java_stubs, kotlin_stubs 30global work, verbose, show_solo, max_stubs 31global java_source_abs_path 32global kotlin_source_abs_path 33 34verbose = False # set True to list all files as they are stubbed (--verbose) 35work = False # set True to insert stubs, False to do a dry run for stats (--work) 36show_solo = False # set True to list files that only appear in one language, rather than both (--solo) 37max_stubs = 0 # set positive to create a limited number of stubs (--max 12) 38 39 40# You must run the script from the refodcs reference/ root directory 41 42java_ref_root = os.getcwd() 43kotlin_ref_root = os.path.join(java_ref_root, "kotlin") 44root = os.path.split(java_ref_root)[1] 45if root != "reference": 46 print ("You must cd to the refocs reference/ root directoy") 47 sys.exit() 48 49 50# This method inserts the language switcher into the two top-level Android 51# Platform pages: packages.html and classes.html 52# For both Java and Kotlin 53def insert_platform_summaries(): 54 global stubs 55 global java_stubs, kotlin_stubs 56 global verbose, work, show_solo 57 global java_source_abs_path 58 global kotlin_source_abs_path 59 60 stubs = 0 61 java_stubs = 0 62 kotlin_stubs = 0 63 64 java_source_abs_path = java_ref_root 65 kotlin_source_abs_path = kotlin_ref_root 66 insert_stub(os.path.join(java_ref_root, "packages.html"), True, True) 67 insert_stub(os.path.join(kotlin_ref_root, "packages.html"), False, True) 68 69 insert_stub(os.path.join(java_ref_root, "classes.html"), True, True) 70 insert_stub(os.path.join(kotlin_ref_root, "classes.html"), False, True) 71 72# This method uses switcher2, which assumes the refdocs stay in their current 73# assymetrical dirs (ref/android and ref/kotlin/android) 74# And just puts the switcher in the existing docs 75def insert_stub(doc, java, both): 76 global stubs 77 global java_stubs, kotlin_stubs 78 global verbose, work, show_solo 79 global java_source_abs_path 80 global kotlin_source_abs_path 81 82 stubs = stubs+1 83 84 if verbose: 85 print "File: ", stubs, doc 86 else: 87 fn = os.path.split(doc) 88 print "File: ", stubs, fn[1], "\r", 89 90 if (java): 91 java_stubs = java_stubs + 1 92 else: 93 kotlin_stubs = kotlin_stubs + 1 94 95 96 if (work): 97 if (java): 98 file_path = doc[len(java_ref_root)+1:] 99 stub = doc.replace(java_source_abs_path, kotlin_source_abs_path) 100 if (both): 101 slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% setvar page_path %}_page_path_{% endsetvar %}\\n{% setvar can_switch %}1{% endsetvar %}\\n{% include \"reference\/_java_switcher2.md\" %}",doc) 102 else: 103 slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% include \"reference\/_java_switcher2.md\" %}",doc) 104 else: 105 file_path = doc[len(kotlin_ref_root)+1:] 106 stub = doc.replace(kotlin_source_abs_path, java_source_abs_path) 107 if (both): 108 slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% setvar page_path %}_page_path_{% endsetvar %}\\n{% setvar can_switch %}1{% endsetvar %}\\n{% include \"reference\/_kotlin_switcher2.md\" %}",doc) 109 else: 110 slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% include \"reference\/_kotlin_switcher2.md\" %}",doc) 111 112 os.system(slug1) 113 if (both): 114 page_path_slug = "sed -i 's/_page_path_/{}/' {}".format(file_path.replace("/","\/"),doc) 115 os.system(page_path_slug) 116 117 118def scan_files(stem): 119 global work, verbose, show_solo, max_stubs 120 global stubs 121 global java_stubs, kotlin_stubs 122 global java_source_abs_path 123 global kotlin_source_abs_path 124 125 java_source_abs_path = os.path.join(java_ref_root, stem) 126 kotlin_source_abs_path = os.path.join(kotlin_ref_root, stem) 127 128 # Pass 1 129 # Loop over java content, create stubs for java, 130 # and for corresponding Kotlin (when it exsits) 131 132 # solo is java-only classes 133 # both is java+kotlin 134 stubs = 0 135 java_stubs = 0 136 kotlin_stubs = 0 137 solo = 0 138 both = 0 139 140 print "*** PASS1 (Java) ***" 141 maxed_out = False 142 for root, dirs, files in os.walk(java_source_abs_path): 143 if maxed_out: 144 break; 145 for file_ in files: 146 ext = os.path.splitext(file_) 147 ext = ext[1] 148 if not ext: 149 # this catches package-lists with no extension 150 print "***", os.path.join(root, file_) 151 elif ext != ".html": 152 # filter out png, yaml, etc 153 continue 154 else: 155 # we have java content 156 doc = os.path.join(root, file_) 157 158 159 160 # look for matching kotlin file 161 kotlinsource = doc.replace(java_source_abs_path, kotlin_source_abs_path) 162 if os.path.isfile(kotlinsource): 163 # corresponding kotlin content exists 164 insert_stub(doc, True, True) 165 insert_stub(kotlinsource, False, True) 166 both = both+1 167 else: 168 # no kotlin content 169 if (show_solo): 170 print "solo: ", doc 171 insert_stub(doc, True, False) 172 solo = solo+1 173 174 if max_stubs>0 and stubs>=max_stubs: 175 print 176 print "max java stubs: ", max_stubs 177 maxed_out = True; 178 break 179 180 print "Java+Kotlin:", both, "Only Java:", solo 181 print 182 183 184 # PASS 2 185 # Loop over kotlin content, create stubs for Kotlin-only APIs 186 print "*** PASS2 (Kotlin) ***" 187 solo = 0 188 both = 0 189 maxed_out = False 190 stubs = 0 191 for root, dirs, files in os.walk(kotlin_source_abs_path): 192 if maxed_out: 193 break; 194 for file_ in files: 195 ext = os.path.splitext (file_) 196 ext = ext[1] 197 if not ext: 198 # this catches package-lists with no extension 199 print "***", os.path.join(root, file_) 200 elif ext != ".html": 201 # filter out png, yaml, etc 202 continue 203 else: 204 # we have kotlin content 205 doc = os.path.join(root, file_) 206 javadoc = doc.replace(kotlin_source_abs_path, java_source_abs_path) 207 file_name = os.path.splitext(file_)[0] 208 file_path = doc[len(kotlin_source_abs_path)+1:] 209 include_path = os.path.join("/reference/_kotlin", file_path) 210 211 if os.path.isfile(javadoc): 212 # corresponding java content exists 213 # so we already created the kotlin stub file 214 # nothing to do 215 both = both+1 216 else: 217 # no java content 218 # create the kotlin stub file 219 if (show_solo): 220 print "solo: ", doc 221 insert_stub(doc , False, False) 222 solo = solo+1 223 224 if (max_stubs>0 and stubs>=max_stubs): 225 print 226 print "max koltin stubs: ", max_stubs 227 maxed_out = True; 228 break 229 230 231 print "Java+Kotlin:", both, "Only Kotlin:", solo 232 print 233 print "Java: ", java_stubs, " Kotlin: ", kotlin_stubs, "Total: ", java_stubs + kotlin_stubs 234 235 236def main(argv): 237 238 global work, verbose, show_solo, max_stubs 239 global java_source_abs_path 240 global kotlin_source_abs_path 241 stem = "" 242 243 try: 244 opts, args = getopt.getopt(argv,"",["work","verbose","solo","max="]) 245 except getopt.GetoptError: 246 print 'USAGE: switcher --work --verbose --solo --max=<max_stubs> platform|androidx|support|chrome' 247 sys.exit(2) 248 249 for opt, arg in opts: 250 if opt == '--work': 251 work = True 252 elif opt == "--verbose": 253 print "verbose" 254 verbose = True 255 elif opt == "--solo": 256 print "verbose" 257 show_solo = True 258 elif opt == "--max": 259 max_stubs = int(arg) 260 print "max ", max_stubs 261 262 if len(args)>0: 263 source = args[0] 264 if source == "platform": 265 stem = "android" 266 print 267 print "*** PLATFORM PAGES ***" 268 print "======================" 269 270 # Insert the switchers at the top level first 271 insert_platform_summaries() 272 273 elif source == "androidx": 274 stem = "androidx" 275 print 276 print "*** ANDROIDX SUPPORT LIBRARY PAGES ***" 277 print "======================================" 278 279 elif source == "support": 280 stem = "android/support/v4/media" 281 print 282 print "*** ANDROIDX SUPPORT LIBRARY PAGES ***" 283 print "======================================" 284 285 elif source == "chrome": 286 stem = "org/chromium/support_lib_boundary" 287 print 288 print "*** ANDROIDX CHROMIUM PAGES ***" 289 print "===============================" 290 291 if (len(stem)>0): 292 scan_files(stem) 293 print " *** DONE ***" 294 else: 295 print 'You must specify one of: platform|androidx|support|chrome' 296 297 298 299if __name__ == "__main__": 300 main(sys.argv[1:]) 301 302