Skip to content

Add cop static-analysis rules for the C# emitter#10909

Open
JoshLove-msft wants to merge 6 commits into
microsoft:mainfrom
JoshLove-msft:joshlove-msft/csharp-cop-rules
Open

Add cop static-analysis rules for the C# emitter#10909
JoshLove-msft wants to merge 6 commits into
microsoft:mainfrom
JoshLove-msft:joshlove-msft/csharp-cop-rules

Conversation

@JoshLove-msft
Copy link
Copy Markdown
Contributor

@JoshLove-msft JoshLove-msft commented Jun 5, 2026

Adds cop static-analysis rules scoped to the C# emitter generator, fixes the existing violations, and wires the checks into CI.

cop is a general-purpose static-analysis language. Each rule is a .cop file under packages/http-client-csharp/cop-checks/.

Rules

  • braces.cop — control-flow statements (if / else / else if / for / foreach / while) must use { ... } blocks; flags inline unbraced bodies.
  • snippet-factory.cop — expression types must be created through the Snippet factory rather than their constructors (see Create an analyzer for MGC to ensure some APIs are not misused #3724). Excludes the Snippets/ and Expressions/ layers and test code. Only constructors with a clear factory equivalent are flagged (e.g. KeywordExpression is limited to null/this/default; InvokeMethodExpression only when it has a non-null instance receiver).

main.cop wires the per-rule predicates to the C# codebase and exposes one command per rule (CHECK-BRACES, CHECK-SNIPPETS).

Fixes

Resolved all violations the rules surface: added braces to inline guard clauses and replaced expression constructors with Snippet helpers (Literal, TypeOf, New.Instance, Default, recv.Invoke(...), Static(t).Invoke(...)).

CI

eng/scripts/Invoke-Cop.ps1 downloads a pinned cop release and runs the checks against the generator, failing on any violation. It is invoked from the unit-test CI job (Test-Packages.ps1). Locally: npm run cop.

Note: the script downloads the cop binary from the cop GitHub releases at build time — an external dependency that maintainers may want to mirror/pin before enabling broadly.

Run locally

cop packages/http-client-csharp/cop-checks/main.cop -t packages/http-client-csharp/generator

Run a single rule with -c CHECK-BRACES or -c CHECK-SNIPPETS.

Add cop checks scoped to the C# generator:
- braces.cop: control-flow statements (if/else/for/foreach/while) must use braces
- snippet-factory.cop: expression types must be created via the Snippet factory
  (see microsoft#3724)

main.cop wires the per-rule predicates to the codebase and exposes one command
per rule (CHECK-BRACES, CHECK-SNIPPETS).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 5, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@10909

commit: a6854ae

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

No changes needing a change description found.

JoshLove-msft and others added 2 commits June 5, 2026 14:19
Apply the cop checks to the generator:
- Add braces to inline guard clauses in PartialMethodCustomization.
- Use Snippet factory helpers instead of expression constructors:
  Literal, TypeOf, New.Instance, Default, and receiver.Invoke(...).

Tighten snippet-factory.cop to remove false positives:
- KeywordExpression only flags null/this/default (yield/break have no Snippet).
- InvokeMethodExpression only flags calls with a non-null instance receiver
  (unqualified `new InvokeMethodExpression(null, ...)` has no Snippet equivalent).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add Invoke-Cop.ps1 which downloads a pinned Agent Cop release and runs the
cop-checks rules against the generator, failing on any violation. Wire it into
the unit-test CI job (Test-Packages.ps1) and add an `npm run cop` convenience
script.

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

The cop provider packages (code, csharp) are auto-restored from the GitHub
feed on first run, which can fail transiently on CI agents (rate limiting /
network blips). Retry the check run with backoff when a restore/provider
failure is detected, while still reporting genuine rule violations immediately.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JoshLove-msft and others added 2 commits June 5, 2026 16:59
The cop provider packages (code, csharp) auto-restored from the GitHub feed are
version-locked to the cop runtime and always track the latest upstream build.
Pinning the binary to an older release tag caused the provider to fail to load
(assembly load error) once the feed moved ahead. Default to the latest release
(via the releases/latest/download redirect, no API call) so the binary stays in
lockstep with the providers, and only retry genuinely transient feed errors --
not version-mismatch load failures.

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

cop resolves its feed packages (code, csharp) via the GitHub REST API, which is
rate-limited to 60 req/hour for unauthenticated callers. On shared CI agents
that budget is exhausted, so auto-restore fails with "not found in any
configured feed" and the csharp provider never loads. Fork PRs have no secrets,
so a GITHUB_TOKEN cannot be supplied to raise the limit.

Seed the two imported packages directly from the cop repo at the tag matching
the downloaded binary (read from cop -v) via a sparse, blob-filtered git clone
(git protocol, not the REST API; fetches only those two directories). cop then
finds them in its cache and never calls the rate-limited feed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JoshLove-msft JoshLove-msft enabled auto-merge June 6, 2026 04:42
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.

2 participants