1# Copyright (C) 2023 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. 14import argparse 15import os 16from enum import Enum 17from collections import defaultdict 18 19class Severity(Enum): 20 ENABLED_ERRORS=0 21 ENABLED_WARNINGS=1 22 DISABLED_CHECKS=2 23 24 def to_flag_string(self): 25 if self == Severity.ENABLED_ERRORS: 26 return "ERROR" 27 elif self == Severity.ENABLED_WARNINGS: 28 return "WARN" 29 else: 30 return "OFF" 31 32def extract_error_prone_default_checks_by_severity(filename): 33 """ 34 Args: 35 filename: filename containing the default checks in a version of Errorprone 36 37 Returns: 38 default_checks: a dictionary representing the Default Errorprone checks, a 39 check_name maps to a severity. 40 """ 41 default_checks = {} 42 43 with open(filename) as f: 44 lines = f.readlines() 45 46 current_severity = "" 47 for line in lines: 48 line = line[:-1] 49 if line in [severity.name for severity in Severity]: 50 current_severity = Severity[line] 51 else: 52 default_checks[line] = current_severity 53 return default_checks 54 55def get_bazel_compatibility_checks(soong_file, bazel_file): 56 """ 57 Args: 58 soong_file: name of file containing the default checks in the Soong version 59 of Errorprone 60 bazel_file: name of file containing the default checks in the Bazel version 61 of Errorprone 62 63 64 Returns: 65 a dictionary representing the checks that need to be modified in 66 Bazel in order for its checks to match Soong's default checks. 67 check_name maps to a severity. 68 """ 69 soong_defaults = extract_error_prone_default_checks_by_severity(soong_file) 70 bazel_defaults= extract_error_prone_default_checks_by_severity(bazel_file) 71 72 return { 73 check:Severity.DISABLED_CHECKS 74 for check in bazel_defaults 75 if check not in soong_defaults and bazel_defaults[check] != Severity.DISABLED_CHECKS 76 }|{ 77 check:soong_severity 78 for check, soong_severity in soong_defaults.items() 79 if check not in bazel_defaults or soong_severity != bazel_defaults[check] 80 } 81 82 83def check_to_flag_string(check_name, severity): 84 return "-Xep:" + check_name + ":" + severity.to_flag_string() 85 86def checks_to_flags(compatibility_checks): 87 """ 88 iterates over items in compatibility_checks dic and returns a dic of the flags 89 using the -Xep:<checkName>[:severity] format 90 91 Args: 92 compatibility_checks: output from checks_dic. 93 94 Returns: 95 severity_to_flag: Dic mapping severities to the command-line flag 96 97 """ 98 severity_to_flag = defaultdict(list) 99 100 for check_name, severity in compatibility_checks.items(): 101 severity_to_flag[severity].append(check_to_flag_string(check_name, severity)) 102 103 for severity in severity_to_flag: 104 severity_to_flag[severity].sort() 105 106 return severity_to_flag 107 108 109def license_header(): 110 return "# Copyright (C) 2023 The Android Open Source Project\n" \ 111 "#\n" \ 112 "# Licensed under the Apache License, Version 2.0 (the \"License\");\n" \ 113 "# you may not use this file except in compliance with the License.\n" \ 114 "# You may obtain a copy of the License at\n" \ 115 "#\n" \ 116 "# http://www.apache.org/licenses/LICENSE-2.0\n" \ 117 "#\n" \ 118 "# Unless required by applicable law or agreed to in writing, software\n" \ 119 "# distributed under the License is distributed on an \"AS IS\" BASIS,\n" \ 120 "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" \ 121 "# See the License for the specific language governing permissions and\n" \ 122 "# limitations under the License.\n\n" \ 123 124def output_as_bzl_file(flags): 125 filename = os.path.dirname(os.path.abspath(__file__)) + "/errorprone_flags.bzl" 126 127 with open(filename, 'w') as f: 128 f.write(license_header()) 129 f.write("# DO NOT MODIFY: This file is auto-generated by errorProneCompatibilityFlags.sh\n") 130 f.write("errorprone_soong_bazel_diffs = [\n") 131 for severity in Severity: 132 f.write(" # Errorprone {severity}\n".format(severity=severity.name)) 133 for flag in flags[severity]: 134 f.write(" \"{flag}\",\n".format(flag=flag)) 135 136 f.write("]\n") 137 138def main(): 139 parser = argparse.ArgumentParser() 140 parser.add_argument("--soong_file", required=True, 141 help="file containing the default checks in the " 142 "Soong version of Error Prone") 143 parser.add_argument("--bazel_file",required=True, 144 help="file containing the default checks in the" 145 "Bazel version of the Error Prone") 146 args = parser.parse_args() 147 148 compatibility_checks = get_bazel_compatibility_checks(args.soong_file, args.bazel_file) 149 compatibility_flags = checks_to_flags(compatibility_checks) 150 151 output_as_bzl_file(compatibility_flags) 152 153if __name__ == '__main__': 154 main()