Skip to content

[Swagger Linter Migration] ValidQueryParametersForPointOperations - #5273

Open
Yuchao Yan (msyyc) wants to merge 2 commits into
Azure:mainfrom
msyyc:promote-valid-query-parameters-point-operations
Open

[Swagger Linter Migration] ValidQueryParametersForPointOperations#5273
Yuchao Yan (msyyc) wants to merge 2 commits into
Azure:mainfrom
msyyc:promote-valid-query-parameters-point-operations

Conversation

@msyyc

@msyyc Yuchao Yan (msyyc) commented Aug 20, 2026

Copy link
Copy Markdown
Member

Original Swagger linters

This promoted TypeSpec rule intentionally covers two Swagger validator rules:

  1. ValidQueryParametersForPointOperations, implemented by the validator's Spectral function for ARM RPC guideline RPC-Uri-V1-13.
  2. ParametersInPointGet, implemented by the validator's Spectral function for ARM RPC guideline RPC-Get-V1-08.

Official TypeSpec rule name: point-operation-invalid-query-parameter (renamed during promotion to follow TypeSpec linter naming conventions).

ValidQueryParametersForPointOperations performs these checks:

  • Traverses resolved Swagger paths and x-ms-paths entries.
  • Classifies a URI as a point path only when its final provider-qualified portion contains /providers/{namespace} followed by one or more resource-type/resource-name pairs; resource names may be {parameters} or default.
  • Checks GET, PUT, PATCH, and DELETE operations.
  • Reads each operation's parameters array and ignores non-query parameters.
  • Allows api-version and reports every other query parameter independently.
  • Excludes collection paths, unmatched trailing path segments, and providerless paths.

ParametersInPointGet is the older production GET-only form of the same policy. It performs these checks:

  • Traverses Swagger paths entries.
  • Classifies a URI as a point resource path with getResourcesPathHierarchyBasedOnResourceType.
  • Checks only GET operations.
  • Allows GET query parameters named exactly api-version.
  • Reports every other GET query parameter at the operation parameters array.

How the Swagger linters work

ValidQueryParametersForPointOperations is invoked over the resolved maps selected by $[paths,'x-ms-paths']. The function loops each URI, applies the shared isPointOperation regex to the portion beginning at the last /providers/, then loops GET/PUT/PATCH/DELETE and filters each resolved parameter array for query parameters other than api-version. Each rejected emitted parameter produces one error located at that operation's parameters array.

ParametersInPointGet uses a narrower production path: it loops the Swagger paths object, classifies each URI with the ARM resource hierarchy helper, checks only the get operation, and reports query parameters other than api-version. This is a subset of the broader point-operation rule, so it should map to the same TypeSpec implementation rather than to a second production TypeSpec rule.

The broader Swagger rule is stagingOnly, so normal production AutoRest validation disables it and reports 0 projects. The checked-in migration investigation instead ran the actual Spectral staging rule. Its initial 64-project same-corpus population became 62 projects after restricting both sides to the 462 projects whose TypeSpec compiled, with all 62 projects overlapping. The production ParametersInPointGet row separately shows 40 Swagger projects, all overlapping the same TypeSpec rule.

Raw diagnostic counts are intentionally not one-to-one: Swagger reports emitted operation-parameter occurrences, while a shared TypeSpec parameter declaration can instantiate into several operations and projected versions. The final staging comparison is 321 Swagger diagnostics versus 724 TypeSpec diagnostics, but 62 versus 62 projects with no one-sided projects. The GET-only production comparison is 189 Swagger diagnostics versus the same raw 724 TypeSpec diagnostics, with 40 overlapping Swagger projects and 22 TypeSpec-only projects explained by PUT/PATCH/DELETE coverage from the broader staging rule. The validator also accepts x-ms-paths, while a clean TypeSpec @sharedRoute equivalent was not included because its emitted ?_overload=... disambiguator does not reproduce the upstream rule.

Source TypeSpec lintdiff rule

The user-marked done source is tsp-lintdiff-local-linter/valid-query-parameters-for-point-operations on branch feature/lintdiff-migration-new, captured at intake commit e9d5541c2ef3e354ce1bf6ab3332dfb87620a8d2. The source worktree was clean at intake and had no uncommitted rule changes. This promotion did not modify the lintdiff source, fixtures, snapshots, manifests, or documentation.

Destination analysis

This rule belongs in @azure-tools/typespec-azure-resource-manager because validator metadata declares applicability: ARM, sources: ["arm"], and the fixture explicitly selects the resource-manager ruleset. Its semantics depend on ARM provider-qualified resource paths and ARM RPC guidance. Azure Core was technically possible because the implementation needs only compiler and HTTP APIs, but placing ARM-only URI policy in the shared data-plane package would expose the wrong dependency and ruleset surface. No equivalent official ARM or Core rule exists.

How the promoted TypeSpec linter works

The promoted rule visits TypeSpec operations and resolves each with getHttpOperation. It filters to GET, PUT, PATCH, and DELETE, then applies the same provider/resource-pair path regex as the Swagger helper to the portion after the last /providers/. For eligible point paths, it examines resolved HTTP parameters, ignores non-query parameters and case-insensitive api-version, and reports each additional query parameter on its authorable TypeSpec parameter declaration.

