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.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
SonarSource/SonarJS
آخر نشاط في المصدر
٨ سبتمبر ٢٠٢٦ في ١٢:٢٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٬٢٩٠
التفرعات
١٩٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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)
عرض على GitHub