From 58721a433b81790368386cf117347e5bd31fa961 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Mon, 22 Jan 2024 11:35:51 +0000 Subject: [PATCH] Move layout macro OOB checks to lint (#22610) --- lib/python/qmk/cli/generate/keyboard_h.py | 11 ++------- lib/python/qmk/info.py | 29 ++++++++++++++++++++--- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/python/qmk/cli/generate/keyboard_h.py b/lib/python/qmk/cli/generate/keyboard_h.py index b9e89032b9e2..5863a0983ad3 100755 --- a/lib/python/qmk/cli/generate/keyboard_h.py +++ b/lib/python/qmk/cli/generate/keyboard_h.py @@ -33,18 +33,11 @@ def _generate_layouts(keyboard, kb_info_json): layout_keys = [] layout_matrix = [['KC_NO'] * col_num for _ in range(row_num)] - for index, key_data in enumerate(layout_data['layout']): + for key_data in layout_data['layout']: row, col = key_data['matrix'] identifier = f'k{ROW_LETTERS[row]}{COL_LETTERS[col]}' - if row >= row_num or col >= col_num: - key_name = key_data.get('label', identifier) - if row >= row_num: - cli.log.error(f'{keyboard}/{layout_name}: Matrix row for key {index} ({key_name}) is {row} but must be less than {row_num}') - - if col >= col_num: - cli.log.error(f'{keyboard}/{layout_name}: Matrix column for key {index} ({key_name}) is {col} but must be less than {col_num}') - + cli.log.error(f'Skipping layouts due to {layout_name} containing invalid matrix values') return [] layout_matrix[row][col] = identifier diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py index d51741ecb6e6..d42ba5c660fc 100644 --- a/lib/python/qmk/info.py +++ b/lib/python/qmk/info.py @@ -7,7 +7,7 @@ from milc import cli -from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS +from qmk.constants import COL_LETTERS, ROW_LETTERS, CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS from qmk.c_parse import find_layouts, parse_config_h_file, find_led_config from qmk.json_schema import deep_update, json_load, validate from qmk.keyboard import config_h, rules_mk @@ -78,9 +78,11 @@ def _find_invalid_encoder_index(info_data): return ret -def _additional_validation(keyboard, info_data): +def _validate_layouts(keyboard, info_data): """Non schema checks """ + col_num = info_data.get('matrix_size', {}).get('cols', 0) + row_num = info_data.get('matrix_size', {}).get('rows', 0) layouts = info_data.get('layouts', {}) layout_aliases = info_data.get('layout_aliases', {}) community_layouts = info_data.get('community_layouts', []) @@ -90,6 +92,16 @@ def _additional_validation(keyboard, info_data): if len(layouts) == 0 or all(not layout.get('json_layout', False) for layout in layouts.values()): _log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in info.json.') + # Make sure all matrix values are in bounds + for layout_name, layout_data in layouts.items(): + for index, key_data in enumerate(layout_data['layout']): + row, col = key_data['matrix'] + key_name = key_data.get('label', f'k{ROW_LETTERS[row]}{COL_LETTERS[col]}') + if row >= row_num: + _log_error(info_data, f'{layout_name}: Matrix row for key {index} ({key_name}) is {row} but must be less than {row_num}') + if col >= col_num: + _log_error(info_data, f'{layout_name}: Matrix column for key {index} ({key_name}) is {col} but must be less than {col_num}') + # Warn if physical positions are offset (at least one key should be at x=0, and at least one key at y=0) for layout_name, layout_data in layouts.items(): offset_x = min([_get_key_left_position(k) for k in layout_data['layout']]) @@ -122,12 +134,20 @@ def _additional_validation(keyboard, info_data): if layout_name not in layouts and layout_name not in layout_aliases: _log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name)) + +def _validate_keycodes(keyboard, info_data): + """Non schema checks + """ # keycodes with length > 7 must have short forms for visualisation purposes for decl in info_data.get('keycodes', []): if len(decl["key"]) > 7: if not decl.get("aliases", []): _log_error(info_data, f'Keycode {decl["key"]} has no short form alias') + +def _validate_encoders(keyboard, info_data): + """Non schema checks + """ # encoder IDs in layouts must be in range and not duplicated found = _find_invalid_encoder_index(info_data) for layout_name, encoder_index, reason in found: @@ -141,7 +161,10 @@ def _validate(keyboard, info_data): try: validate(info_data, 'qmk.api.keyboard.v1') - _additional_validation(keyboard, info_data) + # Additional validation + _validate_layouts(keyboard, info_data) + _validate_keycodes(keyboard, info_data) + _validate_encoders(keyboard, info_data) except jsonschema.ValidationError as e: json_path = '.'.join([str(p) for p in e.absolute_path])