This one TypeSpec rule therefore covers both Swagger inputs: it covers ParametersInPointGet when the verb is GET, and it covers ValidQueryParametersForPointOperations across GET/PUT/PATCH/DELETE. The implementation intentionally does not use ARM operation-kind metadata because that would misclassify list-shaped reads and providerless resource-group DELETE operations that the Swagger path matcher excludes. It also performs no promotion-only deduplication, preserving the done lintdiff rule's operation traversal and source-target behavior. No version projection or semantic behavior was added during promotion.

Fixture-to-native test mapping

Each lintdiff fixture became focused native vitest coverage using the ARM package tester:

No validator snapshots or lintdiff corpus artifacts were copied.

Migration evidence

The focused fixtures, real-service comparison, full-corpus counts, former TypeSpec-only projects, projection fix, diagnostic-cardinality analysis, compile-success population, and remaining uncertainty for ValidQueryParametersForPointOperations are documented in migration.md.

The companion ParametersInPointGet investigation confirms the same TypeSpec rule covers every assessable production GET-only Swagger project and explains the 22 TypeSpec-only projects as broader PUT/PATCH/DELETE coverage, not as false positives or a need for another TypeSpec rule: #5210

Promotion sync policy

If review identifies a semantic gap, this PR should remain blocked until the user explicitly reopens the lintdiff repair workflow. The immutable source rule must be repaired and revalidated first; semantic changes should not be made only in this promotion PR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 72da97a1-a62c-41e5-b4da-c2a485f735d4
@msyyc Yuchao Yan (msyyc) added the int:azure-specs Run integration tests against azure-rest-api-specs label Aug 20, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library meta:website TypeSpec.io updates linter Issues related to linter rules labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @azure-tools/typespec-azure-resource-manager
  • @azure-tools/typespec-azure-rulesets
Show changes

@azure-tools/typespec-azure-resource-manager - feature ✏️

Add an ARM lint rule that warns when point GET, PUT, PATCH, or DELETE operations declare query parameters other than api-version.

@azure-tools/typespec-azure-rulesets - feature ✏️

Add an ARM lint rule that warns when point GET, PUT, PATCH, or DELETE operations declare query parameters other than api-version.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

📦 Package size report

1 package changed size, +1.75 KB (+0.0%) packed overall.

Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-client-generator-core 227.76 KB → 229.25 KB +1.49 KB (+0.7%) 🔴 1.23 MB → 1.23 MB +3.31 KB (+0.3%)
12 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-java 13.51 MB → 13.51 MB +105 B (+0.0%) 15.03 MB → 15.03 MB +65 B (+0.0%)
@azure-tools/typespec-azure-resource-manager 172.95 KB → 173.03 KB +84 B (+0.0%) 1.05 MB → 1.05 MB +682 B (+0.1%)
@azure-tools/typespec-go 258.42 KB → 258.44 KB +29 B (+0.0%) 1.32 MB → 1.32 MB +95 B (+0.0%)
@azure-tools/typespec-azure-rulesets 5.16 KB → 5.18 KB +24 B (+0.5%) 32.09 KB → 32.31 KB +228 B (+0.7%)
@azure-tools/typespec-python 42.20 KB → 42.22 KB +21 B (+0.0%) 164.85 KB → 164.91 KB +65 B (+0.0%)
@azure-tools/typespec-ts 527.17 KB → 527.17 KB -2 B (-0.0%) 2.54 MB → 2.54 MB
@azure-tools/azure-http-specs 146.63 KB → 146.63 KB 1.16 MB → 1.16 MB
@azure-tools/typespec-autorest 80.93 KB → 80.93 KB 395.06 KB → 395.06 KB
@azure-tools/typespec-autorest-canonical 7.42 KB → 7.42 KB 26.00 KB → 26.00 KB
@azure-tools/typespec-azure-core 129.43 KB → 129.43 KB 702.77 KB → 702.77 KB
@azure-tools/typespec-azure-portal-core 42.40 KB → 42.40 KB 192.91 KB → 192.91 KB
@azure-tools/typespec-metadata 15.91 KB → 15.91 KB 62.26 KB → 62.26 KB

Packed = gzipped .tgz published to npm. Unpacked = total extracted size. 🆕 added, 🗑️ removed. Packages from the core/ submodule are not included.
🔴 grew · 🟢 shrank — only changes of at least 512 B and 0.5% are marked.

@pkg-pr-new

pkg-pr-new Bot commented Aug 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-azure-resource-manager@5273
npm i https://pkg.pr.new/@azure-tools/typespec-azure-rulesets@5273

commit: 80e8ff6

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8ed00e6d-dd0a-40f7-8871-ee32f0f371fb
@msyyc

Yuchao Yan (msyyc) commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

Finding from the ParametersInPointGet migration check: we do not need a separate TypeSpec linter for ParametersInPointGet.

ParametersInPointGet is the older production Swagger rule for point GET operations only. The migrated TypeSpec rule in this PR, valid-query-parameters-for-point-operations, is the right shared implementation because it covers that GET behavior and also covers the broader staging-only Swagger rule ValidQueryParametersForPointOperations for point GET/PUT/PATCH/DELETE.

So the expected follow-up is documentation/evidence only: map ParametersInPointGet to this broader rule and explain the apparent TypeSpec-only projects as PUT/PATCH/DELETE coverage from the broader rule, not as false positives or a need for another rule.

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

Labels

int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library linter Issues related to linter rules meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant