Skip to content

[tcgc]: add exact() function for preserving client names without …#4378

Open
iscai-msft wants to merge 5 commits intoAzure:mainfrom
iscai-msft:feature/tcgc-exact-client-name
Open

[tcgc]: add exact() function for preserving client names without …#4378
iscai-msft wants to merge 5 commits intoAzure:mainfrom
iscai-msft:feature/tcgc-exact-client-name

Conversation

@iscai-msft
Copy link
Copy Markdown
Contributor

…casing transformations

Add the exact() function that can be used with @clientName to signal that language emitters should not apply their usual casing transformations (e.g., snake_case for Python, PascalCase for C#).

Usage: @clientName(exact("hello_world"), "python")

Implementation:

  • extern fn exact() in lib/functions.tsp that returns a prefixed string
  • normalizeExactName/hasExactNameMarker helpers for stripping the prefix
  • isExactName field added to SDK interfaces (SdkModelType, SdkEnumType, SdkUnionType, SdkConstantType, SdkNullableType, SdkModelPropertyTypeBase, SdkClientInitializationType)
  • isExactClientName() public utility for checking exact name status
  • Prefix is stripped at name resolution time (getLibraryName) and isExactName is set at SDK type creation time
  • 7 new tests covering models, properties, enums, operations, and language-scoped exact names

iscai-msft and others added 2 commits May 5, 2026 12:18
…casing transformations

Add the exact() function that can be used with @clientName to signal
that language emitters should not apply their usual casing transformations
(e.g., snake_case for Python, PascalCase for C#).

Usage: @clientName(exact("hello_world"), "python")

Implementation:
- extern fn exact() in lib/functions.tsp that returns a prefixed string
- normalizeExactName/hasExactNameMarker helpers for stripping the prefix
- isExactName field added to SDK interfaces (SdkModelType, SdkEnumType,
  SdkUnionType, SdkConstantType, SdkNullableType, SdkModelPropertyTypeBase,
  SdkClientInitializationType)
- isExactClientName() public utility for checking exact name status
- Prefix is stripped at name resolution time (getLibraryName) and
  isExactName is set at SDK type creation time
- 7 new tests covering models, properties, enums, operations, and
  language-scoped exact names

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The `exact()` function preserves client names without language-specific casing transformations. Added `isExactName` field to SDK type interfaces for emitters to check casing transformations.
@microsoft-github-policy-service microsoft-github-policy-service Bot added the lib:tcgc Issues for @azure-tools/typespec-client-generator-core library label May 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

⚡ Benchmark Results

Comparing [135c9a9] against baseline [ea64206]

Metric Baseline Current Change
total 🔴 876.3ms 🔴 868.4ms -0.9%
loader 🟢 176.9ms 🟢 179.0ms +1.2%
resolver 🟢 21.1ms 🟢 20.0ms -5.3% 🟢
checker 🟡 215.8ms 🟡 208.3ms -3.5%
validation 🟢 43.9ms 🟢 43.2ms -1.6%
 ↳ validation/@azure-tools/typespec-azure-core 🟢 6.8ms 🟢 7.2ms +5.0%
 ↳ validation/@typespec/http 🟢 6.8ms 🟢 7.2ms +6.7% 🔴
 ↳ validation/@typespec/rest 🟢 0.6ms 🟢 0.6ms -11.5% 🟢
 ↳ validation/@typespec/versioning 🔴 27.9ms 🔴 26.6ms -4.7%
 ↳ validation/compiler 🟢 1.7ms 🟢 1.7ms -5.1% 🟢
linter 🟢 155.3ms 🟢 156.0ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.0ms 🟢 0.0ms +5.6% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.2ms 🟢 0.2ms -2.6%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 7.5ms 🟢 6.7ms -10.9% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 0.7ms 🟢 0.7ms +2.0%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.1ms 🟢 0.1ms +5.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 0.8ms 🟢 0.8ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 0.7ms 🟢 0.7ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.2ms 🟢 0.2ms +0.0%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.2ms 🟢 0.2ms -2.2%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.3ms 🟢 0.3ms +0.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.2ms 🟢 0.2ms -4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 0.3ms 🟢 0.3ms -2.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.0ms 🟢 0.0ms -2.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.1ms 🟢 0.1ms -1.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.1ms 🟢 0.1ms -5.5% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.5ms 🟢 0.5ms -3.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.4ms 🟢 0.4ms -6.7% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 21.9ms 🔴 21.5ms -1.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 1.1ms 🟢 1.2ms +1.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.1ms 🟢 0.1ms +32.6% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.2ms 🟢 0.2ms -2.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 1.3ms 🟢 1.3ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 2.1ms 🟢 2.0ms -8.7% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 2.2ms 🟢 1.9ms -14.1% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 25.9ms 🔴 28.4ms +9.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 24.1ms 🔴 24.3ms +0.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.0ms 🟢 0.0ms -3.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 6.0ms 🟢 6.4ms +7.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.2ms 🟢 0.2ms -7.6% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.1ms 🟢 0.1ms +8.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.2ms 🟢 0.2ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.3ms 🟢 0.3ms -5.0% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.2ms 🟢 0.2ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.2ms 🟢 0.2ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.0ms 🟢 0.0ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 24.1ms 🔴 24.5ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.3ms 🟢 0.3ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.3ms 🟢 0.3ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 5.7ms 🟢 5.5ms -3.3%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.1ms 🟢 0.1ms +0.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟢 6.3ms 🟢 6.2ms -1.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.1ms 🟢 0.1ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms -13.8% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 7.4ms 🟢 7.2ms -1.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.4ms 🟢 0.4ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 0.7ms 🟢 0.7ms -0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.0ms 🟢 0.0ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.3ms 🟢 0.3ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.2ms 🟢 0.1ms -6.3% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.0ms 🟢 0.0ms -29.5% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.1ms 🟢 0.1ms -2.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.1ms 🟢 0.1ms -14.2% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.1ms 🟢 0.1ms -16.7% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.3ms 🟢 0.3ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.0ms 🟢 0.0ms -12.9% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.2ms 🟢 0.2ms +1.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 8.9ms 🟢 8.4ms -6.4% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.4ms 🟢 0.4ms -3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.2ms 🟢 0.2ms -6.2% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.1ms 🟢 0.1ms -4.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.1ms 🟢 0.1ms +1.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.2ms 🟢 0.2ms +5.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.0ms 🟢 0.0ms -11.3% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🔴 21.6ms 🟡 19.7ms -8.6% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.0ms 🟢 0.0ms -11.6% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 0.3ms 🟢 0.3ms -0.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.2ms 🟢 0.1ms -12.4% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.2ms 🟢 0.2ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 28.2ms 🔴 30.8ms +9.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.2ms 🟢 0.1ms -3.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.2ms 🟢 0.2ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 2.7ms 🟢 2.5ms -5.8% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.4ms 🟢 0.4ms +2.2%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 1.1ms 🟢 1.1ms +1.0%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 0.2ms 🟢 0.2ms -4.6%
emit 🟡 263.3ms 🟡 261.8ms -0.6%
 ↳ emit/@azure-tools/typespec-autorest 🟢 166.0ms 🟢 164.3ms -1.1%
 ↳ emit/@typespec/openapi3 🟢 145.8ms 🟢 146.3ms +0.3%
 ↳ emit/@typespec/openapi3/compute 🟢 126.9ms 🟢 130.8ms +3.0%
 ↳ emit/@typespec/openapi3/write 🟢 18.8ms 🟢 15.4ms -17.7% 🟢

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.

@azure-sdk
Copy link
Copy Markdown
Collaborator

azure-sdk commented May 5, 2026

All changed packages have been documented.

  • @azure-tools/typespec-client-generator-core
Show changes

@azure-tools/typespec-client-generator-core - feature ✏️

Added exact() function for use with @clientName to preserve client names without language-specific casing transformations. When a name is marked with exact(), emitters should use it as-is. Also added isExactName boolean field to SDK type interfaces (SdkModelType, SdkEnumType, SdkUnionType, SdkModelPropertyTypeBase, etc.) so emitters can check whether to skip casing transformations.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 5, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-client-generator-core@4378

commit: d71e8d1

@azure-sdk
Copy link
Copy Markdown
Collaborator

azure-sdk commented May 5, 2026

You can try these changes here

🛝 Playground 🌐 Website

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

Labels

lib:tcgc Issues for @azure-tools/typespec-client-generator-core library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants