tools: add support of templates for hints

This commit is contained in:
simon.chupin 2022-07-25 17:19:07 +02:00 committed by Simon Chupin
parent 9cd98fbd4a
commit 270ed8d056
2 changed files with 153 additions and 60 deletions

View File

@ -1,57 +1,76 @@
# -
# re: Regular expression of error to search
# hint: Message of the hint. Optionally, it is possible to use '{}' at the place where the matched group from 're' should be inserted. This requires 'match_to_output: True'.
# hint: The message of the hint. Optionally, it is possible to use '{}' at the place where the matched group from 're' should be inserted. This requires 'match_to_output: True'. You can use variables with hint messages. For this, you need to add variables and "{}" in a place where you want to put your hint variable, but you can't use 'match_to_output' with variables.
# match_to_output: (False by default) see the description of 'hint'.
# variables:
# -
# re_variables: [set variable for regular expression]
# hint_variables: [set variable for hint]
# Rules to write regex for hints on how to resolve errors
# - Do not use more than one whitespace in a row. The script automatically merges several whitespaces into one when capturing output
# - Do not use \n in your regex. They are all automatically deletes by the script when capturing output
#
# example of using hints:
# -
# re: "Error: header {} is missing" (you can use '{1} ... {1}' placeholders in 'hint' and 're', so that you don't have to repeat the same variables, you can use 'hint: 'The {0} (functions/types/macros prefixed with '{1}') has been made into a private API. If users still require usage of the {0} (though this is not recommended), it can be included via #include "esp_private/{2}.h".' in this file as an example)
# hint: "header {} is missing, you need to add dependency on component {}"
# variables:
# -
# re_variables: [Q]
# hint_variables: [A, B]
# -
# re_variables: [W]
# hint_variables: [C, D]
# -
# re_variables: [R]
# hint_variables: [E, F]
#
# that example will replace this :
# -
# re: "Error: header Q is missing"
# hint: "header A is missing, you need to add dependency on component B"
# -
# re: Error: header W is missing"
# hint: "header C is missing, you need to add dependency on component D"
# -
# re: Error: header R is missing"
# hint: "header E is missing, you need to add dependency on component F"
-
re: "warning: passing argument 1 of 'esp_secure_boot_read_key_digests' from incompatible pointer type"
hint: "The parameter type of the function esp_secure_boot_read_key_digests() has been changed from ets_secure_boot_key_digests_t* to esp_secure_boot_key_digests_t*."
-
re: "error: implicit declaration of function 'bootloader_common_get_reset_reason'"
hint: "'bootloader_common_get_reset_reason()' has been removed. Please use the function 'esp_rom_get_reset_reason()' in the ROM component."
re: "error: implicit declaration of function '{}'"
hint: "Function '{}' has been removed. Please use the function {}."
variables:
-
re_variables: [bootloader_common_get_reset_reason]
hint_variables: [bootloader_common_get_reset_reason(), "'esp_rom_get_reset_reason()' in the ROM component"]
-
re_variables: [esp_efuse_get_chip_ver]
hint_variables: [esp_efuse_get_chip_ver(), efuse_hal_get_major_chip_version(), efuse_hal_get_minor_chip_version() or efuse_hal_chip_revision() instead]
-
re_variables: [(esp_spiram_get_chip_size|esp_spiram_get_size)]
hint_variables: [esp_spiram_get_chip_size and esp_spiram_get_size, esp_psram_get_size()]
-
re: "error: implicit declaration of function 'esp_secure_boot_verify_sbv2_signature_block|esp_secure_boot_verify_rsa_signature_block'"
hint: "'esp_secure_boot_verify_sbv2_signature_block()' and 'esp_secure_boot_verify_rsa_signature_block()' and has been made private and are no longer available."
hint: "'esp_secure_boot_verify_sbv2_signature_block()' and 'esp_secure_boot_verify_rsa_signature_block()' and have been made private and are no longer available."
-
re: "error: implicit declaration of function 'esp_cpu_ccount_t'"
hint: "Use esp_cpu_cycle_count_t defined in esp_cpu.h instead of esp_cpu_ccount_t."
-
re: "error: implicit declaration of function 'esp_cpu_(g|s)et_ccount'"
hint: "Use esp_cpu_{}et_cycle_count() defined in esp_cpu.h instead."
match_to_output: True
-
re: "error: implicit declaration of function 'esp_efuse_get_chip_ver'"
hint: "Function esp_efuse_get_chip_ver() has been removed. Use efuse_hal_get_major_chip_version(), efuse_hal_get_minor_chip_version() or efuse_hal_chip_revision() instead."
-
re: "error: implicit declaration of function '(esp_random|esp_fill_random)'"
hint: "esp_random.h header file is not included by esp_system.h anymore. It shall then be manually included with #include \"esp_random.h\""
-
re: "error: implicit declaration of function '(esp_base_mac_addr_(s|g)et|esp_efuse_mac_get_(custom|default)|esp_read_mac|esp_derive_local_mac)'"
hint: "esp_mac.h header file is not included by esp_system.h anymore. It shall then be manually included with #include \"esp_mac.h\""
-
re: "error: (implicit declaration of function 'esp_chip_info'|unknown type name 'esp_chip_info_t')"
hint: "esp_chip_info.h header file is not included by esp_system.h anymore. It shall then be manually included with #include \"esp_chip_info.h\""
-
re: "error: implicit declaration of function 'esp_int_wdt_\\w+'"
hint: "The Interrupt Watchdog API has been made private, it shall not be used anymore. You can still force its inclusion with #include \"esp_private/esp_int_wdt.h\" (not recommended)"
-
re: "error: implicit declaration of function '(esp_spiram_get_chip_size|esp_spiram_get_size)'"
hint: "{}() has been deleted, please use esp_psram_get_size() instead."
match_to_output: True
re: "error: implicit declaration of function '{}'"
hint: '{0}.h header file is not included by esp_system.h anymore. It shall then be manually included with #include "{0}.h"'
variables:
-
re_variables: [(esp_random|esp_fill_random)]
hint_variables: [esp_random]
-
re_variables: [(esp_base_mac_addr_(s|g)et|esp_efuse_mac_get_(custom|default)|esp_read_mac|esp_derive_local_mac)]
hint_variables: [esp_mac]
-
re_variables: [esp_chip_info]
hint_variables: [esp_chip_info]
-
re: "fatal error: (spiram.h|esp_spiram.h): No such file or directory"
@ -59,19 +78,39 @@
match_to_output: True
-
re: "fatal error: (soc/cpu.h|compare_set.h): No such file or directory"
hint: "{} was removed. Include and use the API function provided by esp_cpu.h instead."
match_to_output: True
re: "error: implicit declaration of function '{}'"
hint: "Use {} defined in esp_cpu.h instead of {}."
variables:
-
re_variables: [esp_cpu_ccount_t]
hint_variables: [esp_cpu_cycle_count_t, esp_cpu_ccount_t]
-
re_variables: [esp_cpu_get_ccount]
hint_variables: [esp_cpu_get_cycle_count(), esp_cpu_get_ccount]
-
re_variables: [esp_cpu_set_ccount]
hint_variables: [esp_cpu_set_cycle_count(), esp_cpu_set_ccount]
-
re: "fatal error: (esp_intr.h): No such file or directory"
hint: "{} was removed. Include esp_intr_alloc.h instead."
match_to_output: True
re: "fatal error: {}: No such file or directory"
hint: "{} was removed. Include {} instead."
variables:
-
re_variables: [esp_intr.h]
hint_variables: [esp_intr.h, esp_intr_alloc.h]
-
re_variables: [soc/cpu.h]
hint_variables: [soc/cpu.h, and use the API function provided by esp_cpu.h]
-
re_variables: [compare_set.h]
hint_variables: [compare_set.h, and use the API function provided by esp_cpu.h]
-
re_variables: [esp_panic.h]
hint_variables: [esp_panic.h, use functionalities provided in esp_debug_helpers.h]
-
re: "fatal error: (esp_panic.h): No such file or directory"
hint: "{} was made private. Use functionalities provided in esp_debug_helpers.h instead."
match_to_output: True
re: "error: implicit declaration of function 'esp_int_wdt_\\w+'"
hint: 'The Interrupt Watchdog API has been made private, it shall not be used anymore. You can still force its inclusion with #include "esp_private/esp_int_wdt.h" (not recommended)'
-
re: "fatal error: soc/(spinlock.h|clk_ctrl_os.h|rtc_wdt.h): No such file or directory"
@ -83,9 +122,6 @@
hint: "{} was renamed and made private. Consider using the logging APIs provided under esp_log.h instead."
match_to_output: True
-
re: "fatal error: eh_frame_parser.h: No such file or directory"
hint: "Backtrace Parser API (eh_frame_parser.h) has been made private, it shall not be used anymore. You can still force its inclusion with #include \"esp_private/eh_frame_parser.h\" (not recommended)"
-
re: "error: unknown type name '(portTickType|xTaskHandle|xQueueHandle|xSemaphoreHandle|xQueueSetHandle|xQueueSetMemberHandle|xTimeOutType|xMemoryRegion|xTaskParameters|xTaskStatusType|xTimerHandle|xCoRoutineHandle|pdTASK_HOOK_CODE|tmrTIMER_CALLBACK|pdTASK_CODE|xListItem|xList)'"
hint: "You maybe using pre FreeRTOS V8.0.0 data types. The backward compatibility of such data types is no longer enabled by default. Please turn on CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY explicitly to use such data types."
@ -115,6 +151,26 @@
hint: "Please check that the function name is correct. Also it is possible that you've forgot to import {} library(s) in header file or add the necessary REQURIES component. Try to add missing libraries to your project header file or check idf_component_register(REQUIRES ...) section in your component CmakeList.txt file. For more information run 'idf.py docs -sp api-guides/build-system.html'.\nAlso, please check if the function has been removed, renamed or replaced by an alternative function - refer to the migration guide for more information."
match_to_output: True
-
re: "fatal error: {}.h: No such file or directory"
hint: 'The {0} (functions/types/macros prefixed with "{1}") has been made into a private API. If users still require usage of the {0} (though this is not recommended), it can be included via #include "esp_private/{2}.h".'
variables:
-
re_variables: [esp32\\w*\\/clk]
hint_variables: [ESP Clock API, esp_clk, esp_clk]
-
re_variables: [esp32\\w*\\/cache_err_int]
hint_variables: [Cache Error Interrupt API, esp_cache_err, cache_err_int]
-
re_variables: [brownout]
hint_variables: [Brownout API, esp_brownout, brownout]
-
re_variables: [trax]
hint_variables: [Trax API, trax_, trax]
-
re_variables: [eh_frame_parser]
hint_variables: [Backtrace Parser API, eh_frame_parser, eh_frame_parser]
-
re: "fatal error: esp_adc_cal.h: No such file or directory"
hint: "``esp_adc_cal`` component is no longer supported. New adc calibration driver is in ``esp_adc``. Legacy adc calibration driver has been moved into ``esp_adc`` component. To use legacy ``esp_adc_cal`` driver APIs, you should add ``esp_adc`` component to the list of component requirements in CMakeLists.txt. For more information run 'idf.py docs -sp migration-guides/release-5.x/peripherals.html'."

