diff options
author | Zach White <skullydazed@gmail.com> | 2021-08-28 19:37:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-29 12:37:55 +1000 |
commit | 566d59851634bf0ffb5b95dd85f65858b0905dc7 (patch) | |
tree | 7f632e9c4b08e231bad97e638d2635f9560b10b4 | |
parent | f155865804da332ac544e6a6bca0ca9035d3e818 (diff) | |
download | qmk_firmware-566d59851634bf0ffb5b95dd85f65858b0905dc7.tar.gz qmk_firmware-566d59851634bf0ffb5b95dd85f65858b0905dc7.zip |
Add check for non-assignment code in rules.mk (#12108)
* Add check for non-assignment code in rules.mk
* fix lint check
* fix lint
* fixup to reflect the final state of #8422
* fix lint
-rw-r--r-- | lib/python/qmk/cli/lint.py | 139 |
1 files changed, 98 insertions, 41 deletions
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py index 02b31fbc4..008ec1393 100644 --- a/lib/python/qmk/cli/lint.py +++ b/lib/python/qmk/cli/lint.py | |||
@@ -1,72 +1,129 @@ | |||
1 | """Command to look over a keyboard/keymap and check for common mistakes. | 1 | """Command to look over a keyboard/keymap and check for common mistakes. |
2 | """ | 2 | """ |
3 | from pathlib import Path | ||
4 | |||
3 | from milc import cli | 5 | from milc import cli |
4 | 6 | ||
5 | from qmk.decorators import automagic_keyboard, automagic_keymap | 7 | from qmk.decorators import automagic_keyboard, automagic_keymap |
6 | from qmk.info import info_json | 8 | from qmk.info import info_json |
7 | from qmk.keyboard import find_readme, keyboard_completer | 9 | from qmk.keyboard import keyboard_completer, list_keyboards |
8 | from qmk.keymap import locate_keymap | 10 | from qmk.keymap import locate_keymap |
9 | from qmk.path import is_keyboard, keyboard | 11 | from qmk.path import is_keyboard, keyboard |
10 | 12 | ||
11 | 13 | ||
14 | def keymap_check(kb, km): | ||
15 | """Perform the keymap level checks. | ||
16 | """ | ||
17 | ok = True | ||
18 | keymap_path = locate_keymap(kb, km) | ||
19 | |||
20 | if not keymap_path: | ||
21 | ok = False | ||
22 | cli.log.error("%s: Can't find %s keymap.", kb, km) | ||
23 | |||
24 | return ok | ||
25 | |||
26 | |||
27 | def rules_mk_assignment_only(keyboard_path): | ||
28 | """Check the keyboard-level rules.mk to ensure it only has assignments. | ||
29 | """ | ||
30 | current_path = Path() | ||
31 | errors = [] | ||
32 | |||
33 | for path_part in keyboard_path.parts: | ||
34 | current_path = current_path / path_part | ||
35 | rules_mk = current_path / 'rules.mk' | ||
36 | |||
37 | if rules_mk.exists(): | ||
38 | continuation = None | ||
39 | |||
40 | for i, line in enumerate(rules_mk.open()): | ||
41 | line = line.strip() | ||
42 | |||
43 | if '#' in line: | ||
44 | line = line[:line.index('#')] | ||
45 | |||
46 | if continuation: | ||
47 | line = continuation + line | ||
48 | continuation = None | ||
49 | |||
50 | if line: | ||
51 | if line[-1] == '\\': | ||
52 | continuation = line[:-1] | ||
53 | continue | ||
54 | |||
55 | if line and '=' not in line: | ||
56 | errors.append(f'Non-assignment code on line +{i} {rules_mk}: {line}') | ||
57 | |||
58 | return errors | ||
59 | |||
60 | |||
12 | @cli.argument('--strict', action='store_true', help='Treat warnings as errors.') | 61 | @cli.argument('--strict', action='store_true', help='Treat warnings as errors.') |
13 | @cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='The keyboard to check.') | 62 | @cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='The keyboard to check.') |
14 | @cli.argument('-km', '--keymap', help='The keymap to check.') | 63 | @cli.argument('-km', '--keymap', help='The keymap to check.') |
64 | @cli.argument('--all-kb', action='store_true', arg_only=True, help='Check all keyboards.') | ||
15 | @cli.subcommand('Check keyboard and keymap for common mistakes.') | 65 | @cli.subcommand('Check keyboard and keymap for common mistakes.') |
16 | @automagic_keyboard | 66 | @automagic_keyboard |
17 | @automagic_keymap | 67 | @automagic_keymap |
18 | def lint(cli): | 68 | def lint(cli): |
19 | """Check keyboard and keymap for common mistakes. | 69 | """Check keyboard and keymap for common mistakes. |
20 | """ | 70 | """ |
21 | if not cli.config.lint.keyboard: | 71 | failed = [] |
22 | cli.log.error('Missing required argument: --keyboard') | ||
23 | cli.print_help() | ||
24 | return False | ||
25 | 72 | ||
26 | if not is_keyboard(cli.config.lint.keyboard): | 73 | # Determine our keyboard list |
27 | cli.log.error('No such keyboard: %s', cli.config.lint.keyboard) | 74 | if cli.args.all_kb: |
28 | return False | 75 | if cli.args.keyboard: |
76 | cli.log.warning('Both --all-kb and --keyboard passed, --all-kb takes presidence.') | ||
29 | 77 | ||
30 | # Gather data about the keyboard. | 78 | keyboard_list = list_keyboards() |
31 | ok = True | 79 | elif not cli.config.lint.keyboard: |
32 | keyboard_path = keyboard(cli.config.lint.keyboard) | 80 | cli.log.error('Missing required arguments: --keyboard or --all-kb') |
33 | keyboard_info = info_json(cli.config.lint.keyboard) | 81 | cli.print_help() |
34 | readme_path = find_readme(cli.config.lint.keyboard) | 82 | return False |
35 | missing_readme_path = keyboard_path / 'readme.md' | 83 | else: |
84 | keyboard_list = cli.args.keyboard.split(',') | ||
36 | 85 | ||
37 | # Check for errors in the info.json | 86 | # Lint each keyboard |
38 | if keyboard_info['parse_errors']: | 87 | for kb in keyboard_list: |
39 | ok = False | 88 | if not is_keyboard(kb): |
40 | cli.log.error('Errors found when generating info.json.') | 89 | cli.log.error('No such keyboard: %s', kb) |
90 | continue | ||
41 | 91 | ||
42 | if cli.config.lint.strict and keyboard_info['parse_warnings']: | 92 | # Gather data about the keyboard. |
43 | ok = False | 93 | ok = True |
44 | cli.log.error('Warnings found when generating info.json (Strict mode enabled.)') | 94 | keyboard_path = keyboard(kb) |
95 | keyboard_info = info_json(kb) | ||
45 | 96 | ||
46 | # Check for a readme.md and warn if it doesn't exist | 97 | # Check for errors in the info.json |
47 | if not readme_path: | 98 | if keyboard_info['parse_errors']: |
48 | ok = False | 99 | ok = False |
49 | cli.log.error('Missing %s', missing_readme_path) | 100 | cli.log.error('%s: Errors found when generating info.json.', kb) |
50 | 101 | ||
51 | # Keymap specific checks | 102 | if cli.config.lint.strict and keyboard_info['parse_warnings']: |
52 | if cli.config.lint.keymap: | 103 | ok = False |
53 | keymap_path = locate_keymap(cli.config.lint.keyboard, cli.config.lint.keymap) | 104 | cli.log.error('%s: Warnings found when generating info.json (Strict mode enabled.)', kb) |
54 | 105 | ||
55 | if not keymap_path: | 106 | # Check the rules.mk file(s) |
107 | rules_mk_assignment_errors = rules_mk_assignment_only(keyboard_path) | ||
108 | if rules_mk_assignment_errors: | ||
56 | ok = False | 109 | ok = False |
57 | cli.log.error("Can't find %s keymap for %s keyboard.", cli.config.lint.keymap, cli.config.lint.keyboard) | 110 | cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb) |
58 | else: | 111 | for assignment_error in rules_mk_assignment_errors: |
59 | keymap_readme = keymap_path.parent / 'readme.md' | 112 | cli.log.error(assignment_error) |
60 | if not keymap_readme.exists(): | ||
61 | cli.log.warning('Missing %s', keymap_readme) | ||
62 | 113 | ||
63 | if cli.config.lint.strict: | 114 | # Keymap specific checks |
64 | ok = False | 115 | if cli.config.lint.keymap: |
116 | if not keymap_check(kb, cli.config.lint.keymap): | ||
117 | ok = False | ||
118 | |||
119 | # Report status | ||
120 | if not ok: | ||
121 | failed.append(kb) | ||
65 | 122 | ||
66 | # Check and report the overall status | 123 | # Check and report the overall status |
67 | if ok: | 124 | if failed: |
68 | cli.log.info('Lint check passed!') | 125 | cli.log.error('Lint check failed for: %s', ', '.join(failed)) |
69 | return True | 126 | return False |
70 | 127 | ||
71 | cli.log.error('Lint check failed!') | 128 | cli.log.info('Lint check passed!') |
72 | return False | 129 | return True |