Skip to content

Lint Compiler Warnings in Lambdas on the Generated Code - #262

Merged
ptr727 merged 9 commits into
developfrom
feature/lambda-lint
Oct 25, 2026
Merged

ptr727 merged 9 commits into
developfrom
feature/lambda-lint

Conversation

@ptr727

@ptr727 ptr727 commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

Adds a compile-time C++ lint over each ESPHome build, so a compiler warning in this repository's own code surfaces while developing and at pull request time rather than in a log nobody reads.

What It Does

  • tools/compile-lint (a new uv workspace member) reruns the compile of the generated main.cpp syntax-only, with the build's own flags plus -Wdouble-promotion, from the build's compile_commands.json. It works on the ESP-IDF and the ESP8266 builds alike, and never builds or changes firmware.
  • It blanks ESPHome's #line directives in a copy, so every diagnostic keeps its main.cpp line. It then attributes a line to YAML only where it matches the lambda line after ESPHome's own rewrites (substitutions, id(), globals, its comment remover). Generated widget and action code, which ESPHome attributes to the same YAML lines, is set aside.
  • A lambda ESPHome inlined as a bare expression is found by searching the build's YAML for it, matching whole tokens. A C++ file in this tree, or the build's copy of one, is matched by content.
  • CI: a new "Lint compiled code step" in every compile leg annotates each finding on its line, writes the step summary, and fails the leg.
  • Development: the VS Code task "ESPHome: Compile and Lint" compiles the open file, then lints the build, with findings in the Problems pane.
  • Fixes every double-promotion site it finds in the templates and example devices (f suffixes), and casts the EasyStart component's float log arguments.
  • Docs: OPERATIONS.md "Compile Lint", CODESTYLE.md, the GOVERNANCE.md layout list, and the 2.4 release notes.

Verification

  • Unit tests over constructed builds and a fake compiler, ruff and pyright strict clean.
  • Compiled and linted from this branch, the CoreS3, Heltec and NORVI example devices report no finding and set nothing aside.
  • Run for real against fresh CoreS3 (ESP-IDF) and Sonoff S31 (ESP8266) builds. A probe lambda with a deliberate warning was reported on its exact YAML line, past a blanked comment, a substitution, and a global rewrite. The corrected config exits 0.
  • The prose gate and the Docker linters (editorconfig-checker, actionlint, markdownlint, cspell, shellcheck, shfmt) pass locally.

Local Review

Every introduced finding the local review raised is fixed in this pull request, the last being an args: entry beside a substituted format:.

Found by CI on the First Run

The first CI run is the lint's real end-to-end test, and it found what the local caches had hidden:

  • Float arguments to it.printf in the Heltec and NORVI example display lambdas, now cast with static_cast<double>(), the maintainer's choice over exempting printf-style calls. The text: format: args: entries are linted the same way, and the CoreS3 and Dial float arguments are cast.
  • The CeilSense vendor package sets its own build_path, so CI now reads the build path from the compile log rather than globbing /cache/build.

Pre-existing Findings, Not Filed

  • pre-existing, style: CODESTYLE.md "This Repository's Python", the sentence opening "The root pyproject.toml" runs past the 25-word sentence cap.

Closes #256 at the promotion to main.

🤖 Generated with Claude Code

Rechecks each compiled example device's generated main.cpp syntax-only with
the build's own flags plus -Wdouble-promotion, and fails the compile leg on
a warning that lands in this repository's code: a YAML lambda line, a lambda
ESPHome inlined as an expression, or a component file copied into the build.
Generated and third-party code is set aside. A VS Code task runs the same
lint after a local compile and puts findings in the Problems pane.

Fixes the two double-promotion lambdas it finds on the builds checked so far.

Closes #256
Inline search matches whole tokens, skips an expression that is only an id(),
searches only the YAML the build includes, and reports a block lambda's code
line. Code after a remote package's #line is set aside. Comments are stripped
with ESPHome's own remover, and a global's member access matches its real
rewrite. The YAML is read before a --compile run starts, and an unreadable
file fails the run.

Adds f suffixes to the remaining double literals in the templates and the Dial
example, and casts the EasyStart component's float log arguments.
@ptr727 ptr727 added the comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses label Oct 25, 2026
Copilot AI lite review requested due to automatic review settings October 25, 2026 15:54
@ptr727 ptr727 added the comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses label Oct 25, 2026
@ptr727

ptr727 commented Oct 25, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 0a273e60555021d2209d54fee767ef5ba621e614, the content this pull request carries at that commit against develop, and it recorded 5 findings.

@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 2 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 3c606d49-b277-475f-b88d-7c5021eaccbd
Commits

Reviewing files that changed from the base of the PR and between 0db406e and ac7e7eb.

Files ignored due to path filters: 1
  • uv.lock is excluded by !**/*.lock
Files selected for processing: 24
  • .github/workflows/test-pull-request.yml
  • .vscode/tasks.json
  • CODESTYLE.md
  • GOVERNANCE.md
  • HISTORY.md
  • OPERATIONS.md
  • README.md
  • easystart/components/easystart/easystart.h
  • pyproject.toml
  • templates/apollo-plt-1b.yaml
  • templates/basic.yaml
  • templates/efun-sh331.yaml
  • templates/konnected-blaq.yaml
  • templates/smarthome-ceilsense.yaml
  • test/heltec-wifi-lora32-v4-r8.yaml
  • test/m5stack-cores3.yaml
  • test/m5stack-dial.yaml
  • test/norvi-enet-ae06-r.yaml
  • tests/compile_lint/test_lint.py
  • tools/compile-lint/pyproject.toml
  • tools/compile-lint/src/compile_lint/__init__.py
  • tools/compile-lint/src/compile_lint/__main__.py
  • tools/compile-lint/src/compile_lint/lint.py
  • tools/compile-lint/src/compile_lint/py.typed
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.23810% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.17%. Comparing base (0db406e) to head (ac7e7eb).

Files with missing lines Patch % Lines
tools/compile-lint/src/compile_lint/lint.py 95.63% 21 Missing ⚠️
tools/compile-lint/src/compile_lint/__main__.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           develop     #262       +/-   ##
============================================
+ Coverage    43.07%   84.17%   +41.09%     
============================================
  Files            1        3        +2     
  Lines          130      613      +483     
============================================
+ Hits            56      516      +460     
- Misses          74       97       +23     
Flag Coverage Δ
python-3.13 84.17% <95.23%> (+41.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The review includes one critical compiler-exit handling issue and multiple unresolved attribution, ownership, and documentation findings.

8 open issues
What changed in this PR

This pull request adds a compile-time C++ lint for ESPHome-generated code, integrates it into CI and VS Code, fixes detected floating-point promotion warnings, and documents the workflow.

Changes:

  • Added the compile-lint workspace package, compiler diagnostics, YAML/source attribution, tests, and lockfile updates.
  • Integrated linting into pull-request compile jobs and the VS Code compile-and-lint task.
  • Updated templates, examples, EasyStart logging, repository documentation, and release notes.
File Summary Review findings
uv.lock Locks the new compile-lint package and dependencies. —
tools/​compile-lint/​src/​compile_lint/​py.typed Marks the package as typed. —
tools/​compile-lint/​src/​compile_lint/​lint.py Implements compilation, diagnostic parsing, attribution, annotations, and summaries. P1 / critical (2 votes): Any nonzero compiler exit must fail the lint, even when diagnostics are unclassified.
P2 / moderate (4 votes): Continue inline matching after remote directives.
P2 / moderate (3 votes): Include YAML files without local directives in the inline search set.
P2 / moderate (4 votes): Preserve raw scalar line mappings for folded multi-line lambdas.
P1 / moderate (1 vote): Restrict the YAML index to lambda values.
P1 / moderate (2 votes): Preserve block-comment state across source lines.
P1 / moderate (1 vote): Exclude generated build roots from direct source ownership.
tools/​compile-lint/​src/​compile_lint/​__main__.py Provides module execution support. —
tools/​compile-lint/​src/​compile_lint/​__init__.py Defines the package metadata. —
tools/​compile-lint/​pyproject.toml Defines the compile-lint project and console script. —
tests/​compile_lint/​test_lint.py Tests compiler invocation, attribution, reporting, and CLI behavior. —
test/​m5stack-dial.yaml Fixes a floating-point promotion warning. —
test/​m5stack-cores3.yaml Fixes a floating-point promotion warning. —
templates/​smarthome-ceilsense.yaml Fixes uptime conversion promotion. —
templates/​konnected-blaq.yaml Fixes uptime conversion promotion. —
templates/​efun-sh331.yaml Fixes calibration-lambda promotion. —
templates/​basic.yaml Fixes a floating-point promotion warning. —
templates/​apollo-plt-1b.yaml Fixes a floating-point promotion warning. —
README.md Documents the compile lint and related release changes. P2 / nit (4 votes): Describe findings as landing on YAML or source lines, since owned component diagnostics use source files.
pyproject.toml Adds the workspace member and shared tooling configuration. —
OPERATIONS.md Documents compile-lint usage and behavior. P2 / nit (4 votes): Document YAML or source-line locations for component findings.
HISTORY.md Records the compile-lint release changes. P2 / nit (4 votes): Describe findings as landing on YAML or source lines, since owned component diagnostics use source files.
GOVERNANCE.md Adds the tools directory to the repository layout. —
easystart/​components/​easystart/​easystart.h Casts floating-point log arguments to double. —
CODESTYLE.md Updates Python workspace and generated-code analysis guidance. —
.vscode/​tasks.json Adds the compile-and-lint task and problem matcher. —
.github/​workflows/​test-pull-request.yml Runs compile-lint after each applicable compile leg and reports failures. —

Review effort: Lite

Comment thread HISTORY.md Resolved
Comment thread OPERATIONS.md Resolved
Comment thread README.md Resolved
…he Log

Comments are removed across a whole lambda, with each emitted line mapped back
to its YAML line, and a plain, quoted or folded lambda is one logical line.
Code after a remote package's #line is set aside only where it copies that
package's lambda. The inline search covers the build's config, found from
ESPHome's storage file, and every repository YAML it includes. A recheck that
fails outside this repository's code fails the run.

CI reads the build path from the compile log, since a package can set its own
build_path. Casts the float printf arguments in the Heltec and NORVI examples.
@ptr727

ptr727 commented Oct 25, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 9d003fb62f93f71fa7ba213db2d169fea2560076, the content this pull request carries at that commit against develop, and it recorded 2 findings.

@ptr727

ptr727 commented Oct 25, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head ac7e7eba0c0d7bfb7de06ebd29f9c7cbfc8ba514, the content this pull request carries at that commit against develop, and it recorded 1 finding.

@ptr727
ptr727 merged commit 337ef0d into develop Oct 25, 2026
37 checks passed
@ptr727
ptr727 deleted the feature/lambda-lint branch October 25, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comments Permits the comment lines the pull request adds or edits, which the prose gate otherwise refuses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants