microsoft / microsoft/typespec

[http-client-csharp] Support declarative generated property transformations without full replacement

Open
#11,804 3 comments 1 reaction 0 assignees View on GitHub
emitter:client:csharp feature
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

## Feature request

Allow C# customization code to modify individual aspects of a generated property without replacing and reimplementing the entire property.

Today, `[CodeGenMember("OriginalName")]` is applied to a custom property declaration and replaces the generated property. Even when the desired change is only a rename, accessibility adjustment, or setter addition, the customization must take ownership of the complete declaration and implementation.

For example, renaming a property currently requires repeating its type, accessors, initialization behavior, documentation, and sometimes its backing field:

```csharp
[CodeGenMember("OriginalName")]
public BicepValue NewName
{
get { Initialize(); return _value; }
set { Initialize(); _value.Assign(value); }
}
```

This is cumbersome and fragile. It can also discard generator-owned metadata or behavior and prevents future generator improvements from flowing into the customized member. Azure/azure-sdk-for-net#62602 is a concrete example where replacement properties and generated wire metadata interact poorly.

## Proposed direction

Support declarative transformations on a generated member while retaining the original generated `PropertyProvider`, body, metadata, attributes, documentation, and serialization information.

One possible syntax would allow repeatable attributes on the containing partial type:

```csharp
[CodeGenMember("OriginalName", "NewName")]
[CodeGenMember("InternalProperty", Accessibility = CodeGenAccessibility.Public)]
[CodeGenMember("GetterOnlyProperty", SetterAccessibility = CodeGenAccessibility.Public)]
public partial class ExampleModel
{
}
```

Alternatively, a separate attribute could avoid overloading the existing replacement semantics:

```csharp
[CodeGenMemberCustomization(
"OriginalName",
Name = "NewName",
Accessibility = CodeGenAccessibility.Public,
SetterAccessibility = CodeGenAccessibility.Public)]
public partial class ExampleModel
{
}
```

The exact API is open for discussion. The important distinction is that these declarations should transform the generated member rather than replace it.

## Initial scenarios

- Rename a generated property while preserving its serialized name and all wire metadata.
- Change property accessibility, such as `internal` to `public`.
- Add or change setter accessibility when the generator can produce a valid setter implementation.
- Add or change getter accessibility.
- Combine transformations without copying the full property into custom code.

If a requested transformation cannot be implemented safely—for example, adding a setter when there is no valid assignment path—the generator should report a diagnostic rather than require a silently incomplete implementation.

## Expected benefits

- Smaller, intention-revealing customization files.
- Generated metadata and serialization behavior remain attached to the property.
- Generator fixes and implementation improvements continue to flow through customizations.
- Less duplicated accessor and backing-field logic.
- Reduced risk of API compatibility customizations diverging from generated behavior.

Contributor guide

Open the contributing guide

Research direction

Start by tracing the existing CodeGenMember replacement path and the generated PropertyProvider model. Review how generated metadata, accessors, documentation, and serialization information are retained, then define tests for the listed rename and accessibility scenarios. Done means transformations preserve generated behavior and report a diagnostic when an unsafe setter change is requested.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.