mirror of
https://github.com/esphome/esphome.git
synced 2026-09-29 16:00:23 +00:00
[core] Lint against std::nothrow, use RAMAllocator instead (#19244)
This commit is contained in:
+39
-3
@@ -164,7 +164,21 @@ def lint_post_check(func):
|
||||
return func
|
||||
|
||||
|
||||
def lint_re_check(regex, **kwargs):
|
||||
def _nolint_in_match(content, haystack, match, mask):
|
||||
"""With masking, only a trailing comment counts: the raw span still holds string contents, and
|
||||
the masked text is blank exactly where comments and strings were, so NOLINT must sit after the
|
||||
last real code character of the span."""
|
||||
raw = content[match.start() : match.end()]
|
||||
if not mask:
|
||||
return "NOLINT" in raw
|
||||
masked = haystack[match.start() : match.end()].rstrip()
|
||||
return "NOLINT" in raw[len(masked) :]
|
||||
|
||||
|
||||
def lint_re_check(regex, mask=False, prefilter=None, **kwargs):
|
||||
"""mask=True blanks comments and string literals first so prose about the pattern is not reported;
|
||||
the masked text keeps its length, so match offsets still index the original content.
|
||||
prefilter is a literal every match must contain, checked before the costlier masking."""
|
||||
flags = kwargs.pop("flags", re.MULTILINE)
|
||||
prog = re.compile(regex, flags)
|
||||
decor = lint_content_check(**kwargs)
|
||||
@@ -173,8 +187,11 @@ def lint_re_check(regex, **kwargs):
|
||||
@functools.wraps(func)
|
||||
def new_func(fname, content):
|
||||
errs = []
|
||||
for match in prog.finditer(content):
|
||||
if "NOLINT" in match.group(0):
|
||||
if prefilter is not None and prefilter not in content:
|
||||
return errs
|
||||
haystack = _mask_cpp_comments_strings(content) if mask else content
|
||||
for match in prog.finditer(haystack):
|
||||
if _nolint_in_match(content, haystack, match, mask):
|
||||
continue
|
||||
lineno = content.count("\n", 0, match.start()) + 1
|
||||
substr = content[: match.start()]
|
||||
@@ -1199,6 +1216,25 @@ def lint_no_std_bind(fname, match):
|
||||
)
|
||||
|
||||
|
||||
@lint_re_check(
|
||||
r"[^\w]std\s*::\s*nothrow\b" + CPP_RE_EOL,
|
||||
mask=True,
|
||||
prefilter="nothrow",
|
||||
include=cpp_include,
|
||||
)
|
||||
def lint_no_std_nothrow(fname, match):
|
||||
return (
|
||||
f"{highlight('new (std::nothrow)')} aborts on ESP-IDF when the allocation fails, exceptions are disabled "
|
||||
f"there, so it never returns nullptr.\n"
|
||||
f"Please use {highlight('RAMAllocator')} from esphome/core/helpers.h, which does.\n"
|
||||
f" Before: {highlight('auto *buf = new (std::nothrow) uint8_t[n];')}\n"
|
||||
f" After: {highlight('auto buf = RAMAllocator<uint8_t>().make_unique_array_for_overwrite(n);')}\n"
|
||||
f"For one object use {highlight('RAMAllocator<T>().make_unique(args...)')}; both return empty on failure.\n"
|
||||
f"Default flags prefer PSRAM; pass RAMAllocator<T>::PREFER_INTERNAL to keep it where new put it.\n"
|
||||
f"(If strictly necessary, add `// NOLINT` to the end of the line)"
|
||||
)
|
||||
|
||||
|
||||
LOG_CALL_START_RE = re.compile(r"ESP_LOG\w+\s*\(")
|
||||
# Comments, raw/plain string literals and single char literals are consumed whole so ; ( ) ? :
|
||||
# inside them are never seen. A char literal is exactly one (escaped) char so a digit separator
|
||||
|
||||
Reference in New Issue
Block a user