Skip to main content

new-rule

Implement a new SonarJS rule from scratch. Use when creating a new rule, scaffolding rule files, or understanding the full rule implementation workflow.

Aller à l'installation

Informations de source

Dépôt
SonarSource/SonarJS
Dernière activité de la source
8 septembre 2026 à 12:22
Langue détectée de SKILL.md
anglais
Étoiles
1 296
Forks
193

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
new-rule
description
Implement a new SonarJS rule from scratch. Use when creating a new rule, scaffolding rule files, or understanding the full rule implementation workflow.
disable-model-invocation
true
## Overview New rules follow the pattern: RSPEC description → scaffold → implement → test → ruling. ## Step 1: Scaffold the Rule ```bash npm run new-rule ``` This interactive script generates in `packages/analysis/src/jsts/rules/SXXXX/`: - `index.ts` — rule export - `rule.ts` — ESLint rule implementation (skeleton) - `cb.fixture.js` — empty comment-based test fixture - `cb.test.js` — test launcher It also auto-generates (not tracked by git): - Java check class `SXXXX.java` - Updates `rules/rules.ts` and `rules/plugin-rules.ts` - Updates `AllRules.java` ## Step 2: Configure the Java Check Class In the generated Java class, verify: - `@JavaScriptRule` and/or `@TypeScriptRule` annotations match target languages - If rule has options, override `configurations()` method (see `/rule-options` skill) - If rule targets test files, extend `TestFileCheck` instead of `MainFileCheck` ## Step 3: Implement the Rule ### File Structure | File | Purpose | | ------------------- | ---------------------------------------------------------------------------- | | `rule.ts` | ESLint rule implementation | | `meta.ts` | Manual metadata: `implementation`, `eslintId`, `schema`, re-exports `fields` | | `config.ts` | Option definitions with `fields` array (if rule has options) | | `generated-meta.ts` | Auto-generated from RSPEC — do not edit | ### Rule Template ```typescript import { generateMeta } from '../helpers/index.js'; import { meta } from './meta.js'; const messages = { errorKey: 'Error message to display', }; export const rule: Rule.RuleModule = { meta: generateMeta(meta, { messages }), create(context: Rule.RuleContext) { return { Identifier(node: estree.Identifier) { if (/* violation detected */) { context.report({ messageId: 'errorKey', node }); } }, }; }, }; ``` ### Be Conservative **Never report when uncertain.** False positives are worse than missed detections. ```typescript const services = context.sourceCode.parserServices; if (!isRequiredParserServices(services)) { return; // No type info — don't report } ``` When in doubt: skip. ## Step 4: Check Shared Helpers **Before writing any utility code**, check `packages/analysis/src/jsts/rules/helpers/`: | File | Contains | | ------------------------------- | ------------------------------------------------------------------------- | | `ast.ts` | `isFunctionNode`, `isIdentifier`, `hasTypePredicateReturn`, AST traversal | | `module.ts` | `isESModule`, `getImportDeclarations`, `getFullyQualifiedName` | | `package-jsons/dependencies.ts` | `getDependencies`, `getReactVersion` | | `index.ts` | Re-exports all helpers — check here first | If a new utility would benefit multiple rules, add it to the appropriate helper file. ## Step 5: Generate Metadata After setting up `meta.ts` and optionally `config.ts`: ```bash npm run generate-meta ``` This creates/updates `generated-meta.ts` with `defaultOptions`, `sonarKey`, `scope`, `languages`. ## Step 6: Write Tests See `/test-rule` skill for full testing documentation. Quick start — write `cb.fixture.js`: ```javascript someCleanCode(); // no issue raised someFaultyCode(); // Noncompliant {{message}} // ^^^^^^^^^^ ``` Run: ```bash npx tsx --test packages/analysis/src/jsts/rules/S1234/**/*.test.ts ``` ## Step 7: Run Ruling See `/ruling` skill. Required before merging new or modified rules. ## Rule Implementation Patterns ### Wrapping an ESLint Rule (`decorated`) ```typescript // meta.ts export const implementation = 'decorated'; export const eslintId = 'no-magic-numbers'; export const externalRules = [ { externalPlugin: 'typescript-eslint', externalRule: 'no-magic-numbers' }, ]; export * from './config.js'; ``` ### Original Rule ```typescript // meta.ts export const implementation = 'original'; export const eslintId = 'function-name'; export * from './config.js'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; export const schema = { type: 'array', items: [{ type: 'object', properties: { format: { type: 'string' } } }], } as const satisfies JSONSchema4; ``` ### RSPEC Tags When creating the RSPEC PR: - Tag `type-dependent` if the rule uses TypeScript type information - Add `dependencies` field if rule requires a specific import (e.g., `'react'`, `'jest'`) - Add `compatibleLanguages: ['js', 'ts']` as appropriate ## References - Security Hotspot: [PR #3148](https://github.com/SonarSource/SonarJS/pull/3148) - Rule with quickfix: [PR #3141](https://github.com/SonarSource/SonarJS/pull/3141) - Wrapping ESLint rule: [PR #3134](https://github.com/SonarSource/SonarJS/pull/3134)
Voir sur GitHub