lint-new

作者: sentry

為 eslintPluginScraps 建立一個新的 ESLint 規則並附帶測試。當被要求「建立 lint 規則」、「新增 eslint 規則」、「搭建規則」、「撰寫新…」時使用。

npx skills add https://github.com/getsentry/sentry --skill lint-new

Create a new ESLint rule named $ARGUMENTS in the eslintPluginScraps plugin.

Step 1: Choose Your Archetype

Read references/rule-archetypes.md and pick the archetype that matches your rule's intent:

You want to...ArchetypeReference to load
Rewrite import pathsImport rewriteInline — simple pattern
Validate token/value usage per CSS propertyProperty validationstyle-collector-guide.md
Restrict JSX elements in specific propsJSX structuralrule-archetypes.md §Archetype 3
Detect patterns in static CSS textTemplate text analysisrule-archetypes.md §Archetype 4

Read the relevant reference before writing code. The archetypes document which AST visitors to use, which shared utilities apply, and which patterns are NOT appropriate for each approach.

Step 2: Check Shared Utilities

Before writing AST traversal logic, check static/eslint/eslintPluginScraps/src/ast/ for reusable code:

UtilityLocationUse for
getStyledCallInfosrc/ast/utils/styled.tsClassifying styled/css calls as element, component, or css
createQuasiScannersrc/ast/scanner/index.tsScanning static CSS text in template literals (Archetype 4)
createImportTrackersrc/ast/tracker/imports.tsResolving where a local name was imported from
createStyleCollectorsrc/ast/extractor/index.tsCollecting CSS-in-JS dynamic value declarations (NOT static text)
shouldAnalyzesrc/ast/extractor/index.tsFast pre-scan to skip files without Emotion usage
normalizePropertyNamesrc/ast/utils/normalizePropertyName.tsNormalizing CSS property names
decomposeValuesrc/ast/extractor/value-decomposer.tsBreaking complex expressions into all possible values
Theme trackersrc/ast/tracker/theme.tsTracking useTheme() and callback theme bindings

If another rule already solves a similar problem, extract shared logic into src/ast/utils/ and reuse it.

Step 3: Create Files

  1. Rule: static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.ts
  2. Test: static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts

Rule Template

import {ESLintUtils} from '@typescript-eslint/utils';

export const $RULE_NAME = ESLintUtils.RuleCreator.withoutDocs({
  meta: {
    type: 'problem',
    docs: {
      description: '[Rule description]',
    },
    fixable: 'code', // include if rule has autofix — see Autofix Guidance
    schema: [],
    messages: {
      forbidden: 'Error message shown to user',
    },
  },
  create(context) {
    return {
      // AST visitor methods — see your chosen archetype
    };
  },
});

If your rule needs configurable options, load references/schema-patterns.md.

Test Template

import {RuleTester} from '@typescript-eslint/rule-tester';

import {$RULE_NAME} from './$ARGUMENTS';

const ruleTester = new RuleTester();

ruleTester.run('$ARGUMENTS', $RULE_NAME, {
  valid: [
    {
      code: '// valid code',
      filename: '/project/src/file.tsx',
    },
  ],
  invalid: [
    {
      code: '// invalid code',
      filename: '/project/src/file.tsx',
      errors: [{messageId: 'forbidden'}],
      output: '// expected output after autofix', // REQUIRED for fixable rules
    },
  ],
});

Run tests:

pnpm test-ci "static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"

Autofix Guidance

Default stance: implement autofix unless the transformation is ambiguous or could change runtime behavior.

Safe autofix patterns

  • Import path rewrites (see no-core-import.ts as canonical example)
  • Adding/removing JSX attributes with known values
  • Wrapping expressions in a known component
  • Identifier renames with no shadowing risk

Do NOT autofix when

  • Multiple valid fixes exist and the right choice requires human judgment
  • The fix requires type information not available from the AST alone
  • The transformation alters control flow or runtime behavior
  • The change spans multiple files

Fixer API

context.report({
  node,
  messageId: 'forbidden',
  fix(fixer) {
    return fixer.replaceText(node, newText);
    // Also: fixer.replaceTextRange([start, end], text)
    //        fixer.insertTextBefore(node, text)
    //        fixer.insertTextAfter(node, text)
    //        fixer.remove(node)
    // Return single fix or array of fixes
  },
});

When a rule is fixable, every invalid test case MUST include output showing the expected code after the fix.

Step 4: Register the Rule

1. Rule Index

Add to static/eslint/eslintPluginScraps/src/rules/index.ts:

import {$RULE_NAME} from './$ARGUMENTS';

export const rules = {
  // existing rules...
  $ARGUMENTS: $RULE_NAME,
};

2. ESLint Config

Add to eslint.config.ts inside the name: 'plugin/@sentry/scraps' block:

'@sentry/scraps/$ARGUMENTS': 'error',
// or with options:
'@sentry/scraps/$ARGUMENTS': ['error', { /* options */ }],

3. Verify

pnpm test-ci "static/eslint/eslintPluginScraps/src/rules/$ARGUMENTS.spec.ts"

Extending an Existing Rule

If modifying an existing rule rather than creating a new one:

  1. Read the existing rule and its config files to understand the architecture
  2. For config-driven rules (like use-semantic-token): changes often only require editing the config file (e.g., src/config/tokenRules.ts), not the rule logic
  3. Watch for reverse-mapping side effects — adding a new category can change which category is suggested for shared properties (last writer wins in buildPropertyToRule)
  4. Update existing tests for any changed behavior, then add new test cases

Naming Convention

  • Rule name (kebab-case): my-rule-name — verb-noun pattern (e.g., no-token-import, use-semantic-token)
  • Export name (camelCase): myRuleName
  • File name: matches rule name exactly (my-rule-name.ts, my-rule-name.spec.ts)

來自 sentry 的更多技能

generate-frontend-forms
sentry
使用 Sentry 新表單系統建立表單的指南。適用於實作表單、表單欄位、驗證或自動儲存功能時使用。
official
sentry-snapshots-cocoa
sentry
完整的 Sentry Snapshots 設定,適用於 Apple/Cocoa 專案。當被要求「設定 SnapshotPreviews」、「設定 Apple 快照測試」、「上傳 Apple 快照至…」時使用。
official
architecture-review
sentry
員工級別的程式碼庫健康檢查。找出單體模組、靜默失敗、型別安全漏洞、測試覆蓋缺口,以及LLM友善性問題。
official
linear-type-labeler
sentry
根據每個問題的標題與描述內容,從 Sentry 工作區的標籤分類法中分類 Linear 問題,並套用對應的類型標籤。
official
sentry-flutter-sdk
sentry
完整的 Sentry SDK 設定,適用於 Flutter 和 Dart。當被要求「為 Flutter 加入 Sentry」、「安裝 sentry_flutter」、「在 Dart 中設定 Sentry」或設定錯誤…時使用。
official
sentry-svelte-sdk
sentry
完整的 Sentry SDK 設定,適用於 Svelte 和 SvelteKit。當被要求「將 Sentry 加入 Svelte」、「將 Sentry 加入 SvelteKit」、「安裝 @sentry/sveltekit」或進行設定時使用…
official
vercel-react-best-practices
sentry
來自 Vercel Engineering 的 React 與 Next.js 效能優化指南。此技能應在撰寫、審查或重構 React/Next.js… 時使用。
official
sentry-tanstack-start-sdk
sentry
完整的 Sentry SDK 設定,適用於 TanStack Start React。當被要求「將 Sentry 加入 TanStack Start」、「安裝 @sentry/tanstackstart-react」或設定錯誤…時使用。
official