diff --git a/skills/adamantite/SKILL.md b/skills/adamantite/SKILL.md index 57c5042e..5f990753 100644 --- a/skills/adamantite/SKILL.md +++ b/skills/adamantite/SKILL.md @@ -9,6 +9,7 @@ sources: - "adelrodriguez/adamantite:src/cli.ts" - "adelrodriguez/adamantite:src/commands/*.ts" - "adelrodriguez/adamantite:src/lib/workspace/custom-rules/index.ts" + - "adelrodriguez/adamantite:src/lib/workspace/custom-rules/stub.ts.template" --- # Adamantite diff --git a/src/__tests__/presets/custom.test.ts b/src/__tests__/presets/custom.test.ts index 575a89aa..77d2bbf4 100644 --- a/src/__tests__/presets/custom.test.ts +++ b/src/__tests__/presets/custom.test.ts @@ -6,6 +6,7 @@ import { afterEach, beforeEach, describe, expect, it } from "@effect/vitest" import * as EffectArray from "effect/Array" import * as Order from "effect/Order" import * as Schema from "effect/Schema" +import { toCustomRuleStub } from "#lib/workspace/custom-rules/index.ts" const REPO_ROOT = join(import.meta.dirname, "../../..") const CUSTOM_PRESET = join(REPO_ROOT, "presets/lint/custom.ts") @@ -107,6 +108,19 @@ describe("custom preset", () => { expect(lint("src")).toStrictEqual(["project(no-debugger-here):error"]) }) + it("load and run the stub that rule add writes", () => { + write( + ".adamantite/rules/no-debugger-here.ts", + toCustomRuleStub("no-debugger-here").replace( + '"adamantite/rules"', + JSON.stringify(RULES_MODULE) + ) + ) + write("oxlint.config.ts", makeConfig("custom()")) + + expect(lint("src")).toStrictEqual(["project(no-debugger-here):error"]) + }) + it("apply severity overrides from the rules option", () => { write(".adamantite/rules/no-debugger-here.ts", makeRule("No debugger here.")) write("oxlint.config.ts", makeConfig('custom({ rules: { "no-debugger-here": "warn" } })')) diff --git a/src/lib/workspace/custom-rules/index.ts b/src/lib/workspace/custom-rules/index.ts index e4d4d82e..34eb65f8 100644 --- a/src/lib/workspace/custom-rules/index.ts +++ b/src/lib/workspace/custom-rules/index.ts @@ -3,6 +3,9 @@ import * as FileSystem from "effect/FileSystem" import * as Path from "effect/Path" import { CustomRuleExists, FailedToReadFile, InvalidRuleName } from "#lib/shared/errors.ts" import { ensureDirectory, writeFile } from "#lib/shared/filesystem.ts" +import { getStubTemplate } from "#lib/workspace/custom-rules/stub.macro.ts" with { type: "macro" } + +const stubTemplate = getStubTemplate() /** * The rules folder that `custom()` loads when no `dir` is given, relative to the file that calls @@ -16,25 +19,7 @@ const RULE_NAME_PATTERN = /^[a-z][\da-z]*(?:-[\da-z]+)*$/ * The stub that `adamantite rule add` writes: a working rule that the author replaces. */ export function toCustomRuleStub(name: string): string { - return `import { defineRule } from "adamantite/rules" - -export default defineRule({ - meta: { - docs: { description: "TODO: describe what ${name} reports." }, - messages: { unexpected: "TODO: tell the author what to do instead." }, - schema: [], - type: "problem", - }, - createOnce(context) { - return { - // Run \`adamantite rule ast \` to find the node types to visit. - DebuggerStatement(node) { - context.report({ messageId: "unexpected", node }) - }, - } - }, -}) -` + return stubTemplate.replaceAll("{{name}}", name) } /** diff --git a/src/lib/workspace/custom-rules/stub.macro.ts b/src/lib/workspace/custom-rules/stub.macro.ts new file mode 100644 index 00000000..db6eb76a --- /dev/null +++ b/src/lib/workspace/custom-rules/stub.macro.ts @@ -0,0 +1,9 @@ +import { readFileSync } from "node:fs" + +/** + * Build-time macro that inlines `stub.ts.template` into the bundle, so `rule add` never reads the + * template from disk at run time. + */ +export function getStubTemplate(): string { + return readFileSync(new URL("stub.ts.template", import.meta.url), "utf8") +} diff --git a/src/lib/workspace/custom-rules/stub.ts.template b/src/lib/workspace/custom-rules/stub.ts.template new file mode 100644 index 00000000..4f02b5d9 --- /dev/null +++ b/src/lib/workspace/custom-rules/stub.ts.template @@ -0,0 +1,18 @@ +import { defineRule } from "adamantite/rules" + +export default defineRule({ + meta: { + docs: { description: "TODO: describe what {{name}} reports." }, + messages: { unexpected: "TODO: tell the author what to do instead." }, + schema: [], + type: "problem", + }, + createOnce(context) { + return { + // Run `adamantite rule ast ` to find the node types to visit. + DebuggerStatement(node) { + context.report({ messageId: "unexpected", node }) + }, + } + }, +})