Skip to content

Add bool-property-name-prefix lint rule for TCGC C# ruleset#4459

Draft
Copilot wants to merge 4 commits into
mainfrom
copilot/linter-rename-bool-properties
Draft

Add bool-property-name-prefix lint rule for TCGC C# ruleset#4459
Copilot wants to merge 4 commits into
mainfrom
copilot/linter-rename-bool-properties

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 19, 2026

Encodes the Azure SDK for .NET mgmt naming convention — boolean property/parameter names must start with Is, Has, Can, Should, Are, Was, Will, Do, or Does — as a lint rule so the ~576 hand-rolled @@clientName overrides observed in azure-rest-api-specs can be caught automatically.

Rule

  • New rule @azure-tools/typespec-client-generator-core/bool-property-name-prefix, registered in the best-practices:csharp ruleset.
  • Visits every ModelProperty (covers operation parameters, which live on Operation.parameters).
  • Boolean detection walks the Scalar.baseScalar chain, so custom scalars extending boolean are flagged too.
  • Reads the C#-scoped name via getLibraryName(ctx, prop, "csharp") and PascalCases it (matching the .NET emitter) before checking the prefix list.
  • Diagnostic suggests @clientName("Is<PascalName>", "csharp") for a C#-only fix, or a TypeSpec rename when the convention applies cross-language.

Example

// ❌ flagged
model Widget {
  tracked: boolean;     // → suggest IsTracked
  exclude: boolean;     // → suggest IsExcluded
}
op restore(restore: boolean): void;  // → suggest IsRestore

// ✅ accepted
model Widget {
  @clientName("IsTracked", "csharp")
  tracked: boolean;
  hasDynamicFieldSchema: boolean;
  canDelete: boolean;
}

Files

  • src/rules/bool-property-name-prefix.rule.ts — rule implementation.
  • src/linter.ts — registered in rules and csharpRules.
  • test/rules/bool-property-name-prefix.test.ts — 12 tests: positive/negative cases, custom scalars extending boolean, csharp-scoped @clientName overrides (resolving and introducing violations), operation parameters, and prefix-substring boundary (issueIs prefix).
  • website/.../rules/bool-property-name-prefix.md — rule doc.
  • .chronus/changes/...feature changelog entry for @azure-tools/typespec-client-generator-core.

@microsoft-github-policy-service microsoft-github-policy-service Bot added lib:tcgc Issues for @azure-tools/typespec-client-generator-core library meta:website TypeSpec.io updates labels May 19, 2026
Copilot AI changed the title [WIP] Fix bool properties to start with Is/Can/Has prefix Add bool-property-name-prefix lint rule for TCGC C# ruleset May 19, 2026
Copilot AI requested a review from haiyuazhang May 19, 2026 08:09
Offer three Quick Fix options (Is, Can, Has prefix) when the rule flags
a boolean property. Each codefix inserts @clientName with the chosen
prefix on the line before the property.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 19, 2026

⚡ Benchmark Results

⚠️ 27 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
total 🔴 581.2ms 🔴 814.1ms +40.1% 🔴
loader 🟢 108.4ms 🟢 168.7ms +55.6% 🔴
resolver 🟢 13.5ms 🟢 18.4ms +36.0% 🔴
checker 🟢 135.4ms 🟢 193.1ms +42.6% 🔴
validation 🟢 32.0ms 🟢 41.8ms +30.7% 🔴
 ↳ validation/@azure-tools/typespec-azure-core 🟢 4.4ms 🟢 6.4ms +43.7% 🔴
 ↳ validation/@typespec/http 🟢 3.8ms 🟢 5.6ms +47.8% 🔴
 ↳ validation/@typespec/versioning 🔴 21.6ms 🔴 27.6ms +27.6% 🔴
linter 🟢 93.5ms 🟢 134.9ms +44.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 4.1ms 🟢 5.6ms +35.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🟡 12.7ms 🟡 19.5ms +54.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🟡 13.0ms 🟡 19.8ms +51.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🟡 16.6ms 🔴 23.9ms +43.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 3.5ms 🟢 5.7ms +65.0% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🟡 15.5ms 🔴 23.0ms +48.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 3.3ms 🟢 5.2ms +55.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟢 3.0ms 🟢 4.3ms +44.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 3.8ms 🟢 5.5ms +47.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟢 3.4ms 🟢 4.6ms +36.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 3.6ms 🟢 5.3ms +45.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟢 9.2ms 🟡 14.6ms +58.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🟡 14.6ms 🔴 22.2ms +52.1% 🔴
emit 🟢 192.6ms 🟡 250.7ms +30.1% 🔴
 ↳ emit/@azure-tools/typespec-autorest 🟢 120.0ms 🟢 157.5ms +31.2% 🔴
 ↳ emit/@typespec/openapi3 🟢 107.7ms 🟢 139.9ms +29.9% 🔴
 ↳ emit/@typespec/openapi3/compute 🟢 96.5ms 🟢 125.4ms +30.0% 🔴
 ↳ emit/@typespec/openapi3/write 🟢 11.0ms 🟢 14.6ms +33.0% 🔴
Full details – comparing 5bc71b5 vs baseline 213d2b2
Metric Baseline Current Change
total 🔴 581.2ms 🔴 814.1ms +40.1% 🔴
loader 🟢 108.4ms 🟢 168.7ms +55.6% 🔴
resolver 🟢 13.5ms 🟢 18.4ms +36.0% 🔴
checker 🟢 135.4ms 🟢 193.1ms +42.6% 🔴
validation 🟢 32.0ms 🟢 41.8ms +30.7% 🔴
 ↳ validation/@azure-tools/typespec-azure-core 🟢 4.4ms 🟢 6.4ms +43.7% 🔴
 ↳ validation/@typespec/http 🟢 3.8ms 🟢 5.6ms +47.8% 🔴
 ↳ validation/@typespec/rest 🟢 0.4ms 🟢 0.5ms +20.4%
 ↳ validation/@typespec/versioning 🔴 21.6ms 🔴 27.6ms +27.6% 🔴
 ↳ validation/compiler 🟢 1.3ms 🟢 1.3ms +6.1%
linter 🟢 93.5ms 🟢 134.9ms +44.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.0ms 🟢 0.0ms +16.6%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.1ms 🟢 0.2ms +27.2%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 4.1ms 🟢 5.6ms +35.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 0.4ms 🟢 0.6ms +29.0%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.1ms 🟢 0.1ms +10.4%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 0.6ms 🟢 0.8ms +21.4%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 0.4ms 🟢 0.6ms +24.3%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.1ms 🟢 0.2ms +30.3%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.2ms 🟢 0.2ms +24.6%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.2ms 🟢 0.3ms +34.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.2ms 🟢 0.2ms +12.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 0.2ms 🟢 0.2ms +27.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.0ms 🟢 0.0ms +21.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.1ms 🟢 0.1ms +23.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.1ms 🟢 0.1ms +25.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.3ms 🟢 0.4ms +33.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.3ms 🟢 0.4ms +14.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🟡 12.7ms 🟡 19.5ms +54.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 0.8ms 🟢 1.0ms +28.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.0ms 🟢 0.1ms +31.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.2ms 🟢 0.2ms +23.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 0.9ms 🟢 1.2ms +24.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 1.4ms 🟢 1.7ms +18.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 1.4ms 🟢 1.7ms +24.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🟡 13.0ms 🟡 19.8ms +51.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🟡 16.6ms 🔴 23.9ms +43.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.0ms 🟢 0.0ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 3.5ms 🟢 5.7ms +65.0% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.1ms 🟢 0.2ms +42.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.0ms 🟢 0.0ms +30.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.1ms 🟢 0.2ms +38.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.2ms 🟢 0.3ms +34.9%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.1ms 🟢 0.1ms +11.4%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.2ms 🟢 0.2ms +14.9%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.0ms 🟢 0.0ms -9.1%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🟡 15.5ms 🔴 23.0ms +48.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.2ms 🟢 0.3ms +51.5%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.2ms 🟢 0.2ms +33.5%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 3.3ms 🟢 5.2ms +55.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.1ms 🟢 0.1ms +46.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟢 3.0ms 🟢 4.3ms +44.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.1ms 🟢 0.1ms +39.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.0ms 🟢 0.1ms +32.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 3.8ms 🟢 5.5ms +47.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟢 3.4ms 🟢 4.6ms +36.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.3ms 🟢 0.3ms +27.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 0.4ms 🟢 0.5ms +39.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.0ms 🟢 0.0ms +8.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.2ms 🟢 0.2ms +46.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.1ms 🟢 0.1ms +43.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.0ms 🟢 0.0ms +21.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.1ms 🟢 0.1ms +27.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.1ms 🟢 0.1ms +44.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.0ms 🟢 0.0ms +20.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.2ms 🟢 0.2ms +30.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.0ms 🟢 0.0ms +0.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.1ms 🟢 0.2ms +21.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 3.6ms 🟢 5.3ms +45.3% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.2ms 🟢 0.3ms +30.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.1ms 🟢 0.2ms +38.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.1ms 🟢 0.1ms +40.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.1ms 🟢 0.1ms +39.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.1ms 🟢 0.1ms +39.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.0ms 🟢 0.0ms +18.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟢 9.2ms 🟡 14.6ms +58.9% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.0ms 🟢 0.0ms +28.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 0.2ms 🟢 0.3ms +17.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.1ms 🟢 0.1ms +25.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.1ms 🟢 0.2ms +41.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🟡 14.6ms 🔴 22.2ms +52.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.1ms 🟢 0.1ms +34.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.1ms 🟢 0.1ms +34.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 1.9ms 🟢 2.2ms +13.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.3ms 🟢 0.4ms +32.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.0ms 🟢 0.0ms +5.3%
 ↳ linter/@azure-tools/typespec-client-generator-core/bool-property-name-prefix 🟢 0.0ms 🟢 0.3ms +100.0%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 0.7ms 🟢 1.0ms +33.9%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 0.2ms 🟢 0.2ms +3.9%
emit 🟢 192.6ms 🟡 250.7ms +30.1% 🔴
 ↳ emit/@azure-tools/typespec-autorest 🟢 120.0ms 🟢 157.5ms +31.2% 🔴
 ↳ emit/@typespec/openapi3 🟢 107.7ms 🟢 139.9ms +29.9% 🔴
 ↳ emit/@typespec/openapi3/compute 🟢 96.5ms 🟢 125.4ms +30.0% 🔴
 ↳ emit/@typespec/openapi3/write 🟢 11.0ms 🟢 14.6ms +33.0% 🔴

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 19, 2026

Open in StackBlitz

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

commit: 8fe365f

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linter: bool properties/parameters must start with Is/Can/Has

2 participants