Skip to content

Commit 1669a5d

Browse files
author
Simon Chupin
committed
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
2 parents a2f028a + cc1eb81 commit 1669a5d

File tree

2 files changed

+152
-75
lines changed

2 files changed

+152
-75
lines changed

tools/idf_py_actions/hints.yml

+105-65
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,116 @@
11
# -
22
# re: Regular expression of error to search
3-
# 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'.
3+
# 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.
44
# match_to_output: (False by default) see the description of 'hint'.
5-
6-
5+
# variables:
6+
# -
7+
# re_variables: [set variable for regular expression]
8+
# hint_variables: [set variable for hint]
79
# Rules to write regex for hints on how to resolve errors
810
# - Do not use more than one whitespace in a row. The script automatically merges several whitespaces into one when capturing output
911
# - Do not use \n in your regex. They are all automatically deletes by the script when capturing output
12+
#
13+
# example of using hints:
14+
# -
15+
# 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)
16+
# hint: "header {} is missing, you need to add dependency on component {}"
17+
# variables:
18+
# -
19+
# re_variables: [Q]
20+
# hint_variables: [A, B]
21+
# -
22+
# re_variables: [W]
23+
# hint_variables: [C, D]
24+
# -
25+
# re_variables: [R]
26+
# hint_variables: [E, F]
27+
#
28+
# that example will replace this :
29+
# -
30+
# re: "Error: header Q is missing"
31+
# hint: "header A is missing, you need to add dependency on component B"
32+
# -
33+
# re: Error: header W is missing"
34+
# hint: "header C is missing, you need to add dependency on component D"
35+
# -
36+
# re: Error: header R is missing"
37+
# hint: "header E is missing, you need to add dependency on component F"
1038

1139
-
1240
re: "warning: passing argument 1 of 'esp_secure_boot_read_key_digests' from incompatible pointer type"
1341
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*."
1442

1543
-
16-
re: "error: implicit declaration of function 'bootloader_common_get_reset_reason'"
17-
hint: "'bootloader_common_get_reset_reason()' has been removed. Please use the function 'esp_rom_get_reset_reason()' in the ROM component."
44+
re: "error: implicit declaration of function '{}'"
45+
hint: "Function '{}' has been removed. Please use the function {}."
46+
variables:
47+
-
48+
re_variables: [bootloader_common_get_reset_reason]
49+
hint_variables: [bootloader_common_get_reset_reason(), "'esp_rom_get_reset_reason()' in the ROM component"]
50+
-
51+
re_variables: [esp_efuse_get_chip_ver]
52+
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]
53+
-
54+
re_variables: [(esp_spiram_get_chip_size|esp_spiram_get_size)]
55+
hint_variables: [esp_spiram_get_chip_size and esp_spiram_get_size, esp_psram_get_size()]
1856

1957
-
2058
re: "error: implicit declaration of function 'esp_secure_boot_verify_sbv2_signature_block|esp_secure_boot_verify_rsa_signature_block'"
21-
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."
22-
23-
-
24-
re: "error: implicit declaration of function 'esp_cpu_ccount_t'"
25-
hint: "Use esp_cpu_cycle_count_t defined in esp_cpu.h instead of esp_cpu_ccount_t."
26-
27-
-
28-
re: "error: implicit declaration of function 'esp_cpu_(g|s)et_ccount'"
29-
hint: "Use esp_cpu_{}et_cycle_count() defined in esp_cpu.h instead."
30-
match_to_output: True
31-
32-
-
33-
re: "error: implicit declaration of function 'esp_efuse_get_chip_ver'"
34-
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."
35-
36-
-
37-
re: "error: implicit declaration of function '(esp_random|esp_fill_random)'"
38-
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\""
39-
40-
-
41-
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)'"
42-
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\""
43-
44-
-
45-
re: "error: (implicit declaration of function 'esp_chip_info'|unknown type name 'esp_chip_info_t')"
46-
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\""
59+
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."
4760

4861
-
49-
re: "error: implicit declaration of function 'esp_int_wdt_\\w+'"
50-
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)"
51-
52-
-
53-
re: "error: implicit declaration of function '(esp_spiram_get_chip_size|esp_spiram_get_size)'"
54-
hint: "{}() has been deleted, please use esp_psram_get_size() instead."
55-
match_to_output: True
62+
re: "error: implicit declaration of function '{}'"
63+
hint: '{0}.h header file is not included by esp_system.h anymore. It shall then be manually included with #include "{0}.h"'
64+
variables:
65+
-
66+
re_variables: [(esp_random|esp_fill_random)]
67+
hint_variables: [esp_random]
68+
-
69+
re_variables: [(esp_base_mac_addr_(s|g)et|esp_efuse_mac_get_(custom|default)|esp_read_mac|esp_derive_local_mac)]
70+
hint_variables: [esp_mac]
71+
-
72+
re_variables: [esp_chip_info]
73+
hint_variables: [esp_chip_info]
5674

5775
-
5876
re: "fatal error: (spiram.h|esp_spiram.h): No such file or directory"
5977
hint: "{} was removed. Include esp_psram.h instead. Make sure to also add esp_psram as a dependency in your CMakeLists.txt file."
6078
match_to_output: True
6179

6280
-
63-
re: "fatal error: (soc/cpu.h|compare_set.h): No such file or directory"
64-
hint: "{} was removed. Include and use the API function provided by esp_cpu.h instead."
65-
match_to_output: True
66-
67-
-
68-
re: "fatal error: (esp_intr.h): No such file or directory"
69-
hint: "{} was removed. Include esp_intr_alloc.h instead."
70-
match_to_output: True
81+
re: "error: implicit declaration of function '{}'"
82+
hint: "Use {} defined in esp_cpu.h instead of {}."
83+
variables:
84+
-
85+
re_variables: [esp_cpu_ccount_t]
86+
hint_variables: [esp_cpu_cycle_count_t, esp_cpu_ccount_t]
87+
-
88+
re_variables: [esp_cpu_get_ccount]
89+
hint_variables: [esp_cpu_get_cycle_count(), esp_cpu_get_ccount]
90+
-
91+
re_variables: [esp_cpu_set_ccount]
92+
hint_variables: [esp_cpu_set_cycle_count(), esp_cpu_set_ccount]
93+
94+
-
95+
re: "fatal error: {}: No such file or directory"
96+
hint: "{} was removed. Include {} instead."
97+
variables:
98+
-
99+
re_variables: [esp_intr.h]
100+
hint_variables: [esp_intr.h, esp_intr_alloc.h]
101+
-
102+
re_variables: [soc/cpu.h]
103+
hint_variables: [soc/cpu.h, and use the API function provided by esp_cpu.h]
104+
-
105+
re_variables: [compare_set.h]
106+
hint_variables: [compare_set.h, and use the API function provided by esp_cpu.h]
107+
-
108+
re_variables: [esp_panic.h]
109+
hint_variables: [esp_panic.h, use functionalities provided in esp_debug_helpers.h]
71110

72111
-
73-
re: "fatal error: (esp_panic.h): No such file or directory"
74-
hint: "{} was made private. Use functionalities provided in esp_debug_helpers.h instead."
75-
match_to_output: True
112+
re: "error: implicit declaration of function 'esp_int_wdt_\\w+'"
113+
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)'
76114

77115
-
78116
re: "fatal error: soc/(spinlock.h|clk_ctrl_os.h|rtc_wdt.h): No such file or directory"
@@ -84,9 +122,6 @@
84122
hint: "{} was renamed and made private. Consider using the logging APIs provided under esp_log.h instead."
85123
match_to_output: True
86124

87-
-
88-
re: "fatal error: eh_frame_parser.h: No such file or directory"
89-
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)"
90125
-
91126
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)'"
92127
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 @@
117152
match_to_output: True
118153

119154
-
120-
re: "fatal error: esp32\\w*\\/clk.h: No such file or directory"
121-
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\"'."
122-
-
123-
re: "fatal error: esp32\\w*\\/cache_err_int.h: No such file or directory"
124-
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\"'"
125-
126-
-
127-
re: "fatal error: brownout.h: No such file or directory"
128-
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\"'."
129-
130-
-
131-
re: "fatal error: trax.h: No such file or directory"
132-
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\"'."
155+
re: "fatal error: {}.h: No such file or directory"
156+
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".'
157+
variables:
158+
-
159+
re_variables: [esp32\\w*\\/clk]
160+
hint_variables: [ESP Clock API, esp_clk, esp_clk]
161+
-
162+
re_variables: [esp32\\w*\\/cache_err_int]
163+
hint_variables: [Cache Error Interrupt API, esp_cache_err, cache_err_int]
164+
-
165+
re_variables: [brownout]
166+
hint_variables: [Brownout API, esp_brownout, brownout]
167+
-
168+
re_variables: [trax]
169+
hint_variables: [Trax API, trax_, trax]
170+
-
171+
re_variables: [eh_frame_parser]
172+
hint_variables: [Backtrace Parser API, eh_frame_parser, eh_frame_parser]
133173

