From 32d1cf60aa678c3f69782b9a345d3ba7443fe52a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 21 Mar 2023 15:30:35 -0700 Subject: [PATCH 1/2] Port no-declare-current-package tslint->eslint --- packages/dtslint/dt.json | 1 - .../src/rules/no-declare-current-package.ts | 43 +++++++++++++++++++ .../src/rules/noDeclareCurrentPackageRule.ts | 43 ------------------- .../test/no-declare-current-package.test.ts | 41 ++++++++++++++++++ packages/utils/src/collections.ts | 13 ++---- 5 files changed, 87 insertions(+), 54 deletions(-) create mode 100644 packages/dtslint/src/rules/no-declare-current-package.ts delete mode 100644 packages/dtslint/src/rules/noDeclareCurrentPackageRule.ts create mode 100644 packages/dtslint/test/no-declare-current-package.test.ts diff --git a/packages/dtslint/dt.json b/packages/dtslint/dt.json index 8847d63935..0ce708cb1a 100644 --- a/packages/dtslint/dt.json +++ b/packages/dtslint/dt.json @@ -1,7 +1,6 @@ { "extends": "./dtslint.json", "rules": { - "no-declare-current-package": true, "no-self-import": true, "no-outside-dependencies": true, diff --git a/packages/dtslint/src/rules/no-declare-current-package.ts b/packages/dtslint/src/rules/no-declare-current-package.ts new file mode 100644 index 0000000000..2df2daca0d --- /dev/null +++ b/packages/dtslint/src/rules/no-declare-current-package.ts @@ -0,0 +1,43 @@ +import { getCommonDirectoryName, createRule } from "../util"; +import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils"; + +const rule = createRule({ + name: "no-declare-current-package", + defaultOptions: [], + meta: { + type: "problem", + docs: { + description: "Don't use an ambient module declaration of the current package; use a normal module.", + recommended: "error", + }, + messages: { + noDeclareCurrentPackage: `Instead of declaring a module with \`declare module "{{ text }}"\`, ` + + `write its contents in directly in {{ preferred }}.`, + }, + schema: [], + }, + create(context) { + if (!context.getFilename().endsWith(".d.ts")) { + return {} + } + const parserServices = ESLintUtils.getParserServices(context); + const packageName = getCommonDirectoryName(parserServices.program.getRootFileNames()); + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + TSModuleDeclaration(node) { + if (node.id.type === AST_NODE_TYPES.Literal + && (node.id.value === packageName || node.id.value.startsWith(packageName + "/"))) { + const text = node.id.value; + const preferred = text === packageName ? '"index.d.ts"' : `"${text}.d.ts" or "${text}/index.d.ts`; + context.report({ + messageId: "noDeclareCurrentPackage", + data: { text, preferred }, + node, + }); + } + }, + }; + }, +}); + +export = rule; diff --git a/packages/dtslint/src/rules/noDeclareCurrentPackageRule.ts b/packages/dtslint/src/rules/noDeclareCurrentPackageRule.ts deleted file mode 100644 index 91c99e2e4a..0000000000 --- a/packages/dtslint/src/rules/noDeclareCurrentPackageRule.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as Lint from "tslint"; -import * as ts from "typescript"; - -import { failure, getCommonDirectoryName } from "../util"; - -export class Rule extends Lint.Rules.TypedRule { - static metadata: Lint.IRuleMetadata = { - ruleName: "no-declare-current-package", - description: "Don't use an ambient module declaration of the current package; use a normal module.", - optionsDescription: "Not configurable.", - options: null, - type: "functionality", - typescriptOnly: true, - }; - - applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { - if (!sourceFile.isDeclarationFile) { - return []; - } - - const packageName = getCommonDirectoryName(program.getRootFileNames()); - return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, packageName)); - } -} - -function walk(ctx: Lint.WalkContext, packageName: string): void { - for (const statement of ctx.sourceFile.statements) { - if (ts.isModuleDeclaration(statement) && ts.isStringLiteral(statement.name)) { - const { text } = statement.name; - if (text === packageName || text.startsWith(`${packageName}/`)) { - const preferred = text === packageName ? '"index.d.ts"' : `"${text}.d.ts" or "${text}/index.d.ts`; - ctx.addFailureAtNode( - statement.name, - failure( - Rule.metadata.ruleName, - `Instead of declaring a module with \`declare module "${text}"\`, ` + - `write its contents in directly in ${preferred}.` - ) - ); - } - } - } -} diff --git a/packages/dtslint/test/no-declare-current-package.test.ts b/packages/dtslint/test/no-declare-current-package.test.ts new file mode 100644 index 0000000000..e397067542 --- /dev/null +++ b/packages/dtslint/test/no-declare-current-package.test.ts @@ -0,0 +1,41 @@ +import { ESLintUtils } from "@typescript-eslint/utils"; + +import * as noDeclareCurrentPackage from "../src/rules/no-declare-current-package"; + +const ruleTester = new ESLintUtils.RuleTester({ + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 2018, + tsconfigRootDir: __dirname, + project: "./tsconfig.json", + } +}); + +ruleTester.run("no-declare-current-package", noDeclareCurrentPackage, { + invalid: [ + { + + code: `module "test" { }`, + errors: [ + { + line: 1, + messageId: "noDeclareCurrentPackage", + }, + ], + }, + { + + code: `module "test/deep/import" { }`, + errors: [ + { + line: 1, + messageId: "noDeclareCurrentPackage", + }, + ], + }, + ], + valid: [` +module "foo" { } +module "foo/bar/baz" { } +`], +}); diff --git a/packages/utils/src/collections.ts b/packages/utils/src/collections.ts index b1379452a2..14cc0b8cad 100644 --- a/packages/utils/src/collections.ts +++ b/packages/utils/src/collections.ts @@ -148,26 +148,19 @@ export function isArray(value: any): value is readonly {}[] { } /** - * Maps an array. If the mapped value is an array, it is spread into the result. + * Maps an array. The mapped value is spread into the result. * * @param array The array to map. * @param mapfn The callback used to map the result into one or more values. */ export function flatMap( array: readonly T[] | undefined, - mapfn: (x: T, i: number) => U | readonly U[] | undefined + mapfn: (x: T, i: number) => readonly U[] ): readonly U[] { let result: U[] | undefined; if (array) { for (let i = 0; i < array.length; i++) { - const v = mapfn(array[i], i); - if (v) { - if (isArray(v)) { - result = addRange(result, v); - } else { - result = append(result, v); - } - } + result = addRange(result, mapfn(array[i], i)); } } return result || []; From 35063f451eca6cac29c03994885bc633b3ff734a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 22 Mar 2023 10:51:20 -0700 Subject: [PATCH 2/2] Fix no-declare-current-packages tests --- .../src/rules/no-declare-current-package.ts | 1 - .../test/no-declare-current-package.test.ts | 30 +++++++++++++++---- packages/dtslint/test/tsconfig.json | 4 ++- .../tsconfig.no-declare-current-package.json | 11 +++++++ .../tsconfig.no-declare-current-package2.json | 11 +++++++ 5 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 packages/dtslint/test/tsconfig.no-declare-current-package.json create mode 100644 packages/dtslint/test/tsconfig.no-declare-current-package2.json diff --git a/packages/dtslint/src/rules/no-declare-current-package.ts b/packages/dtslint/src/rules/no-declare-current-package.ts index 2df2daca0d..a361182404 100644 --- a/packages/dtslint/src/rules/no-declare-current-package.ts +++ b/packages/dtslint/src/rules/no-declare-current-package.ts @@ -1,6 +1,5 @@ import { getCommonDirectoryName, createRule } from "../util"; import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils"; - const rule = createRule({ name: "no-declare-current-package", defaultOptions: [], diff --git a/packages/dtslint/test/no-declare-current-package.test.ts b/packages/dtslint/test/no-declare-current-package.test.ts index e397067542..5e33e83070 100644 --- a/packages/dtslint/test/no-declare-current-package.test.ts +++ b/packages/dtslint/test/no-declare-current-package.test.ts @@ -7,14 +7,14 @@ const ruleTester = new ESLintUtils.RuleTester({ parserOptions: { ecmaVersion: 2018, tsconfigRootDir: __dirname, - project: "./tsconfig.json", + project: "./tsconfig.no-declare-current-package.json", } }); ruleTester.run("no-declare-current-package", noDeclareCurrentPackage, { invalid: [ { - + filename: "index.d.ts", code: `module "test" { }`, errors: [ { @@ -23,8 +23,29 @@ ruleTester.run("no-declare-current-package", noDeclareCurrentPackage, { }, ], }, + ], + valid: [ { + filename: "index.d.ts", + code: `module "foo" { } +module "foo/bar/baz" { } +`} + ], +}); +// needed because you can only test one non-file.ts file per tsconfig +// (and tsconfig is required for typed-based rules) +const ruleTester2 = new ESLintUtils.RuleTester({ + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: 2018, + tsconfigRootDir: __dirname, + project: "./tsconfig.no-declare-current-package2.json", + } +}); +ruleTester2.run("no-declare-current-package", noDeclareCurrentPackage, { + invalid: [{ + filename: "deep/import.d.ts", code: `module "test/deep/import" { }`, errors: [ { @@ -34,8 +55,5 @@ ruleTester.run("no-declare-current-package", noDeclareCurrentPackage, { ], }, ], - valid: [` -module "foo" { } -module "foo/bar/baz" { } -`], + valid: [], }); diff --git a/packages/dtslint/test/tsconfig.json b/packages/dtslint/test/tsconfig.json index e5619d0a39..fa9a18a276 100644 --- a/packages/dtslint/test/tsconfig.json +++ b/packages/dtslint/test/tsconfig.json @@ -4,5 +4,7 @@ "strict": true, "target": "esnext" }, - "files": ["file.ts"] + "files": [ + "file.ts" + ] } diff --git a/packages/dtslint/test/tsconfig.no-declare-current-package.json b/packages/dtslint/test/tsconfig.no-declare-current-package.json new file mode 100644 index 0000000000..d4462f426c --- /dev/null +++ b/packages/dtslint/test/tsconfig.no-declare-current-package.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "skipLibCheck": true, + "strict": true, + "target": "esnext" + }, + "files": [ + "index.d.ts", + "deep/import.d.ts" + ] +} diff --git a/packages/dtslint/test/tsconfig.no-declare-current-package2.json b/packages/dtslint/test/tsconfig.no-declare-current-package2.json new file mode 100644 index 0000000000..70c55a8165 --- /dev/null +++ b/packages/dtslint/test/tsconfig.no-declare-current-package2.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "skipLibCheck": true, + "strict": true, + "target": "esnext" + }, + "files": [ + "file.ts", + "deep/import.d.ts" + ] +}