Skip to content

Skip service domains without services in the code generator - #1447

Merged
helto4real merged 1 commit into
net-daemon:mainfrom
DevJasperNL:fix/codegen-empty-service-domain
Sep 5, 2026
Merged

Skip service domains without services in the code generator#1447
helto4real merged 1 commit into
net-daemon:mainfrom
DevJasperNL:fix/codegen-empty-service-domain

Conversation

@DevJasperNL

Copy link
Copy Markdown
Contributor

Proposed change

nd-codegen could emit a HomeAssistantGenerated.cs that does not compile.

Generator.GenerateTypes handed every service domain to HelpersGenerator and ServicesGenerator. ServicesGenerator only emitted a {Domain}Services class for domains that still had at least one service, but it built the IServices interface and the Services root class from all domains, and HelpersGenerator registered AddTransient<{Domain}Services>() for all domains as well.

ServiceMetaDataParser swallows per-service deserialization errors by design. When every service of a domain fails to parse, that domain reaches the generators with an empty service list. The generated file then contained an IServices property, a Services property and a DI registration for a {Domain}Services type that was never declared, so the user's project no longer built.

This PR:

  • Filters out domains without services once, in Generator.GenerateTypes, before the helpers, services and extension-method generators see them. All generated types now agree on the same set of domains.
  • Removes the local Where(sd => sd.Services.Any()) in ServicesGenerator, which was the source of the inconsistency. Given the same input, the root interface, the root class and the domain classes are now always consistent.
  • Adds TestDomainWithoutAnyServices_ServicesTypeNotReferenced to ServicesGeneratorTest. It generates code for a domain with zero services next to a normal light domain, asserts the {Domain}Services name does not appear anywhere in the output, and compiles the generated code together with app code. It fails without the fix with three dangling references to the undeclared type.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to an existing integration)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • The code compiles without warnings (code quality check)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration are added/changed:

@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83%. Comparing base (5a5c659) to head (67663cc).

Additional details and impacted files
@@         Coverage Diff          @@
##           main   #1447   +/-   ##
====================================
  Coverage    83%     83%           
====================================
  Files       201     201           
  Lines      4170    4170           
  Branches    486     486           
====================================
+ Hits       3466    3470    +4     
+ Misses      498     496    -2     
+ Partials    206     204    -2     
Flag Coverage Δ
unittests 83% <100%> (+<1%) ⬆️

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.

Generator.GenerateTypes handed every service domain to the helpers and
services generators, but ServicesGenerator only emitted a {Domain}Services
class for domains that still had at least one service. When
ServiceMetaDataParser drops all services of a domain because they failed
to deserialize, the generated IServices, Services and
AddHomeAssistantGenerated still referenced the missing class and the
generated file no longer compiled.

Filter out domains without services once, before any generator sees
them, and drop the local filter in ServicesGenerator so the root types
and the domain classes always agree.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYWUzTg6pKoqNKAxdc1hT
@helto4real
helto4real force-pushed the fix/codegen-empty-service-domain branch from 1c1fbb5 to 67663cc Compare September 5, 2026 19:49

@helto4real helto4real left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The shared filtering keeps the service interfaces, root types, domain classes and DI registrations consistent. All 153 HassModel tests passed locally, and the new regression test failed as expected when the production fix was removed. The reviewed HassModel code and tests are unchanged after rebasing onto main. Approved, with merge pending required CI on the rebased commit.

@helto4real
helto4real enabled auto-merge (squash) September 5, 2026 19:50
@helto4real
helto4real merged commit 22d654a into net-daemon:main Sep 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants