Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 20, 2025

External Types Implementation for http-client-csharp

This PR implements support for external type references in the C# http-client-csharp emitter, enabling the use of the @alternateType decorator with ExternalType objects as defined in Azure/typespec-azure#3233.

Note: Only .NET framework types are supported as external type references. Non-framework external types will emit a warning diagnostic and be skipped during code generation to ensure buildable libraries.

Changes Made

  • Add InputExternalType interface to TypeScript input-type.ts
  • Update InputType union to include InputExternalType
  • Implement external type detection and conversion in type-converter.ts
  • Add InputExternalType C# class to the generator
  • Add InputExternalTypeConverter for JSON deserialization
  • Update InputTypeConverter to handle "external" kind
  • Update TypeFactory.CreateCSharpTypeCore to handle InputExternalType
  • Add CreateExternalType method to create CSharpType from external references
  • Add comprehensive test coverage for external types
  • Add diagnostic for unsupported external types (emitted from generator code)
  • Return null for non-framework external types to prevent non-buildable code generation
  • Add unit tests in ModelProviderTests validating external type functionality

Implementation Details

Emitter (TypeScript):

  • Added InputExternalType interface with identity, package, and minVersion properties
  • Modified fromSdkType to detect when an SDK type has an external property and convert it to InputExternalType
  • Added fromSdkExternalType helper function that converts external type information to InputExternalType

Generator (C#):

  • Created InputExternalType class in Microsoft.TypeSpec.Generator.Input
  • Created InputExternalTypeConverter for JSON deserialization of InputExternalType from the TypeScript emitter output
  • Updated InputTypeConverter to handle "external" kind and route to InputExternalTypeConverter
  • Updated TypeFactory.CreateCSharpTypeCore switch statement to handle InputExternalType
  • Implemented CreateExternalType method that:
    • Attempts to resolve external types as framework types using CreateFrameworkType
    • Emits a warning diagnostic using CodeModelGenerator.Instance.Emitter.ReportDiagnostic for types that cannot be resolved
    • Returns null for types that cannot be resolved as framework types (preventing generation of non-buildable code)

Usage Example

import "@azure-tools/typespec-client-generator-core";

using Azure.ClientGenerator.Core;

// ✅ Supported: Framework types will be resolved successfully
@alternateType({
  identity: "System.Uri",
}, "csharp")
model ExternalUri {
  value: string;
}

// ⚠️ Warning: Non-framework types will emit a diagnostic and be skipped
@alternateType({
  identity: "Azure.Core.Expressions.DataFactoryExpression",
  package: "Azure.Core.Expressions",
  minVersion: "1.0.0",
}, "csharp")
union Dfe<T> {
  T,
  DfeExpression: string
}

Framework types like System.Uri, System.BinaryData, System.Text.Json.JsonElement will be successfully resolved and referenced in the generated code. Non-framework external types will emit a warning during code generation and be skipped, ensuring that all generated libraries are buildable.

Testing

TypeScript Tests (in type-converter.test.ts):

  • External types on unions
  • External types on models
  • Package and version information handling

C# Generator Tests (in ModelProviderTests.cs):

  • ExternalTypeModelUsedAsProperty: Tests a model decorated with @alternateType that references System.Uri, used as a property in another model
  • ExternalTypePropertyIsResolved: Tests a property decorated with @alternateType referencing System.Net.IPAddress
  • UnsupportedExternalTypeEmitsDiagnostic: Tests that unsupported external types (non-framework) emit diagnostics and are properly skipped

Diagnostics

The warning diagnostic unsupported-external-type is emitted from the generator code (not the emitter) when:

  • An external type cannot be resolved as a framework type
  • The diagnostic uses a simplified message: "External type '{identity}' is not currently supported."

Fixes #8187

Original prompt

This section details on the original issue you should resolve

<issue_title>[http-client-csharp] Reference external types Implementation</issue_title>
<issue_description></issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #8187


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Implement reference for external types in HTTP client [http-client-csharp] Implement support for external type references Oct 20, 2025
Copilot AI requested a review from JoshLove-msft October 20, 2025 17:10
Copilot finished work on behalf of JoshLove-msft October 20, 2025 17:10

// If the type cannot be resolved as a framework type, create a generic CSharpType
// using the identity as the fully qualified name
return new CSharpType(externalType.Identity, isValueType: false, isNullable: false, null, null, null, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot there are build failures related to this line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 74e3f90. The issue was an incorrect call to the CSharpType constructor. I updated the CreateExternalType method to properly parse the fully qualified name and use the internal constructor with all required parameters.

Copilot AI requested a review from JoshLove-msft October 20, 2025 18:12
Copilot finished work on behalf of JoshLove-msft October 20, 2025 18:12
return new CSharpType(externalType.Identity, isValueType: false, isNullable: false, null, null, null, true);
// If the type cannot be resolved as a framework type, parse the fully qualified name
// and create a CSharpType using the internal constructor
var lastDotIndex = externalType.Identity.LastIndexOf('.');
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot this is not going to result in buildable libraries. We should emit a diagnostic saying that an unsupported external type was used and just return null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit c8a6e4b. Updated CreateExternalType to return null for external types that cannot be resolved as framework types. Also added a diagnostic warning in the TypeScript emitter for non-framework external types, preventing generation of non-buildable code.

Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot The diagnostic can be emitted directly from the generator code. We should not add this to the emitter code. We can use the CodeModelGenerator.Instance.Emitter property.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 3e8bf94. Moved the diagnostic emission from the TypeScript emitter to the C# generator code. The diagnostic is now emitted using CodeModelGenerator.Instance.Emitter.ReportDiagnostic in the CreateExternalType method, and the diagnostic code has been added to DiagnosticCodes.cs.

Copilot AI changed the title [http-client-csharp] Implement support for external type references [http-client-csharp] Implement support for external type references (framework types only) Oct 20, 2025
Copilot finished work on behalf of JoshLove-msft October 20, 2025 18:21
Copilot AI requested a review from JoshLove-msft October 20, 2025 18:21
Copilot finished work on behalf of JoshLove-msft October 20, 2025 18:44
@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 Oct 20, 2025
@github-actions
Copy link
Contributor

No changes needing a change description found.

public const string MissingItemsProperty = "missing-items-property";
public const string NoMatchingItemsProperty = "no-matching-items-property";
public const string UnsupportedSerialization = "unsupported-serialization";
public const string UnsupportedExternalType = "unsupported-external-type";
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot this can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed in commit 8e63fa5. The constant was not being used since the diagnostic code is passed as a string literal.

/// </summary>
/// <param name="externalType">The <see cref="InputExternalType"/> to convert.</param>
/// <returns>A <see cref="CSharpType"/> representing the external type, or null if the type cannot be resolved.</returns>
protected virtual CSharpType? CreateExternalType(InputExternalType externalType)
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot let's add a few tests that validate the new functionality:

  • simulate a model that is decorated with alternateType. The model should be used as a property in a different model.
  • simulate a property that is decorated with alternateType;
    These should go in ModelProviderTests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added in commit fc47d2e. Three tests added to ModelProviderTests.cs:

  1. TestExternalType_ModelDecoratedWithAlternateType - validates model decorated with @alternateType using System.Uri as property in another model
  2. TestExternalType_PropertyDecoratedWithAlternateType - validates property decorated with @alternateType using System.Net.IPAddress
  3. TestExternalType_UnsupportedExternalType - validates unsupported external types emit diagnostics and are skipped

All tests pass successfully.

Copilot AI requested a review from JoshLove-msft October 20, 2025 19:26
Copilot finished work on behalf of JoshLove-msft October 20, 2025 19:26
Copilot finished work on behalf of JoshLove-msft October 20, 2025 19:41
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.

[http-client-csharp] Reference external types Implementation

2 participants