blob: 31c39f0b327bd5d70d55cd51f1bd049c519c34e6 [file]
# Copyright (C) 2023 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.
import argparse
import os
from enum import Enum
from collections import defaultdict
class Severity(Enum):
ENABLED_ERRORS=0
ENABLED_WARNINGS=1
DISABLED_CHECKS=2
def to_flag_string(self):
if self == Severity.ENABLED_ERRORS:
return "ERROR"
elif self == Severity.ENABLED_WARNINGS:
return "WARN"
else:
return "OFF"
def extract_error_prone_default_checks_by_severity(filename):
"""
Args:
filename: filename containing the default checks in a version of Errorprone
Returns:
default_checks: a dictionary representing the Default Errorprone checks, a
check_name maps to a severity.
"""
default_checks = {}
with open(filename) as f:
lines = f.readlines()
current_severity = ""
for line in lines:
line = line[:-1]
if line in [severity.name for severity in Severity]:
current_severity = Severity[line]
else:
default_checks[line] = current_severity
return default_checks
def get_bazel_compatibility_checks(soong_file, bazel_file):
"""
Args:
soong_file: name of file containing the default checks in the Soong version
of Errorprone
bazel_file: name of file containing the default checks in the Bazel version
of Errorprone
Returns:
a dictionary representing the checks that need to be modified in
Bazel in order for its checks to match Soong's default checks.
check_name maps to a severity.
"""
soong_defaults = extract_error_prone_default_checks_by_severity(soong_file)
bazel_defaults= extract_error_prone_default_checks_by_severity(bazel_file)
return {
check:Severity.DISABLED_CHECKS
for check in bazel_defaults
if check not in soong_defaults and bazel_defaults[check] != Severity.DISABLED_CHECKS
}|{
check:soong_severity
for check, soong_severity in soong_defaults.items()
if check not in bazel_defaults or soong_severity != bazel_defaults[check]
}
def check_to_flag_string(check_name, severity):
return "-Xep:" + check_name + ":" + severity.to_flag_string()
def checks_to_flags(compatibility_checks):
"""
iterates over items in compatibility_checks dic and returns a dic of the flags
using the -Xep:<checkName>[:severity] format
Args:
compatibility_checks: output from checks_dic.
Returns:
severity_to_flag: Dic mapping severities to the command-line flag
"""
severity_to_flag = defaultdict(list)
for check_name, severity in compatibility_checks.items():
severity_to_flag[severity].append(check_to_flag_string(check_name, severity))
for severity in severity_to_flag:
severity_to_flag[severity].sort()
return severity_to_flag
def license_header():
return "# Copyright (C) 2023 The Android Open Source Project\n" \
"#\n" \
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n" \
"# you may not use this file except in compliance with the License.\n" \
"# You may obtain a copy of the License at\n" \
"#\n" \
"# http://www.apache.org/licenses/LICENSE-2.0\n" \
"#\n" \
"# Unless required by applicable law or agreed to in writing, software\n" \
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n" \
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" \
"# See the License for the specific language governing permissions and\n" \
"# limitations under the License.\n\n" \
def output_as_bzl_file(flags):
filename = os.path.dirname(os.path.abspath(__file__)) + "/errorprone_flags.bzl"
with open(filename, 'w') as f:
f.write(license_header())
f.write("# DO NOT MODIFY: This file is auto-generated by errorProneCompatibilityFlags.sh\n")
f.write("errorprone_soong_bazel_diffs = [\n")
for severity in Severity:
f.write(" # Errorprone {severity}\n".format(severity=severity.name))
for flag in flags[severity]:
f.write(" \"{flag}\",\n".format(flag=flag))
f.write("]\n")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--soong_file", required=True,
help="file containing the default checks in the "
"Soong version of Error Prone")
parser.add_argument("--bazel_file",required=True,
help="file containing the default checks in the"
"Bazel version of the Error Prone")
args = parser.parse_args()
compatibility_checks = get_bazel_compatibility_checks(args.soong_file, args.bazel_file)
compatibility_flags = checks_to_flags(compatibility_checks)
output_as_bzl_file(compatibility_flags)
if __name__ == '__main__':
main()