130 lines
3.6 KiB
TypeScript
130 lines
3.6 KiB
TypeScript
import rule from "@effect/oxc/oxlint/rules/no-unused-internal"
|
|
import * as fs from "node:fs"
|
|
import * as os from "node:os"
|
|
import * as path from "node:path"
|
|
import { describe, expect, it } from "vitest"
|
|
import { createTestContext } from "./utils.ts"
|
|
|
|
function writeFixture(files: Record<string, string>): string {
|
|
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "no-unused-internal-rule-"))
|
|
for (const [file, source] of Object.entries(files)) {
|
|
const fileName = path.join(cwd, file)
|
|
fs.mkdirSync(path.dirname(fileName), { recursive: true })
|
|
fs.writeFileSync(fileName, source)
|
|
}
|
|
return cwd
|
|
}
|
|
|
|
function run(cwd: string, file: string) {
|
|
const filename = path.join(cwd, file)
|
|
const source = fs.readFileSync(filename, "utf8")
|
|
const { context, errors } = createTestContext({ sourceCode: source, cwd, filename })
|
|
const visitors = rule.create(context as never)
|
|
visitors.Program?.({ type: "Program", range: [0, source.length] } as never)
|
|
return errors.map((error) => error.message)
|
|
}
|
|
|
|
describe("no-unused-internal", () => {
|
|
it("reports unused top-level @internal exports", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export const unused = 1
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([
|
|
`@internal export "unused" is not used by production sources`
|
|
])
|
|
})
|
|
|
|
it("counts same-file references as usage", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export const used = 1
|
|
|
|
export const value = used
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([])
|
|
})
|
|
|
|
it("counts type-only references as usage", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export interface Internal {
|
|
readonly value: string
|
|
}
|
|
`,
|
|
"packages/foo/src/Consumer.ts": `import type { Internal } from "./Internal.ts"
|
|
|
|
type Local = Internal
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([])
|
|
})
|
|
|
|
it("reports @internal exports used in public exported type signatures", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export interface Internal {
|
|
readonly value: string
|
|
}
|
|
`,
|
|
"packages/foo/src/Public.ts": `import type { Internal } from "./Internal.ts"
|
|
|
|
export interface Public {
|
|
readonly value: Internal
|
|
}
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/Public.ts")).toEqual([
|
|
`Do not reference @internal export "Internal" in a public exported type signature`
|
|
])
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([])
|
|
})
|
|
|
|
it("ignores @internal class member type signatures", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export interface Internal {
|
|
readonly value: string
|
|
}
|
|
`,
|
|
"packages/foo/src/Public.ts": `import type { Internal } from "./Internal.ts"
|
|
|
|
export class Public {
|
|
/** @internal */
|
|
getInternal(): Internal {
|
|
throw new Error("not implemented")
|
|
}
|
|
}
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/Public.ts")).toEqual([])
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([])
|
|
})
|
|
|
|
it("ignores public type signatures in internal directories", () => {
|
|
const cwd = writeFixture({
|
|
"packages/foo/src/Internal.ts": `/** @internal */
|
|
export interface Internal {
|
|
readonly value: string
|
|
}
|
|
`,
|
|
"packages/foo/src/internal/Consumer.ts": `import type { Internal } from "../Internal.ts"
|
|
|
|
export interface PublicInsideInternalDirectory {
|
|
readonly value: Internal
|
|
}
|
|
`
|
|
})
|
|
|
|
expect(run(cwd, "packages/foo/src/internal/Consumer.ts")).toEqual([])
|
|
expect(run(cwd, "packages/foo/src/Internal.ts")).toEqual([])
|
|
})
|
|
})
|