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