View File

@ -8,11 +8,10 @@ import sys
from asyncio.subprocess import Process
from io import open
from types import FunctionType
from typing import Any, Dict, List, Optional, TextIO, Tuple, Union
from typing import Any, Dict, List, Match, Optional, TextIO, Tuple, Union
import click
import yaml
from idf_monitor_base.output_helpers import yellow_print
from .constants import GENERATORS
from .errors import FatalError
@ -79,6 +78,23 @@ def idf_version() -> Optional[str]:
return version
def color_print(message: str, color: str, newline: Optional[str]='\n') -> None:
""" Print a message to stderr with colored highlighting """
ansi_normal = '\033[0m'
sys.stderr.write('%s%s%s%s' % (color, message, ansi_normal, newline))
sys.stderr.flush()
def yellow_print(message: str, newline: Optional[str]='\n') -> None:
ansi_yellow = '\033[0;33m'
color_print(message, ansi_yellow, newline)
def red_print(message: str, newline: Optional[str]='\n') -> None:
ansi_red = '\033[1;31m'
color_print(message, ansi_red, newline)
def print_hints(*filenames: str) -> None:
"""Getting output files and printing hints on how to resolve errors based on the output."""
with open(os.path.join(os.path.dirname(__file__), 'hints.yml'), 'r') as file:
@ -87,18 +103,39 @@ def print_hints(*filenames: str) -> None:
with open(file_name, 'r') as file:
output = ' '.join(line.strip() for line in file if line.strip())
for hint in hints:
variables_list = hint.get('variables')
hint_list, hint_vars, re_vars = [], [], []
match: Optional[Match[str]] = None
try:
match = re.compile(hint['re']).findall(output)
except KeyError:
raise KeyError("Argument 're' missing in {}. Check hints.yml file.".format(hint))
if variables_list:
for variables in variables_list:
hint_vars = variables['re_variables']
re_vars = variables['hint_variables']
regex = hint['re'].format(*re_vars)
if re.compile(regex).search(output):
try:
hint_list.append(hint['hint'].format(*hint_vars))
except KeyError as e:
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
sys.exit(1)
else:
match = re.compile(hint['re']).search(output)
except KeyError as e:
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
sys.exit(1)
except re.error as e:
raise re.error('{} from hints.yml have {} problem. Check hints.yml file.'.format(hint['re'], e))
if match:
extra_info = ', '.join(match) if hint.get('match_to_output', '') else ''
red_print('{} from hints.yml have {} problem. Check hints.yml file.'.format(hint['re'], e))
sys.exit(1)
if hint_list:
for message in hint_list:
yellow_print('HINT:', message)
elif match:
extra_info = ', '.join(match.groups()) if hint.get('match_to_output', '') else ''
try:
yellow_print(' '.join(['HINT:', hint['hint'].format(extra_info)]))
except KeyError:
raise KeyError("Argument 'hint' missing in {}. Check hints.yml file.".format(hint))
except KeyError as e:
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
sys.exit(1)
def fit_text_in_terminal(out: str) -> str: