• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(
49      '--disabled-rules', dest='disabled_rules'
50  )
51  parser.add_argument('--editorconfig', default=EDITOR_CONFIG)
52  parser.set_defaults(format=False, verify_format=True)
53  args = parser.parse_args()
54  kt_files = [f for f in args.file if f.endswith('.kt') or f.endswith('.kts')]
55  if not kt_files:
56    sys.exit(0)
57
58  disabled_rules = [
59      'indent',
60      'paren-spacing',
61      'curly-spacing',
62      'wrapping',
63      # trailing-comma requires wrapping
64      'trailing-comma-on-call-site',
65      'trailing-comma-on-declaration-site',
66      # annotations requires wrapping
67      'spacing-between-declarations-with-annotations',
68      'annotation',
69  ]
70
71  # Disable more format-related rules if we shouldn't verify the format. This is usually
72  # the case if files we are checking are already checked by ktfmt.
73  if not args.verify_format:
74    disabled_rules += [
75        # Please keep sorted.
76        'annotation-spacing',
77        'argument-list-wrapping',
78        'block-comment-initial-star-alignment',
79        'chain-wrapping',
80        'comment-wrapping',
81        'final-newline',
82        'import-ordering',
83        # TODO(b/366424213): Enable this check again.
84        'max-line-length',
85        'multiline-if-else',
86        'no-consecutive-blank-lines',
87        'no-empty-first-line-in-method-block',
88        'parameter-list-wrapping',
89        'parameter-wrapping',
90        'spacing-between-declarations-with-comments',
91    ]
92
93  if args.disabled_rules:
94    additional_rules = args.disabled_rules.split(",")
95    disabled_rules.extend(rule for rule in additional_rules if rule not in disabled_rules)
96
97  ktlint_args = kt_files[:]
98  ktlint_args += ['--disabled_rules=' + ','.join(disabled_rules)]
99
100  # Setup editor config explicitly if defined - else will inherit from tree
101  if args.editorconfig is not None:
102    ktlint_args += ['--editorconfig', args.editorconfig]
103
104  # Automatically format files if requested.
105  if args.format:
106    ktlint_args += ['-F']
107
108  ktlint_env = os.environ.copy()
109  ktlint_env['JAVA_CMD'] = 'java'
110  try:
111    check = subprocess.Popen(
112        [
113            'java',
114            '--add-opens=java.base/java.lang=ALL-UNNAMED',
115            '-jar',
116            KTLINT_JAR,
117        ]
118        + ktlint_args,
119        stdout=subprocess.PIPE,
120        env=ktlint_env,
121    )
122    stdout, _ = check.communicate()
123    if stdout:
124      print('prebuilts/ktlint found errors in files you changed:')
125      print(stdout.decode('utf-8'))
126      if args.verify_format:
127        print(FORMAT_MESSAGE.format(MAIN_DIRECTORY, ' '.join(kt_files)))
128      sys.exit(1)
129    else:
130      sys.exit(0)
131  except OSError as e:
132    if e.errno == errno.ENOENT:
133      print('Error running ktlint!')
134      sys.exit(1)
135
136
137if __name__ == '__main__':
138  main()
139