Skip to content

feat(eslint-plugin-azure-sdk): add opt-in recommendedStrict preset with sonarjs integration#38405

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-recommendedstrict-preset
Draft

feat(eslint-plugin-azure-sdk): add opt-in recommendedStrict preset with sonarjs integration#38405
Copilot wants to merge 3 commits intomainfrom
copilot/add-recommendedstrict-preset

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 4, 2026

Adds two new opt-in ESLint configs to @azure/eslint-plugin-azure-sdk targeting AI-generated and hard-to-maintain code patterns. The new presets are purely additive — existing recommended / recommendedTypeChecked consumers see zero change.

Packages impacted by this PR

@azure/eslint-plugin-azure-sdk (common/tools/eslint-plugin-azure-sdk)

Issues associated with this PR

N/A

Describe the problem that is addressed by this PR

The existing recommended preset has no structural complexity caps or code-smell detection. As AI agents generate more SDK code, reviewers need a single opt-in switch to catch overly complex, redundant, dead, or hard-to-read code that wouldn't otherwise be flagged.

What are the possible designs available to address the problem? If there are more than one possible design, why was the one in this PR chosen?

Option A (chosen): A delta function recommendedStrictDelta({ typeChecked }) that returns only the additional rules, composed with recommended at config-export time. This keeps the strict rules isolated from the base preset and makes the type-checked split explicit with a single boolean. Consumers reference azsdkEslint.configs.recommendedStrict or recommendedStrictTypeChecked directly.

Option B: Bake strict rules into recommended behind a flag. Rejected — would affect all existing consumers and make the type-checked distinction harder to reason about.

Changes

  • package.json: eslint-plugin-sonarjs ^3.0.2 added to peerDependencies and devDependencies. Version 3.0.7 installed (ESLint 9 flat-config compatible; exports configs.recommended as a single flat-config object).

  • New src/configs/recommended-strict.ts: Exports recommendedStrictDelta({ typeChecked }). Rule groups:

    • Structural capsmax-lines-per-function (100), max-classes-per-file (1), @typescript-eslint/max-params (7), sonarjs/cognitive-complexity (15)
    • Anti one-linerno-nested-ternary, no-unneeded-ternary, no-implicit-coercion, no-lonely-if, no-else-return
    • Mutation/scopingno-param-reassign promoted to error + props: true; @typescript-eslint/prefer-readonly (type-checked)
    • Switch/control-flowcurly: all (overrides multi-line); default-case; @typescript-eslint/switch-exhaustiveness-check (type-checked)
    • Importsno-duplicate-imports; @typescript-eslint/consistent-type-imports promoted to error; @typescript-eslint/no-deprecated (type-checked)
    • Error handlingno-empty (no allowEmptyCatch); @typescript-eslint/only-throw-error / use-unknown-in-catch-callback-variable (type-checked)
    • Async safetyno-await-in-loop (warn), no-promise-executor-return, @typescript-eslint/return-await (type-checked)
    • Dead codeno-useless-rename/return/concat; @typescript-eslint/no-unnecessary-condition/type-arguments/template-expression (type-checked)
    • sonarjs — full sonarjs/recommended base with no-duplicate-string, no-commented-code, and todo-tag silenced; no-hardcoded-ip kept at warn
  • src/configs/index.ts: Adds recommendedStrict and recommendedStrictTypeChecked exports. No changes to existing configs.

  • src/index.ts: Adds configStrict() convenience helper (mirrors config() but spreads recommendedStrict).

  • README.md: Documents new configs, configStrict() helper, peer dep, and rule categories.

Usage:

// eslint.config.mjs
import azsdkEslint from "@azure/eslint-plugin-azure-sdk";

// Opt-in — existing packages are unaffected
export default [
  ...azsdkEslint.configs.recommendedStrictTypeChecked,
];

// Or via the convenience helper:
export default azsdkEslint.configStrict();

Are there test cases added in this PR? (If not, why?)

Yes — tests/configs/recommended-strict.spec.ts (Vitest). Covers:

  • recommendedStrictDelta({ typeChecked: false }): asserts presence of always-on rules and absence of type-checked-only rules
  • recommendedStrictDelta({ typeChecked: true }): asserts all type-checked rules are included
  • Plugin export checks: recommendedStrict and recommendedStrictTypeChecked are defined and non-empty
  • Regression sentinel: recommended rule values (curly: multi-line, no-param-reassign: warn/props:false) are unchanged after this PR

Provide a list of related PRs (if any)

None

Checklists

  • Added impacted package name to the issue description.
  • Does this PR need any fixes in the SDK Generator?** (If so, create an Issue in the Autorest/typescript repository and link it here.)
  • Added a changelog (if necessary).
Original prompt

Goal

Add a new opt-in recommendedStrict preset to @azure/eslint-plugin-azure-sdk that layers a curated set of additional maintainability and code-smell rules on top of the existing recommended preset. The intent is to give package authors (and reviewers of AI-generated code) a single switch they can flip to catch overly complex, redundant, dead, or hard-to-read code that AI agents commonly produce.

This preset must be purely additive and opt-in:

  • It must NOT change the behavior of azsdkEslint.configs.recommended, recommendedTypeChecked, internal, or the azsdkEslint.config() helper. Existing packages that don't opt in must see zero rule changes.
  • Existing recommended-type-checked callers must also be unaffected unless they explicitly opt in.

Scope of files in this PR

All work is inside common/tools/eslint-plugin-azure-sdk/. Do NOT modify any package's eslint.config.* file under sdk/** or any other consumer in this PR — adoption is a separate effort.

Required changes

1. Add eslint-plugin-sonarjs as a peer dependency

Edit common/tools/eslint-plugin-azure-sdk/package.json:

  • Add "eslint-plugin-sonarjs": "^3.0.2" (or the latest 3.x at install time that supports ESLint 9 flat config) under peerDependencies, alphabetically placed.
  • Add the same entry under devDependencies so the plugin's own build/lint step can resolve it.
  • Verify the version chosen exports configs.recommended as a flat-config object compatible with ESLint 9 and typescript-eslint 8.x. If 3.x has issues, fall back to ^2.0.4. Document whichever version you pick in the PR description.

2. Create a new file: src/configs/recommended-strict.ts

This file defines the strict-only delta — i.e. ONLY the rules that go beyond what recommended / recommendedTypeChecked already enable. It must export:

import type { FlatConfig } from "@typescript-eslint/utils/ts-eslint";

export function recommendedStrictDelta(options: { typeChecked: boolean }): FlatConfig.ConfigArray;

The delta should include the rules below. Group rules logically with comments. Use error severity unless noted; for highly noisy rules use warn and add a // TODO comment explaining the intent so we can promote later.

Structural caps (always on, no type info needed)

  • max-lines-per-function: ["error", { max: 100, skipBlankLines: true, skipComments: true, IIFEs: true }]
  • max-classes-per-file: ["error", 1]
  • max-params: "off" — disable core in favor of TS extension
  • @typescript-eslint/max-params: ["error", { max: 7, countVoidThis: false }]
  • sonarjs/cognitive-complexity: ["error", 15]

Anti-"clever one-liner" (always on)

  • no-nested-ternary: "error"
  • no-unneeded-ternary: "error"
  • no-implicit-coercion: "error"
  • no-lonely-if: "error"
  • no-else-return: ["error", { allowElseIf: false }]

Mutation / scoping (always on)

  • no-param-reassign: ["error", { props: true }] — note: existing eslint-customized.ts sets this to ["warn", { props: false }]; the strict preset must override it.
  • @typescript-eslint/no-shadow: ["error", { ignoreTypeValueShadow: true }] — already error in customized; keep consistent.
  • @typescript-eslint/prefer-readonly: "error" (type-checked only — see below)

Switch / control flow (always on)

  • curly: ["error", "all"] — note: existing eslint-customized.ts sets this to ["error", "multi-line"]; the strict preset must override it.
  • default-case: "error"
  • default-case-last: "error"
  • consistent-return: "off" — disable core in favor of TS extension
  • @typescript-eslint/consistent-return: "error" (type-checked only)
  • @typescript-eslint/switch-exhaustiveness-check: "error" (type-checked only)

Imports (always on)

  • no-duplicate-imports: "error"
  • @typescript-eslint/consistent-type-imports: "error" (existing customized has "warn"; strict promotes to error)
  • @typescript-eslint/no-import-type-side-effects: "error"
  • @typescript-eslint/no-deprecated: "error" (type-checked only)

Errors thrown / caught (always on)

  • no-empty: ["error", { allowEmptyCatch: false }]
  • @typescript-eslint/only-throw-error: "error" (type-checked only)
  • @typescript-eslint/use-unknown-in-catch-callback-variable: "error" (type-checked only)
  • @typescript-eslint/prefer-promise-reject-errors: "error" (type-checked only)

Async safety (type-checked only)

  • @typescript-eslint/return-await: ["error", "in-try-catch"]
  • no-await-in-loop: "warn" — TODO: promote after audit
  • no-promise-executor-return: "error"
  • require-atomic-updates: "error"

Dead / redundant code (type-checked only)

  • @typescript-eslint/no-unnecessary-condition: "error"
  • @typescript-eslint/no-unnecessary-type-arguments: "error"
  • @typescript-eslint/no-unnecessary-template-expression: "error"
  • no-useless-rename: "error"
  • no-useless-return: "error"
    -...

This pull request was created from Copilot chat.

Copilot AI and others added 2 commits May 4, 2026 17:50
- Add eslint-plugin-sonarjs ^3.0.2 as peer and dev dependency
- New src/configs/recommended-strict.ts with recommendedStrictDelta()
- New configs: recommendedStrict and recommendedStrictTypeChecked in index
- New configStrict() helper in src/index.ts
- Updated README.md with new preset documentation
- Added unit tests in tests/configs/recommended-strict.spec.ts

Agent-Logs-Url: https://github.com/Azure/azure-sdk-for-js/sessions/ecc2227a-f6b0-4267-8109-ac71ae35fdcd

Co-authored-by: jeremymeng <7583839+jeremymeng@users.noreply.github.com>
Copilot AI changed the title [WIP] Add recommendedStrict preset to eslint-plugin-azure-sdk feat(eslint-plugin-azure-sdk): add opt-in recommendedStrict preset with sonarjs integration May 4, 2026
Copilot AI requested a review from jeremymeng May 4, 2026 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants