Skip to content

Remove unused usings when internalizing types#10969

Draft
Copilot wants to merge 12 commits into
mainfrom
copilot/remove-unused-system-diagnostic-import
Draft

Remove unused usings when internalizing types#10969
Copilot wants to merge 12 commits into
mainfrom
copilot/remove-unused-system-diagnostic-import

Conversation

Copilot AI commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

When the post-processor internalizes an unreferenced public type or prunes a model factory method, a using directive can be left dangling on the generated type when nothing else in the file references that namespace. This adds a generic pass that removes any such now-unused using directive.

Changes

  • PostProcessor.InternalizeAsync: after internalizing types and pruning model factory methods, runs a cleanup pass over the affected documents to drop now-unused using directives.
  • RemoveUnusedUsingsAsync: a generic pass that removes any using directive flagged by the C# compiler's CS8019 ("unnecessary using directive") diagnostic, while preserving a using when the namespace is still referenced.
  • Model factory cleanup: RemoveMethodsFromModelFactoryAsync now reports the model factory document it modified, and that document is included in the unused-using cleanup pass. When a model in a different namespace is internalized and its model factory method removed, the now-unused using directive for that namespace is also dropped from the model factory.
  • Robustness against incomplete compilations: the post-processing compilation is reference-incomplete, so when a document has unresolved type/namespace/name references (CS0103/CS0234/CS0246/CS0305/CS0308) the CS8019 diagnostic is unreliable and can falsely flag a genuinely-used directive (for example using System.ClientModel; in a serialization file when that assembly is not referenced). RemoveUnusedUsings now skips removal for any document that has such unresolved-reference diagnostics, so needed usings are preserved and the generated code still builds.

> Note: An earlier revision of this PR re-introduced the reverted [Experimental]-attribute stripping logic (#10972 reverting #10958). Per review feedback, that logic has been removed — this PR no longer re-adds the experimental-attribute stripping and instead focuses solely on the generic removal of unused using statements.

Tests

RemovesUnusedUsingFromModelFactoryWhenInternalizing:

  • A model in a different namespace (Sample.Models) is unreferenced and internalized, its SampleModelFactory method is removed, and the now-unused using Sample.Models; is dropped from the model factory document while the referenced model and its factory method are preserved. The generated model factory output is validated against an expected TestData file.

KeepsUsedUsingWhenTypeReferencesAreUnresolved:

  • A serialization-style partial class with System.ClientModel conversion operators is internalized in a compilation that lacks the System.ClientModel reference (so BinaryContent/ClientResult cannot be resolved). The test confirms the genuinely-used using System.ClientModel; is preserved rather than removed, and validates the full document output against an expected TestData file.

The experimental-specific test (RemovesExperimentalAttributeWhenInternalizing) and its TestData assets were removed along with the reverted logic. Regenerated all test libraries (Sample-TypeSpec + Spector) with zero diff, confirming the genuine unused-using removals come from the retained pass and that the unresolved-reference guard introduces no regression; all generator tests pass.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Jun 11, 2026
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title [WIP] Remove unused System.Diagnostic.CodeAnalysis import when cleaning up Experiment attributes Remove unused System.Diagnostics.CodeAnalysis using when internalizing Experimental types Jun 11, 2026
Copilot AI requested a review from jorgerangel-msft June 11, 2026 18:21
@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@10969

commit: 3ef61c3

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/fd547137-3f63-4177-82be-da0c260abc81

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

@jorgerangel-msft jorgerangel-msft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot we need to ensure all test libraries are regenerated as well for each change we make

…alidated tests

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title Remove unused System.Diagnostics.CodeAnalysis using when internalizing Experimental types Remove unused usings when internalizing Experimental types Jun 11, 2026
Copilot AI requested a review from jorgerangel-msft June 11, 2026 19:41
… to avoid stripping needed usings

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot we need to ensure all test libraries are regenerated as well for each change we make

Regenerated all test libraries (Sample-TypeSpec + Spector). This surfaced a real bug: the unused-using pass ran before the simplification stage, so type references were still fully qualified and System/System.Collections.Generic were incorrectly removed (along with the file header) from internalized paging models. Fixed by reducing names via Simplifier.ReduceAsync before computing CS8019 and preserving the header trivia. Regeneration now produces zero diff and all 1529 generator tests pass. fc528d8

…eedback

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
…sedUsings

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@jorgerangel-msft

Copy link
Copy Markdown
Contributor

@copilot address merge conflicts

…-system-diagnostic-import

# Conflicts:
#	packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/PostProcessor.cs
#	packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/PostProcessing/PostProcessorTests.cs

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address merge conflicts

Merged origin/main and resolved the conflicts in 3ef61c3. The conflicts came from main's revert of #10958 (the [Experimental]-stripping feature this PR builds on, reverted in #10972). Since this PR is the corrected re-introduction of that feature, I kept this branch's version of PostProcessor.cs and PostProcessorTests.cs and restored the test assets the revert deleted, while bringing in main's unrelated changes (paging method suppression, etc.). The full generator solution builds with zero warnings and all PostProcessor tests pass.

private readonly HashSet<string> _typesToKeep;
private INamedTypeSymbol? _modelFactorySymbol;

private static readonly string[] _experimentalAttributeNames = ["Experimental", "ExperimentalAttribute"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot this logic was removed / reverted as part of #10972. We should not be adding this back in, and instead, we should generally remove any unused using statements.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the [Experimental]-stripping logic that #10972 reverted (_experimentalAttributeNames, RemoveExperimentalAttribute, IsExperimentalAttribute, and the call in MarkInternal). The PR now only does the generic unused-using removal: the CS8019-based pass runs after internalizing types and pruning model-factory methods and drops any directive left unused. Also removed the experimental-specific test/assets (kept RemovesUnusedUsingFromModelFactoryWhenInternalizing) and regenerated all test libraries — zero diff, since no generated type carried [Experimental].

@jorgerangel-msft jorgerangel-msft left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot it looks like we still have bugs in our implementation. The diff from regenerating all the libraries is here https://github.com/Azure/azure-sdk-for-net/pull/59868/changes. You can see, for serialization we incorrectly removed the using System.ClientModel statements

…sing cleanup

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title Remove unused usings when internalizing Experimental types Remove unused usings when internalizing types Jun 11, 2026
Copilot AI requested a review from jorgerangel-msft June 11, 2026 23:23
…ping needed usings)

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot it looks like we still have bugs in our implementation. The diff from regenerating all the libraries is here https://github.com/Azure/azure-sdk-for-net/pull/59868/changes. You can see, for se...

Fixed. Root cause: when the post-processing compilation can't resolve some external type references (e.g. BinaryContent/ClientResult because System.ClientModel isn't referenced), the compiler emits CS0234/CS0246 and then falsely reports using System.ClientModel; as CS8019 ("unnecessary"), so it got removed even though it's used by the conversion operators. RemoveUnusedUsings now skips any document that has unresolved type/namespace/name diagnostics, since CS8019 can't be trusted there. Added a regression test (KeepsUsedUsingWhenTypeReferencesAreUnresolved) that reproduces the serialization scenario without the System.ClientModel reference and validates the using is preserved. Regenerated all test libraries with zero diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants