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