Merge branch 'feature/add_templates_for_hints' into 'master'

tools: add support of templates for hints

Closes IDF-5612

See merge request espressif/esp-idf!19227
This commit is contained in:
Simon Chupin 2022-08-18 22:38:33 +08:00
commit 1669a5d861
2 changed files with 150 additions and 73 deletions

View File

@ -1,58 +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"
@ -60,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"
@ -84,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."
@ -117,19 +152,24 @@
match_to_output: True
-
re: "fatal error: esp32\\w*\\/clk.h: No such file or directory"
hint: "The ESP Clock API (functions/types/macros prefixed with 'esp_clk') has been made into a private API. If users still require usage of the ESP Clock API (though this is not recommended), it can be included via '#include \"esp_private/esp_clk.h\"'."
-
re: "fatal error: esp32\\w*\\/cache_err_int.h: No such file or directory"
hint: "The Cache Error Interrupt API (functions/types/macros prefixed with 'esp_cache_err') has been made into a private API. If users still require usage of the Cache Error Interrupt API (though this is not recommended), it can be included via '#include \"esp_private/cache_err_int.h\"'"
-
re: "fatal error: brownout.h: No such file or directory"
hint: "The Brownout API (functions/types/macros prefixed with 'esp_brownout') has been made into a private API. If users still require usage of the Brownout API (though this is not recommended), it can be included via '#include \"esp_private/brownout.h\"'."
-
re: "fatal error: trax.h: No such file or directory"
hint: "The Trax API (functions/types/macros prefixed with 'trax_') has been made into a private API. If users still require usage of the Trax API (though this is not recommended), it can be included via '#include \"esp_private/trax.h\"'."
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"

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: