| # Copyright 2019 - The Android Open Source Project | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| ############################################################################### | |
| # This script adds a HTML snippet to the generated reference docs located at | |
| # developer.android.com/reference. The snippet renders HTML that adds links to | |
| # toggle between the Java and Kotlin versions of the page. | |
| ############################################################################### | |
| import getopt | |
| import os | |
| import sys | |
| # GLOBAL FLAGS | |
| global stubs | |
| global java_stubs, kotlin_stubs | |
| global work, verbose, show_solo, max_stubs | |
| global java_source_abs_path | |
| global kotlin_source_abs_path | |
| verbose = False # set True to list all files as they are stubbed (--verbose) | |
| work = False # set True to insert stubs, False to do a dry run for stats (--work) | |
| show_solo = False # set True to list files that only appear in one language, rather than both (--solo) | |
| max_stubs = 0 # set positive to create a limited number of stubs (--max 12) | |
| # You must run the script from the refodcs reference/ root directory | |
| java_ref_root = os.getcwd() | |
| kotlin_ref_root = os.path.join(java_ref_root, "kotlin") | |
| root = os.path.split(java_ref_root)[1] | |
| if root != "reference": | |
| print("You must cd to the refocs reference/ root directory") | |
| sys.exit() | |
| # This method inserts the language switcher into the two top-level Android | |
| # Platform pages: packages.html and classes.html | |
| # For both Java and Kotlin | |
| def insert_platform_summaries(): | |
| global stubs | |
| global java_stubs, kotlin_stubs | |
| global verbose, work, show_solo | |
| global java_source_abs_path | |
| global kotlin_source_abs_path | |
| stubs = 0 | |
| java_stubs = 0 | |
| kotlin_stubs = 0 | |
| java_source_abs_path = java_ref_root | |
| kotlin_source_abs_path = kotlin_ref_root | |
| insert_stub(os.path.join(java_ref_root, "packages.html"), True, True) | |
| insert_stub(os.path.join(kotlin_ref_root, "packages.html"), False, True) | |
| insert_stub(os.path.join(java_ref_root, "classes.html"), True, True) | |
| insert_stub(os.path.join(kotlin_ref_root, "classes.html"), False, True) | |
| # This method uses switcher2, which assumes the refdocs stay in their current | |
| # assymetrical dirs (ref/android and ref/kotlin/android) | |
| # And just puts the switcher in the existing docs | |
| def insert_stub(doc, java, both): | |
| global stubs | |
| global java_stubs, kotlin_stubs | |
| global verbose, work, show_solo | |
| global java_source_abs_path | |
| global kotlin_source_abs_path | |
| stubs = stubs+1 | |
| if verbose: | |
| print("File: ", stubs, doc) | |
| else: | |
| fn = os.path.split(doc) | |
| print("File: ", stubs, fn[1], end="\r") | |
| if (java): | |
| java_stubs = java_stubs + 1 | |
| else: | |
| kotlin_stubs = kotlin_stubs + 1 | |
| if (work): | |
| if (java): | |
| file_path = doc[len(java_ref_root)+1:] | |
| stub = doc.replace(java_source_abs_path, kotlin_source_abs_path) | |
| if (both): | |
| 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) | |
| else: | |
| slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% include \"reference\/_java_switcher2.md\" %}",doc) | |
| else: | |
| file_path = doc[len(kotlin_ref_root)+1:] | |
| stub = doc.replace(kotlin_source_abs_path, java_source_abs_path) | |
| if (both): | |
| 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) | |
| else: | |
| slug1 = "sed -i 's/<\/h1>/{}/' {}".format("<\/h1>\\n{% include \"reference\/_kotlin_switcher2.md\" %}",doc) | |
| os.system(slug1) | |
| if (both): | |
| page_path_slug = "sed -i 's/_page_path_/{}/' {}".format(file_path.replace("/","\/"),doc) | |
| os.system(page_path_slug) | |
| def scan_files(stem): | |
| global work, verbose, show_solo, max_stubs | |
| global stubs | |
| global java_stubs, kotlin_stubs | |
| global java_source_abs_path | |
| global kotlin_source_abs_path | |
| java_source_abs_path = os.path.join(java_ref_root, stem) | |
| kotlin_source_abs_path = os.path.join(kotlin_ref_root, stem) | |
| # Pass 1 | |
| # Loop over java content, create stubs for java, | |
| # and for corresponding Kotlin (when it exsits) | |
| # solo is java-only classes | |
| # both is java+kotlin | |
| stubs = 0 | |
| java_stubs = 0 | |
| kotlin_stubs = 0 | |
| solo = 0 | |
| both = 0 | |
| print("*** PASS1 (Java) ***") | |
| maxed_out = False | |
| for root, dirs, files in os.walk(java_source_abs_path): | |
| if maxed_out: | |
| break; | |
| for file_ in files: | |
| ext = os.path.splitext(file_) | |
| ext = ext[1] | |
| if not ext: | |
| # this catches package-lists with no extension | |
| print("***", os.path.join(root, file_)) | |
| elif ext != ".html": | |
| # filter out png, yaml, etc | |
| continue | |
| else: | |
| # we have java content | |
| doc = os.path.join(root, file_) | |
| # look for matching kotlin file | |
| kotlinsource = doc.replace(java_source_abs_path, kotlin_source_abs_path) | |
| if os.path.isfile(kotlinsource): | |
| # corresponding kotlin content exists | |
| insert_stub(doc, True, True) | |
| insert_stub(kotlinsource, False, True) | |
| both = both+1 | |
| else: | |
| # no kotlin content | |
| if (show_solo): | |
| print("solo: ", doc) | |
| insert_stub(doc, True, False) | |
| solo = solo+1 | |
| if max_stubs>0 and stubs>=max_stubs: | |
| print() | |
| print("max java stubs: ", max_stubs) | |
| maxed_out = True; | |
| break | |
| print("Java+Kotlin:", both, "Only Java:", solo) | |
| print() | |
| # PASS 2 | |
| # Loop over kotlin content, create stubs for Kotlin-only APIs | |
| print("*** PASS2 (Kotlin) ***") | |
| solo = 0 | |
| both = 0 | |
| maxed_out = False | |
| stubs = 0 | |
| for root, dirs, files in os.walk(kotlin_source_abs_path): | |
| if maxed_out: | |
| break; | |
| for file_ in files: | |
| ext = os.path.splitext (file_) | |
| ext = ext[1] | |
| if not ext: | |
| # this catches package-lists with no extension | |
| print("***", os.path.join(root, file_)) | |
| elif ext != ".html": | |
| # filter out png, yaml, etc | |
| continue | |
| else: | |
| # we have kotlin content | |
| doc = os.path.join(root, file_) | |
| javadoc = doc.replace(kotlin_source_abs_path, java_source_abs_path) | |
| file_name = os.path.splitext(file_)[0] | |
| file_path = doc[len(kotlin_source_abs_path)+1:] | |
| include_path = os.path.join("/reference/_kotlin", file_path) | |
| if os.path.isfile(javadoc): | |
| # corresponding java content exists | |
| # so we already created the kotlin stub file | |
| # nothing to do | |
| both = both+1 | |
| else: | |
| # no java content | |
| # create the kotlin stub file | |
| if (show_solo): | |
| print("solo: ", doc) | |
| insert_stub(doc , False, False) | |
| solo = solo+1 | |
| if (max_stubs>0 and stubs>=max_stubs): | |
| print() | |
| print("max koltin stubs: ", max_stubs) | |
| maxed_out = True; | |
| break | |
| print("Java+Kotlin:", both, "Only Kotlin:", solo) | |
| print() | |
| print("Java: ", java_stubs, " Kotlin: ", kotlin_stubs, "Total: ", java_stubs + kotlin_stubs) | |
| def main(argv): | |
| global work, verbose, show_solo, max_stubs | |
| global java_source_abs_path | |
| global kotlin_source_abs_path | |
| stem = "" | |
| try: | |
| opts, args = getopt.getopt(argv,"",["work","verbose","solo","max="]) | |
| except getopt.GetoptError: | |
| print('USAGE: switcher --work --verbose --solo --max=<max_stubs> platform|androidx|support|chrome') | |
| sys.exit(2) | |
| for opt, arg in opts: | |
| if opt == '--work': | |
| work = True | |
| elif opt == "--verbose": | |
| print("verbose") | |
| verbose = True | |
| elif opt == "--solo": | |
| print("verbose") | |
| show_solo = True | |
| elif opt == "--max": | |
| max_stubs = int(arg) | |
| print("max ", max_stubs) | |
| if len(args)>0: | |
| source = args[0] | |
| if source == "platform": | |
| stem = "android" | |
| print() | |
| print("*** PLATFORM PAGES ***") | |
| print("======================") | |
| # Insert the switchers at the top level first | |
| insert_platform_summaries() | |
| elif source == "androidx": | |
| stem = "androidx" | |
| print() | |
| print("*** ANDROIDX SUPPORT LIBRARY PAGES ***") | |
| print("======================================") | |
| elif source == "support": | |
| stem = "android/support/v4/media" | |
| print() | |
| print("*** ANDROIDX SUPPORT LIBRARY PAGES ***") | |
| print("======================================") | |
| elif source == "chrome": | |
| stem = "org/chromium/support_lib_boundary" | |
| print() | |
| print("*** ANDROIDX CHROMIUM PAGES ***") | |
| print("===============================") | |
| if (len(stem)>0): | |
| scan_files(stem) | |
| print(" *** DONE ***") | |
| else: | |
| print('You must specify one of: platform|androidx|support|chrome') | |
| if __name__ == "__main__": | |
| main(sys.argv[1:]) | |