1#!/usr/bin/env python 2# 3# Copyright (C) 2022 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"""Command line tool to convert API files to sdk-extensions-info. 17 18Example use: 19 20 $ ./api-to-sdk-ext-info.py $(gettop)/prebuilts/sdk/extensions/1/public/api/framework-sdkextensions.txt >/tmp/1.txt 21 $ ./api-to-sdk-ext-info.py $(gettop)/prebuilts/sdk/extensions/2/public/api/framework-sdkextensions.txt >/tmp/2.txt 22 $ diff /tmp/{1,2}.txt 23 0a1,2 24 > android.os.ext.SdkExtensions.getAllExtensionVersions 25 > android.os.ext.SdkExtensions.getExtensionVersion 26""" 27 28import re 29import sys 30 31re_package = re.compile(r"^package (.*?) \{(.*?)^\}", re.M + re.S) 32re_class = re.compile(r"^ .*? (?:class|interface) (\S+) .*?\{(.*?)^ \}", re.M + re.S) 33re_method = re.compile("^ (?:ctor|method).* (\S+)\([^)]*\);", re.M) 34re_field = re.compile(r"^ field.* (\S+)(?: =.*);", re.M) 35 36 37def parse_class(package_name, class_name, contents): 38 def print_members(regex, contents): 39 # sdk-extensions-info ignores method signatures: overloaded methods are 40 # collapsed into the same item; use a set to get this behaviour for free 41 members = set() 42 for symbol_name in regex.findall(contents): 43 members.add(f"{package_name}.{class_name}.{symbol_name}") 44 if len(members) > 0: 45 print("\n".join(sorted(members))) 46 47 print_members(re_field, contents) 48 print_members(re_method, contents) 49 50 51def parse_package(package_name, contents): 52 for match in re_class.findall(contents): 53 parse_class(package_name, match[0], match[1]) 54 55 56def main(): 57 with open(sys.argv[1]) as f: 58 contents = f.read() 59 60 if contents.splitlines()[0] != "// Signature format: 2.0": 61 raise "unexpected file format" 62 for match in re_package.findall(contents): 63 parse_package(match[0], match[1]) 64 65 66if __name__ == "__main__": 67 main() 68