134174
-
135175
re: "fatal error: esp_adc_cal.h: No such file or directory"

tools/idf_py_actions/tools.py

+47-10
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
from asyncio.subprocess import Process
99
from io import open
1010
from types import FunctionType
11-
from typing import Any, Dict, List, Optional, TextIO, Tuple, Union
11+
from typing import Any, Dict, List, Match, Optional, TextIO, Tuple, Union
1212

1313
import click
1414
import yaml
15-
from idf_monitor_base.output_helpers import yellow_print
1615

1716
from .constants import GENERATORS
1817
from .errors import FatalError
@@ -79,6 +78,23 @@ def idf_version() -> Optional[str]:
7978
return version
8079

8180

81+
def color_print(message: str, color: str, newline: Optional[str]='\n') -> None:
82+
""" Print a message to stderr with colored highlighting """
83+
ansi_normal = '\033[0m'
84+
sys.stderr.write('%s%s%s%s' % (color, message, ansi_normal, newline))
85+
sys.stderr.flush()
86+
87+
88+
def yellow_print(message: str, newline: Optional[str]='\n') -> None:
89+
ansi_yellow = '\033[0;33m'
90+
color_print(message, ansi_yellow, newline)
91+
92+
93+
def red_print(message: str, newline: Optional[str]='\n') -> None:
94+
ansi_red = '\033[1;31m'
95+
color_print(message, ansi_red, newline)
96+
97+
8298
def print_hints(*filenames: str) -> None:
8399
"""Getting output files and printing hints on how to resolve errors based on the output."""
84100
with open(os.path.join(os.path.dirname(__file__), 'hints.yml'), 'r') as file:
@@ -87,18 +103,39 @@ def print_hints(*filenames: str) -> None:
87103
with open(file_name, 'r') as file:
88104
output = ' '.join(line.strip() for line in file if line.strip())
89105
for hint in hints:
106+
variables_list = hint.get('variables')
107+
hint_list, hint_vars, re_vars = [], [], []
108+
match: Optional[Match[str]] = None
90109
try:
91-
match = re.compile(hint['re']).findall(output)
92-
except KeyError:
93-
raise KeyError("Argument 're' missing in {}. Check hints.yml file.".format(hint))
110+
if variables_list:
111+
for variables in variables_list:
112+
hint_vars = variables['re_variables']
113+
re_vars = variables['hint_variables']
114+
regex = hint['re'].format(*re_vars)
115+
if re.compile(regex).search(output):
116+
try:
117+
hint_list.append(hint['hint'].format(*hint_vars))
118+
except KeyError as e:
119+
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
120+
sys.exit(1)
121+
else:
122+
match = re.compile(hint['re']).search(output)
123+
except KeyError as e:
124+
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
125+
sys.exit(1)
94126
except re.error as e:
95-
raise re.error('{} from hints.yml have {} problem. Check hints.yml file.'.format(hint['re'], e))
96-
if match:
97-
extra_info = ', '.join(match) if hint.get('match_to_output', '') else ''
127+
red_print('{} from hints.yml have {} problem. Check hints.yml file.'.format(hint['re'], e))
128+
sys.exit(1)
129+
if hint_list:
130+
for message in hint_list:
131+
yellow_print('HINT:', message)
132+
elif match:
133+
extra_info = ', '.join(match.groups()) if hint.get('match_to_output', '') else ''
98134
try:
99135
yellow_print(' '.join(['HINT:', hint['hint'].format(extra_info)]))
100-
except KeyError:
101-
raise KeyError("Argument 'hint' missing in {}. Check hints.yml file.".format(hint))
136+
except KeyError as e:
137+
red_print('Argument {} missing in {}. Check hints.yml file.'.format(e, hint))
138+
sys.exit(1)
102139

103140

104141
def fit_text_in_terminal(out: str) -> str:

0 commit comments

Comments
 (0)