Skip to content

Read attribute and convention arguments as their constant values - #110

Merged
ipjohnson merged 1 commit into
mainfrom
fix/constant-arguments
Sep 24, 2026
Merged

ipjohnson merged 1 commit into
mainfrom
fix/constant-arguments

Conversation

@ipjohnson

Copy link
Copy Markdown
Owner

Closes #74. Closes #75.

The generator now reads attribute and convention arguments with GetConstantValue, not from their source text. A constant declared elsewhere, a digit separator and a fully qualified enum member now give the same result as the literal. A convention call with an argument that is not a constant is refused with DM0009.

#74: arguments read as source text

The new ConstantArgumentReader reads each value from the semantic model. The generator does not reference the runtime assembly, so an enum argument arrives as its underlying number. The reader maps it to the generator's own enum:

  • RegistrationType has the same member order in both.
  • ServiceLifetime numbers its members in the reverse order of ServiceLifestyle.
  • InterceptedMemberKinds has the flag values of InterceptedMembers.

It now reads these arguments:

  • Order and Using on the service attributes and [CrossWireService]
  • Using on [DependencyModule], and the convention call Using(...)
  • Order on [Decorator]
  • Order and Members on [Intercept]

The same text parsing was also in places the issue does not list. These now use the reader too:

  • Lifetime on [CrossWireService] and on [Intercept]. A constant fell back to Singleton, or matched only when its name happened to be Scoped or Transient.
  • The flags of [DependencyModule]: OnlyRealm, GenerateAttribute, RegisterJsonSerializers and GenerateFactories were compared with the text "true", and GenerateUseMethod took the text with its quotes removed.

GetLifestyle(string) in ServiceModelUtility has no callers now, so it is removed. BaseSourceGenerator.GetRegistrationType(string) stays, because the DependencyModules_RegistrationType build property is text.

An attribute argument is always a constant, or the compiler reports an error. So the attribute path adds no diagnostic of its own. In a convention, Using(...) with a value that is not a constant now gets DM0009. Before, GetRegistrationType never returned null, so that DM0009 could not be reported.

#75: convention arguments that are not constant

ReadPatterns now stops at the first argument that is not a constant string. WithName, WithoutName and the environment calls then refuse the whole call with DM0009, and the message names the argument, for example 'Keys.Feature' in 'IfEnvironmentValue' is not a compile-time constant. This is how the namespace calls already worked. Before, the argument was dropped, so IfEnvironmentValue(Keys.Feature, "on") tested the key on.

Public API

The DependencyModules.SourceGenerator snapshot adds ConstantArgumentReader.

Docs

The warnings for #74 and #75 are on docs-ste-rewrite, in services.md, decorators.md, interception.md and conventions.md. They will be removed in one docs pass after the fixes.

Verified

🤖 Generated with Claude Code

Order, Using, Members and Lifetime were parsed from the source text of the argument. A constant
declared elsewhere, a digit separator or a fully qualified enum member then fell back to the
default with no diagnostic. The [DependencyModule] flags were compared with the text "true".
ConstantArgumentReader now reads each value with GetConstantValue, and the enum values arrive as
their underlying numbers.

A convention call with an argument that is not a constant is now refused with DM0009, as the
namespace calls already were. Before, WithName, WithoutName and the environment calls dropped
that argument, so IfEnvironmentValue(key, "on") tested the key "on".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ipjohnson
ipjohnson merged commit 60c0c24 into main Sep 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant