Skip to content

Adding a New Lint Rule

How to add a new rule to the code-style linter.

Process

When the user identifies a new style rule to enforce:

  1. Capture examples from the user. Ask for or collect concrete good and bad code examples. These become the test fixtures.

  2. Create the rule folder. Each rule lives in its own directory under the appropriate language:

    lint/{language}/{rule-name}/
      {rule-name}.js              — the rule
      {rule-name}.test.js         — tests
      {rule-name}.test.good.{ext} — code that should pass
      {rule-name}.test.bad.{ext}  — code that should fail
  3. Write the test fixtures first. Put the user's good examples in {rule-name}.test.good.{ext} and bad examples in {rule-name}.test.bad.{ext}.

  4. Write the rule. Import Rule from the engine. For AST-based rules, use .on(nodeType, handler). For line-based rules, use .onLine(handler).

    js
    import { Rule } from "../../engine.js";
    
    const myRule = Rule();
    myRule.on("node_type", (node, { file, lines }) => {
      return [{ file, line: ..., content: ... }];
    });
    export default myRule;
  5. Write the test. Run the linter CLI against the good and bad fixtures. Assert the good file passes and the bad file fails with the expected violation count and line numbers.

  6. Register the rule. Add it to the language's index.js:

    js
    import myRule from "./my-rule/my-rule.js";
    javascript.use(myRule);

    For shared rules (tabs, line-length), put them in common/ and import from each language that needs them.

  7. Verify. Run all tests and lint the linter's own code:

    sh
    node --test skills/code-style/lint/**/*.test.js