mirror of
https://github.com/esphome/esphome.git
synced 2026-06-02 03:02:19 +08:00
[core] Use begin/end marker pairs around each component's IIFE
Rename the bracket markers from "// === X ===" (same on both sides) to "// === begin X ===" and "// === end X ===" so the generated main.cpp reads unambiguously when scanning by component. Comment-only components still get a single "begin X" marker since they have no IIFE to close.
This commit is contained in:
+12
-10
@@ -1052,15 +1052,15 @@ class EsphomeCore:
|
|||||||
|
|
||||||
# Split main_statements at ComponentMarker sentinels into a prefix
|
# Split main_statements at ComponentMarker sentinels into a prefix
|
||||||
# (statements emitted before any component) plus per-component groups.
|
# (statements emitted before any component) plus per-component groups.
|
||||||
# Each group's first entry is its marker comment, kept separate so
|
# Each group carries its component name so cpp_main_section can emit
|
||||||
# it can bracket the IIFE rather than be buried inside it.
|
# begin/end marker comments bracketing the IIFE.
|
||||||
prefix: list[str] = []
|
prefix: list[str] = []
|
||||||
components: list[tuple[str, list[str]]] = []
|
components: list[tuple[str, list[str]]] = []
|
||||||
current = prefix
|
current = prefix
|
||||||
for exp in self.main_statements:
|
for exp in self.main_statements:
|
||||||
if isinstance(exp, ComponentMarker):
|
if isinstance(exp, ComponentMarker):
|
||||||
body: list[str] = []
|
body: list[str] = []
|
||||||
components.append((str(exp).rstrip(), body))
|
components.append((exp.name, body))
|
||||||
current = body
|
current = body
|
||||||
continue
|
continue
|
||||||
current.append(str(statement(exp)).rstrip())
|
current.append(str(statement(exp)).rstrip())
|
||||||
@@ -1072,16 +1072,18 @@ class EsphomeCore:
|
|||||||
# Each component's block is wrapped in IIFE lambdas so its stack
|
# Each component's block is wrapped in IIFE lambdas so its stack
|
||||||
# frame is released on return, bounding peak stack during setup().
|
# frame is released on return, bounding peak stack during setup().
|
||||||
# Large blocks are sub-split to cap single heavy components (e.g.
|
# Large blocks are sub-split to cap single heavy components (e.g.
|
||||||
# sensor platforms with many filter registrations). The marker
|
# sensor platforms with many filter registrations). "begin X" and
|
||||||
# comment brackets the IIFE on both sides so the generated
|
# "end X" marker comments bracket the IIFE so the generated
|
||||||
# main.cpp is easy to scan by component.
|
# main.cpp is easy to scan by component; a comment-only component
|
||||||
|
# gets a single "begin X" marker (no IIFE, no end marker).
|
||||||
pieces = list(prefix)
|
pieces = list(prefix)
|
||||||
for marker, body in components:
|
for name, body in components:
|
||||||
wrapped = _wrap_in_iifes(body, max_statements=50)
|
wrapped = _wrap_in_iifes(body, max_statements=50)
|
||||||
pieces.append(marker)
|
has_iife = any("[]()" in line for line in wrapped)
|
||||||
|
pieces.append(f"// === begin {name} ===")
|
||||||
pieces.extend(wrapped)
|
pieces.extend(wrapped)
|
||||||
if any("[]()" in line for line in wrapped):
|
if has_iife:
|
||||||
pieces.append(marker)
|
pieces.append(f"// === end {name} ===")
|
||||||
return "\n".join(pieces) + "\n\n"
|
return "\n".join(pieces) + "\n\n"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -436,9 +436,8 @@ class LineComment(Statement):
|
|||||||
|
|
||||||
class ComponentMarker(Statement):
|
class ComponentMarker(Statement):
|
||||||
"""Sentinel marker recorded in main_statements when a component's
|
"""Sentinel marker recorded in main_statements when a component's
|
||||||
to_code begins emitting code. Used by cpp_main_section to split
|
to_code begins emitting code. ``cpp_main_section`` consumes these
|
||||||
setup() output into per-component chunks, so each component's
|
to bracket each component's IIFE with begin/end comment markers."""
|
||||||
stack frame is released on return."""
|
|
||||||
|
|
||||||
__slots__ = ("name",)
|
__slots__ = ("name",)
|
||||||
|
|
||||||
@@ -446,7 +445,7 @@ class ComponentMarker(Statement):
|
|||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"// === {self.name} ==="
|
return f"// === begin {self.name} ==="
|
||||||
|
|
||||||
|
|
||||||
class ProgmemAssignmentExpression(AssignmentExpression):
|
class ProgmemAssignmentExpression(AssignmentExpression):
|
||||||
|
|||||||
@@ -937,7 +937,7 @@ def test_wrap_in_iifes_unbalanced_braces_fall_through() -> None:
|
|||||||
def test_wrap_in_iifes_skips_comment_only_chunks() -> None:
|
def test_wrap_in_iifes_skips_comment_only_chunks() -> None:
|
||||||
# Components that emit only a ComponentMarker + config dump (no C++
|
# Components that emit only a ComponentMarker + config dump (no C++
|
||||||
# statements) should not be wrapped in an empty IIFE.
|
# statements) should not be wrapped in an empty IIFE.
|
||||||
lines = ["// === sha256 ===", "// sha256:", "// {}"]
|
lines = ["// === begin sha256 ===", "// sha256:", "// {}"]
|
||||||
assert core._wrap_in_iifes(lines, max_statements=50) == lines
|
assert core._wrap_in_iifes(lines, max_statements=50) == lines
|
||||||
|
|
||||||
|
|
||||||
@@ -961,14 +961,16 @@ def test_cpp_main_section_component_marker_wraps_in_iife() -> None:
|
|||||||
out = target.cpp_main_section
|
out = target.cpp_main_section
|
||||||
assert out.count("[]() {") == 2
|
assert out.count("[]() {") == 2
|
||||||
assert out.count("}();") == 2
|
assert out.count("}();") == 2
|
||||||
# Each component's marker brackets its IIFE (once before, once after).
|
# Each component's IIFE is bracketed by a begin/end marker pair.
|
||||||
assert out.count("// === logger ===") == 2
|
assert "// === begin logger ===" in out
|
||||||
assert out.count("// === wifi ===") == 2
|
assert "// === end logger ===" in out
|
||||||
|
assert "// === begin wifi ===" in out
|
||||||
|
assert "// === end wifi ===" in out
|
||||||
|
|
||||||
|
|
||||||
def test_cpp_main_section_comment_only_component_emits_single_marker() -> None:
|
def test_cpp_main_section_comment_only_component_emits_single_marker() -> None:
|
||||||
# A component that emits no C++ statements (only a ComponentMarker)
|
# A component that emits no C++ statements (only a ComponentMarker)
|
||||||
# should not grow a useless trailing duplicate marker.
|
# gets only a begin marker — no IIFE, so no end marker.
|
||||||
target = core.EsphomeCore()
|
target = core.EsphomeCore()
|
||||||
target.main_statements = [
|
target.main_statements = [
|
||||||
ComponentMarker("sha256"),
|
ComponentMarker("sha256"),
|
||||||
@@ -976,8 +978,10 @@ def test_cpp_main_section_comment_only_component_emits_single_marker() -> None:
|
|||||||
RawStatement("new_wifi();"),
|
RawStatement("new_wifi();"),
|
||||||
]
|
]
|
||||||
out = target.cpp_main_section
|
out = target.cpp_main_section
|
||||||
assert out.count("// === sha256 ===") == 1
|
assert "// === begin sha256 ===" in out
|
||||||
assert out.count("// === wifi ===") == 2 # wifi has an IIFE
|
assert "// === end sha256 ===" not in out
|
||||||
|
assert "// === begin wifi ===" in out
|
||||||
|
assert "// === end wifi ===" in out
|
||||||
|
|
||||||
|
|
||||||
def test_cpp_main_section_prefix_statements_stay_outside_iife() -> None:
|
def test_cpp_main_section_prefix_statements_stay_outside_iife() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user