xref: /aosp_15_r20/prebuilts/ktlint/ktlint.py (revision f26b5dfd6a29909cfac6f25e5c20ca79705e337b)
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