blob: 044379584c16e617bd5245e257e8d06e99633ba1 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2022, 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.
#
"""Script to format or check Kotlin files."""
import argparse
import os
import subprocess
import sys
def main():
parser = argparse.ArgumentParser(
'Format Kotlin files or check that they are correctly formatted.')
parser.add_argument(
'--check',
'-c',
action='store_true',
default=False,
help='Perform a format check instead of formatting.')
parser.add_argument(
'--includes_file',
'-i',
default='',
help='The file containing the Kotlin files and directories that should be included/excluded, generated using generate_includes_file.py.'
)
parser.add_argument(
'--jar',
default='',
help='The path to the ktfmt jar.'
)
parser.add_argument(
'files',
nargs='*',
help='The files to format or check. If --include_file is specified, only the files at their intersection will be formatted/checked.'
)
args = parser.parse_args()
ktfmt_args = ['--kotlinlang-style']
check = args.check
if check:
ktfmt_args += ['--set-exit-if-changed', '--dry-run']
kt_files = []
for file in args.files:
if os.path.isdir(file):
for root, dirs, files in os.walk(file):
for f in files:
if is_kotlin_file(f):
kt_files += [os.path.join(root, f)]
if is_kotlin_file(file):
kt_files += [file]
# Only format/check files from the includes list.
includes_file = args.includes_file
if kt_files and includes_file:
f = open(includes_file, 'r')
lines = f.read().splitlines()
included = [line[1:] for line in lines if line.startswith('+')]
included_files = set()
included_dirs = []
for line in included:
if is_kotlin_file(line):
included_files.add(line)
else:
included_dirs += [line]
excluded_files = [line[1:] for line in lines if line.startswith('-')]
kt_files = [
kt_file for kt_file in kt_files if kt_file not in excluded_files and
(kt_file in included_files or is_included(kt_file, included_dirs))
]
# No need to start ktfmt if there are no files to check/format.
if not kt_files:
sys.exit(0)
ktfmt_args += kt_files
dir = os.path.normpath(os.path.dirname(__file__))
ktfmt_jar = args.jar if args.jar else os.path.join(dir, 'ktfmt.jar')
ktlint_env = os.environ.copy()
ktlint_env['JAVA_CMD'] = 'java'
try:
process = subprocess.Popen(
['java', '-jar', ktfmt_jar] + ktfmt_args,
stdout=subprocess.PIPE,
env=ktlint_env)
stdout, _ = process.communicate()
code = process.returncode
if check and code != 0:
print(
'**********************************************************************'
)
print(
'Some Kotlin files are not properly formatted. Run the command below to format them.\n'
'Note: If you are using the Android Studio ktfmt plugin, make sure to select the '
'Kotlinlang style in \'Editor > ktfmt Settings\'.\n')
script_path = os.path.normpath(__file__)
incorrect_files = [
os.path.abspath(file) for file in stdout.decode('utf-8').splitlines()
]
print('$ ' + script_path + ' ' + ' '.join(incorrect_files) + '\n')
print(
'**********************************************************************'
)
sys.exit(code)
else:
sys.exit(0)
except OSError as e:
print('Error running ktfmt')
sys.exit(1)
def is_kotlin_file(name):
return name.endswith('.kt') or name.endswith('.kts')
def is_included(file, dirs):
for dir in dirs:
if file.startswith(dir):
return True
if __name__ == '__main__':
main()