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>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the stale Mark a PR that hasn't been recently updated and will be closed. label Jun 5, 2026
@microsoft-github-policy-service
Copy link
Copy Markdown

Hi @@copilot. Your PR has had no update for 14 days and it is marked as a stale PR. If it is not updated within 14 days, the PR will automatically be closed. If you want to refresh the PR, please remove the stale label.

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 stale Mark a PR that hasn't been recently updated and will be closed.

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