1#!/usr/bin/env python3 2 3# 4# Copyright 2017, The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19"""Script that is used by developers to run style checks on Kotlin files.""" 20 21from __future__ import print_function 22 23import argparse 24import errno 25import os 26import subprocess 27import sys 28 29MAIN_DIRECTORY = os.path.normpath(os.path.dirname(__file__)) 30KTLINT_JAR = os.path.join(MAIN_DIRECTORY, 'ktlint-android-all.jar') 31EDITOR_CONFIG = os.path.join(MAIN_DIRECTORY, '.editorconfig') 32FORMAT_MESSAGE = """ 33********************************************************************** 34To format run: 35{}/ktlint.py --format --file {} 36********************************************************************** 37""" 38 39 40def main(args=None): 41 parser = argparse.ArgumentParser() 42 parser.add_argument('--file', '-f', nargs='*') 43 parser.add_argument('--format', '-F', dest='format', action='store_true') 44 parser.add_argument('--noformat', dest='format', action='store_false') 45 parser.add_argument( 46 '--no-verify-format', dest='verify_format', action='store_false' 47 ) 48 parser.add_argument('--editorconfig', default=EDITOR_CONFIG) 49 parser.set_defaults(format=False, verify_format=True) 50 args = parser.parse_args() 51 kt_files = [f for f in args.file if f.endswith('.kt') or f.endswith('.kts')] 52 if not kt_files: 53 sys.exit(0) 54 55 disabled_rules = [ 56 'indent', 57 'paren-spacing', 58 'curly-spacing', 59 'wrapping', 60 # trailing-comma requires wrapping 61 'trailing-comma-on-call-site', 62 'trailing-comma-on-declaration-site', 63 # annotations requires wrapping 64 'spacing-between-declarations-with-annotations', 65 'annotation', 66 ] 67 68 # Disable more format-related rules if we shouldn't verify the format. This is usually 69 # the case if files we are checking are already checked by ktfmt. 70 if not args.verify_format: 71 disabled_rules += [ 72 # Please keep sorted. 73 'annotation-spacing', 74 'argument-list-wrapping', 75 'block-comment-initial-star-alignment', 76 'chain-wrapping', 77 'comment-wrapping', 78 'final-newline', 79 'import-ordering', 80 # TODO(b/366424213): Enable this check again. 81 'max-line-length', 82 'multiline-if-else', 83 'no-consecutive-blank-lines', 84 'no-empty-first-line-in-method-block', 85 'parameter-list-wrapping', 86 'spacing-between-declarations-with-comments', 87 ] 88 89 ktlint_args = kt_files[:] 90 ktlint_args += ['--disabled_rules=' + ','.join(disabled_rules)] 91 92 # Setup editor config explicitly if defined - else will inherit from tree 93 if args.editorconfig is not None: 94 ktlint_args += ['--editorconfig', args.editorconfig] 95 96 # Automatically format files if requested. 97 if args.format: 98 ktlint_args += ['-F'] 99 100 ktlint_env = os.environ.copy() 101 ktlint_env['JAVA_CMD'] = 'java' 102 try: 103 check = subprocess.Popen( 104 [ 105 'java', 106 '--add-opens=java.base/java.lang=ALL-UNNAMED', 107 '-jar', 108 KTLINT_JAR, 109 ] 110 + ktlint_args, 111 stdout=subprocess.PIPE, 112 env=ktlint_env, 113 ) 114 stdout, _ = check.communicate() 115 if stdout: 116 print('prebuilts/ktlint found errors in files you changed:') 117 print(stdout.decode('utf-8')) 118 if args.verify_format: 119 print(FORMAT_MESSAGE.format(MAIN_DIRECTORY, ' '.join(kt_files))) 120 sys.exit(1) 121 else: 122 sys.exit(0) 123 except OSError as e: 124 if e.errno == errno.ENOENT: 125 print('Error running ktlint!') 126 sys.exit(1) 127 128 129if __name__ == '__main__': 130 main() 131