From 3a15413d87a3429ebf19af2cc5db76c9e7ffe4e7 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Tue, 24 Dec 2019 10:59:30 +1030 Subject: [PATCH] feat: add internal eslint plugin for repo-specific lint rules (#1373) There's a few things I want to enforce internally. Save us from having to communicate these things in PR reviews. ensuring people don't do import ts from 'typescript' in packages. this breaks compat with users that don't use allowSyntheticDefaultImports ensuring people don't accidentally do import {} from '@typescript-eslint/typescript-estree' from the plugins, where the package isn't a dependency. this breaks encapsulation, and will cause problems if we move things around in future Adding this in now reduces the barrier to entry, meaning we can easily add rules to warn against patterns we see people do in the future. --- .eslintrc.js | 24 ++++-- .vscode/launch.json | 16 ++++ packages/eslint-plugin-internal/README.md | 5 ++ .../eslint-plugin-internal/jest.config.js | 13 +++ packages/eslint-plugin-internal/package.json | 18 +++++ packages/eslint-plugin-internal/src/index.ts | 5 ++ .../eslint-plugin-internal/src/rules/index.ts | 7 ++ .../src/rules/no-typescript-default-import.ts | 80 +++++++++++++++++++ .../src/rules/no-typescript-estree-import.ts | 52 ++++++++++++ .../src/util/createRule.ts | 11 +++ .../eslint-plugin-internal/src/util/index.ts | 1 + .../tests/RuleTester.ts | 22 +++++ .../no-typescript-default-import.test.ts | 45 +++++++++++ .../tests/rules/no-typescript-estree.test.ts | 43 ++++++++++ .../tsconfig.build.json | 13 +++ packages/eslint-plugin-internal/tsconfig.json | 8 ++ .../eslint-plugin/src/rules/await-thenable.ts | 2 +- .../src/rules/no-for-in-array.ts | 2 +- .../src/rules/no-misused-promises.ts | 2 +- .../src/rules/no-unnecessary-condition.ts | 12 +-- .../src/rules/no-unnecessary-qualifier.ts | 2 +- .../rules/no-unnecessary-type-arguments.ts | 2 +- .../rules/no-unnecessary-type-assertion.ts | 2 +- .../src/rules/no-unused-vars-experimental.ts | 2 +- .../src/rules/prefer-includes.ts | 2 +- .../src/rules/prefer-nullish-coalescing.ts | 2 +- .../src/rules/prefer-readonly.ts | 2 +- .../src/rules/require-array-sort-compare.ts | 2 +- .../eslint-plugin/src/rules/require-await.ts | 2 +- .../src/rules/restrict-plus-operands.ts | 2 +- .../rules/restrict-template-expressions.ts | 2 +- .../eslint-plugin/src/rules/return-await.ts | 4 +- .../src/rules/strict-boolean-expressions.ts | 2 +- .../eslint-plugin/src/rules/unbound-method.ts | 2 +- packages/eslint-plugin/src/util/types.ts | 2 +- packages/experimental-utils/package.json | 1 - .../typescript-estree/src/convert-comments.ts | 2 +- packages/typescript-estree/src/convert.ts | 2 +- .../WatchCompilerHostOfConfigFile.ts | 2 +- .../create-program/createDefaultProgram.ts | 2 +- .../create-program/createIsolatedProgram.ts | 2 +- .../src/create-program/createSourceFile.ts | 2 +- .../src/create-program/createWatchProgram.ts | 2 +- .../src/create-program/shared.ts | 2 +- packages/typescript-estree/src/node-utils.ts | 2 +- packages/typescript-estree/src/parser.ts | 2 +- .../src/semantic-or-syntactic-errors.ts | 2 +- .../src/ts-estree/ts-nodes.ts | 2 +- .../typescript-estree/tests/lib/convert.ts | 2 +- .../tests/lib/semanticInfo.ts | 2 +- yarn.lock | 6 +- 51 files changed, 401 insertions(+), 47 deletions(-) create mode 100644 packages/eslint-plugin-internal/README.md create mode 100644 packages/eslint-plugin-internal/jest.config.js create mode 100644 packages/eslint-plugin-internal/package.json create mode 100644 packages/eslint-plugin-internal/src/index.ts create mode 100644 packages/eslint-plugin-internal/src/rules/index.ts create mode 100644 packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts create mode 100644 packages/eslint-plugin-internal/src/rules/no-typescript-estree-import.ts create mode 100644 packages/eslint-plugin-internal/src/util/createRule.ts create mode 100644 packages/eslint-plugin-internal/src/util/index.ts create mode 100644 packages/eslint-plugin-internal/tests/RuleTester.ts create mode 100644 packages/eslint-plugin-internal/tests/rules/no-typescript-default-import.test.ts create mode 100644 packages/eslint-plugin-internal/tests/rules/no-typescript-estree.test.ts create mode 100644 packages/eslint-plugin-internal/tsconfig.build.json create mode 100644 packages/eslint-plugin-internal/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index f505a7f012e..4aa35ae4305 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,6 +6,7 @@ module.exports = { 'jest', 'import', 'eslint-comments', + '@typescript-eslint/internal', ], env: { es6: true, @@ -117,6 +118,11 @@ module.exports = { 'import/no-self-import': 'error', // Require modules with a single export to use a default export 'import/prefer-default-export': 'off', // we want everything to be named + + // + // Internal repo rules + // + '@typescript-eslint/internal/no-typescript-default-import': 'error', }, parserOptions: { sourceType: 'module', @@ -127,8 +133,10 @@ module.exports = { tsconfigRootDir: __dirname, }, overrides: [ + // all test files { files: [ + 'packages/eslint-plugin-internal/tests/**/*.test.ts', 'packages/eslint-plugin-tslint/tests/**/*.ts', 'packages/eslint-plugin/tests/**/*.test.ts', 'packages/parser/tests/**/*.ts', @@ -138,6 +146,7 @@ module.exports = { 'jest/globals': true, }, rules: { + 'eslint-plugin/no-identical-tests': 'error', 'jest/no-disabled-tests': 'warn', 'jest/no-focused-tests': 'error', 'jest/no-alias-methods': 'error', @@ -152,26 +161,31 @@ module.exports = { 'jest/valid-expect': 'error', }, }, + // plugin source files { files: [ - 'packages/eslint-plugin/tests/**/*.test.ts', - 'packages/eslint-plugin-tslint/tests/**/*.spec.ts', + 'packages/eslint-plugin-internal/**/*.ts', + 'packages/eslint-plugin-tslint/**/*.ts', + 'packages/eslint-plugin/**/*.ts', ], rules: { - 'eslint-plugin/no-identical-tests': 'error', + '@typescript-eslint/internal/no-typescript-estree-import': 'error', }, }, + // rule source files { files: [ - 'packages/eslint-plugin/src/rules/**/*.ts', - 'packages/eslint-plugin/src/configs/**/*.ts', + 'packages/eslint-plugin-internal/src/rules/**/*.ts', 'packages/eslint-plugin-tslint/src/rules/**/*.ts', + 'packages/eslint-plugin/src/configs/**/*.ts', + 'packages/eslint-plugin/src/rules/**/*.ts', ], rules: { // specifically for rules - default exports makes the tooling easier 'import/no-default-export': 'off', }, }, + // tools and tests { files: ['**/tools/**/*.ts', '**/tests/**/*.ts'], rules: { diff --git a/.vscode/launch.json b/.vscode/launch.json index 6552aae6613..9f1633f32ab 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,6 +20,22 @@ "console": "integratedTerminal", "internalConsoleOptions": "neverOpen" }, + { + "type": "node", + "request": "launch", + "name": "Jest Test Current eslint-plugin-internal Rule", + "cwd": "${workspaceFolder}/packages/eslint-plugin-internal/", + "program": "${workspaceFolder}/node_modules/jest/bin/jest.js", + "args": [ + "--runInBand", + "--no-coverage", + // needs the '' around it so that the () are properly handled + "'tests/(.+/)?${fileBasenameNoExtension}'" + ], + "sourceMaps": true, + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + }, { "type": "node", "request": "launch", diff --git a/packages/eslint-plugin-internal/README.md b/packages/eslint-plugin-internal/README.md new file mode 100644 index 00000000000..bf6ed0bbe38 --- /dev/null +++ b/packages/eslint-plugin-internal/README.md @@ -0,0 +1,5 @@ +# `eslint-plugin-internal` + +This is just a collection of internal lint rules to help enforce some guidelines specific to this repository. + +These are not intended to be used externally. diff --git a/packages/eslint-plugin-internal/jest.config.js b/packages/eslint-plugin-internal/jest.config.js new file mode 100644 index 00000000000..b64d433b01a --- /dev/null +++ b/packages/eslint-plugin-internal/jest.config.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, + testRegex: './tests/.+\\.test\\.ts$', + collectCoverage: false, + collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + coverageReporters: ['text-summary', 'lcov'], +}; diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json new file mode 100644 index 00000000000..d8c69d15f6f --- /dev/null +++ b/packages/eslint-plugin-internal/package.json @@ -0,0 +1,18 @@ +{ + "name": "@typescript-eslint/eslint-plugin-internal", + "version": "2.13.0", + "private": true, + "main": "dist/index.js", + "scripts": { + "build": "tsc -b tsconfig.build.json", + "clean": "tsc -b tsconfig.build.json --clean", + "format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore", + "lint": "eslint . --ext .js,.ts --ignore-path='../../.eslintignore'", + "test": "jest --coverage", + "typecheck": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@typescript-eslint/experimental-utils": "2.13.0" + }, + "devDependencies": {} +} diff --git a/packages/eslint-plugin-internal/src/index.ts b/packages/eslint-plugin-internal/src/index.ts new file mode 100644 index 00000000000..0802acef98a --- /dev/null +++ b/packages/eslint-plugin-internal/src/index.ts @@ -0,0 +1,5 @@ +import rules from './rules'; + +export = { + rules, +}; diff --git a/packages/eslint-plugin-internal/src/rules/index.ts b/packages/eslint-plugin-internal/src/rules/index.ts new file mode 100644 index 00000000000..800c448e041 --- /dev/null +++ b/packages/eslint-plugin-internal/src/rules/index.ts @@ -0,0 +1,7 @@ +import noTypescriptDefaultImport from './no-typescript-default-import'; +import noTypescriptEstreeImport from './no-typescript-estree-import'; + +export default { + 'no-typescript-default-import': noTypescriptDefaultImport, + 'no-typescript-estree-import': noTypescriptEstreeImport, +}; diff --git a/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts b/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts new file mode 100644 index 00000000000..ff4e35dc4f6 --- /dev/null +++ b/packages/eslint-plugin-internal/src/rules/no-typescript-default-import.ts @@ -0,0 +1,80 @@ +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; +import { createRule } from '../util'; + +/* +We have `allowSyntheticDefaultImports` turned on in this project, so there are two problems that arise: +- TypeScript's auto import will suggest `import ts = require('typescript');` if you type `ts` +- VSCode's suggestion feature will suggest changing `import * as ts from 'typescript'` to `import ts from 'typescript'` + +In order to keep compatibility with a wide range of consumers, some of whom don't use `allowSyntheticDefaultImports`, we should +always use either: +- `import * as ts from 'typescript';` +- `import { SyntaxKind } from 'typescript';` +*/ + +export default createRule({ + name: 'no-typescript-default-import', + meta: { + type: 'problem', + docs: { + description: + "Enforces that packages rules don't do `import ts from 'typescript';`", + category: 'Possible Errors', + recommended: 'error', + }, + fixable: 'code', + schema: [], + messages: { + noTSDefaultImport: [ + "Do not use the default import for typescript. Doing so will cause the package's type definitions to do the same.", + "This causes errors for consumers if they don't use the allowSyntheticDefaultImports compiler option.", + ].join('\n'), + }, + }, + defaultOptions: [], + create(context) { + return { + 'ImportDeclaration > ImportDefaultSpecifier'( + node: TSESTree.ImportDefaultSpecifier, + ): void { + const importStatement = node.parent as TSESTree.ImportDeclaration; + if (importStatement.source.value === 'typescript') { + context.report({ + node, + messageId: 'noTSDefaultImport', + fix(fixer) { + if (importStatement.specifiers.length === 1) { + return fixer.replaceText(node, '* as ts'); + } + + return null; + }, + }); + } + }, + 'TSImportEqualsDeclaration > TSExternalModuleReference'( + node: TSESTree.TSExternalModuleReference, + ): void { + const parent = node.parent as TSESTree.TSImportEqualsDeclaration; + if ( + node.expression.type === AST_NODE_TYPES.Literal && + node.expression.value === 'typescript' + ) { + context.report({ + node, + messageId: 'noTSDefaultImport', + fix(fixer) { + return fixer.replaceText( + parent, + "import * as ts from 'typescript';", + ); + }, + }); + } + }, + }; + }, +}); diff --git a/packages/eslint-plugin-internal/src/rules/no-typescript-estree-import.ts b/packages/eslint-plugin-internal/src/rules/no-typescript-estree-import.ts new file mode 100644 index 00000000000..2a879c14209 --- /dev/null +++ b/packages/eslint-plugin-internal/src/rules/no-typescript-estree-import.ts @@ -0,0 +1,52 @@ +import { createRule } from '../util'; + +const TSESTREE_NAME = '@typescript-eslint/typescript-estree'; +const UTILS_NAME = '@typescript-eslint/experimental-utils'; + +/* +Typescript will not error if people use typescript-estree within eslint-plugin. +This is because it's an indirect dependency. +We don't want people to import it, instead we want them to import from the utils package. +*/ + +export default createRule({ + name: 'no-typescript-estree-import', + meta: { + type: 'problem', + docs: { + description: `Enforces that eslint-plugin rules don't require anything from ${TSESTREE_NAME}`, + category: 'Possible Errors', + recommended: 'error', + }, + fixable: 'code', + schema: [], + messages: { + dontImportTSEStree: [ + `Don't import from ${TSESTREE_NAME}. Everything you need should be available in ${UTILS_NAME}.`, + `${TSESTREE_NAME} is an indirect dependency of this package, and thus should not be used directly.`, + ].join('\n'), + }, + }, + defaultOptions: [], + create(context) { + return { + ImportDeclaration(node): void { + if ( + typeof node.source.value === 'string' && + node.source.value.startsWith(TSESTREE_NAME) + ) { + context.report({ + node, + messageId: 'dontImportTSEStree', + fix(fixer) { + return fixer.replaceTextRange( + [node.source.range[0] + 1, node.source.range[1] - 1], + UTILS_NAME, + ); + }, + }); + } + }, + }; + }, +}); diff --git a/packages/eslint-plugin-internal/src/util/createRule.ts b/packages/eslint-plugin-internal/src/util/createRule.ts new file mode 100644 index 00000000000..24c630d5245 --- /dev/null +++ b/packages/eslint-plugin-internal/src/util/createRule.ts @@ -0,0 +1,11 @@ +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; + +// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder +const version = require('../../package.json').version; + +const createRule = ESLintUtils.RuleCreator( + name => + `https://github.com/typescript-eslint/typescript-eslint/blob/v${version}/packages/eslint-plugin-internal/src/rules/${name}.ts`, +); + +export { createRule }; diff --git a/packages/eslint-plugin-internal/src/util/index.ts b/packages/eslint-plugin-internal/src/util/index.ts new file mode 100644 index 00000000000..cd13da0f5cd --- /dev/null +++ b/packages/eslint-plugin-internal/src/util/index.ts @@ -0,0 +1 @@ +export * from './createRule'; diff --git a/packages/eslint-plugin-internal/tests/RuleTester.ts b/packages/eslint-plugin-internal/tests/RuleTester.ts new file mode 100644 index 00000000000..daef7ec9a8b --- /dev/null +++ b/packages/eslint-plugin-internal/tests/RuleTester.ts @@ -0,0 +1,22 @@ +import { TSESLint, ESLintUtils } from '@typescript-eslint/experimental-utils'; + +const { batchedSingleLineTests } = ESLintUtils; + +const parser = '@typescript-eslint/parser'; + +type RuleTesterConfig = Omit & { + parser: typeof parser; +}; +class RuleTester extends TSESLint.RuleTester { + // as of eslint 6 you have to provide an absolute path to the parser + // but that's not as clean to type, this saves us trying to manually enforce + // that contributors require.resolve everything + constructor(options: RuleTesterConfig) { + super({ + ...options, + parser: require.resolve(options.parser), + }); + } +} + +export { RuleTester, batchedSingleLineTests }; diff --git a/packages/eslint-plugin-internal/tests/rules/no-typescript-default-import.test.ts b/packages/eslint-plugin-internal/tests/rules/no-typescript-default-import.test.ts new file mode 100644 index 00000000000..3c8db9e6651 --- /dev/null +++ b/packages/eslint-plugin-internal/tests/rules/no-typescript-default-import.test.ts @@ -0,0 +1,45 @@ +import rule from '../../src/rules/no-typescript-default-import'; +import { RuleTester, batchedSingleLineTests } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + }, +}); + +ruleTester.run('no-typescript-default-import', rule, { + valid: [ + "import { foo } from 'typescript';", + "import ts from 'nottypescript';", + "import * as foo from 'typescript';", + 'import ts = foo;', + "import ts = require('nottypescript');", + ], + invalid: batchedSingleLineTests({ + code: ` +import ts from 'typescript'; +import ts, { SyntaxKind } from 'typescript'; +import ts = require('typescript'); + `, + output: ` +import * as ts from 'typescript'; +import ts, { SyntaxKind } from 'typescript'; +import * as ts from 'typescript'; + `, + errors: [ + { + messageId: 'noTSDefaultImport', + line: 2, + }, + { + messageId: 'noTSDefaultImport', + line: 3, + }, + { + messageId: 'noTSDefaultImport', + line: 4, + }, + ], + }), +}); diff --git a/packages/eslint-plugin-internal/tests/rules/no-typescript-estree.test.ts b/packages/eslint-plugin-internal/tests/rules/no-typescript-estree.test.ts new file mode 100644 index 00000000000..a76e03b7c1d --- /dev/null +++ b/packages/eslint-plugin-internal/tests/rules/no-typescript-estree.test.ts @@ -0,0 +1,43 @@ +import rule from '../../src/rules/no-typescript-estree-import'; +import { RuleTester, batchedSingleLineTests } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + }, +}); + +ruleTester.run('no-typescript-estree-import', rule, { + valid: [ + 'import { foo } from "@typescript-eslint/experimental-utils";', + 'import foo from "@typescript-eslint/experimental-utils";', + 'import * as foo from "@typescript-eslint/experimental-utils";', + ], + invalid: batchedSingleLineTests({ + code: ` +import { foo } from "@typescript-eslint/typescript-estree"; +import foo from "@typescript-eslint/typescript-estree"; +import * as foo from "@typescript-eslint/typescript-estree"; + `, + output: ` +import { foo } from "@typescript-eslint/experimental-utils"; +import foo from "@typescript-eslint/experimental-utils"; +import * as foo from "@typescript-eslint/experimental-utils"; + `, + errors: [ + { + messageId: 'dontImportTSEStree', + line: 2, + }, + { + messageId: 'dontImportTSEStree', + line: 3, + }, + { + messageId: 'dontImportTSEStree', + line: 4, + }, + ], + }), +}); diff --git a/packages/eslint-plugin-internal/tsconfig.build.json b/packages/eslint-plugin-internal/tsconfig.build.json new file mode 100644 index 00000000000..b40961d2d9a --- /dev/null +++ b/packages/eslint-plugin-internal/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + // specifically disable declarations for the plugin + "declaration": false, + "declarationMap": false, + "outDir": "./dist", + "rootDir": "./src", + "resolveJsonModule": true + }, + "include": ["src", "typings"], + "references": [{ "path": "../experimental-utils/tsconfig.build.json" }] +} diff --git a/packages/eslint-plugin-internal/tsconfig.json b/packages/eslint-plugin-internal/tsconfig.json new file mode 100644 index 00000000000..6fddcebe2ae --- /dev/null +++ b/packages/eslint-plugin-internal/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.build.json", + "compilerOptions": { + "composite": false, + "rootDir": "." + }, + "include": ["src", "typings", "tests"] +} diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 94dc75cf78d..f5b06b683f4 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,5 +1,5 @@ import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-for-in-array.ts b/packages/eslint-plugin/src/rules/no-for-in-array.ts index db15d310457..b93665069c7 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,4 +1,4 @@ -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 50d6cf9201a..5326129780c 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -1,6 +1,6 @@ import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 5c884f4506c..ba77f30e1f9 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, } from '@typescript-eslint/experimental-utils'; -import ts, { TypeFlags } from 'typescript'; +import * as ts from 'typescript'; import { isTypeFlagSet, unionTypeParts, @@ -139,13 +139,15 @@ export default createRule({ unionTypeParts(type).some(part => isTypeFlagSet( part, - TypeFlags.Any | TypeFlags.Unknown | ts.TypeFlags.TypeParameter, + ts.TypeFlags.Any | + ts.TypeFlags.Unknown | + ts.TypeFlags.TypeParameter, ), ) ) { return; } - const messageId = isTypeFlagSet(type, TypeFlags.Never) + const messageId = isTypeFlagSet(type, ts.TypeFlags.Never) ? 'never' : !isPossiblyTruthy(type) ? 'alwaysFalsy' @@ -161,10 +163,10 @@ export default createRule({ function checkNodeForNullish(node: TSESTree.Node): void { const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if (isTypeFlagSet(type, TypeFlags.Any | TypeFlags.Unknown)) { + if (isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return; } - const messageId = isTypeFlagSet(type, TypeFlags.Never) + const messageId = isTypeFlagSet(type, ts.TypeFlags.Never) ? 'never' : !isPossiblyNullish(type) ? 'neverNullish' diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index dbf07b46848..f489fd3c331 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -2,7 +2,7 @@ import { AST_NODE_TYPES, TSESTree, } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as tsutils from 'tsutils'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index c5c439c7bd0..3ccca4f74a0 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -1,6 +1,6 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; import { findFirstResult } from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index 29f98bdedf0..542e937f530 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -10,7 +10,7 @@ import { isTypeFlagSet, isVariableDeclaration, } from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 1f75e1f026f..359397efdc7 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,7 +1,7 @@ /* eslint-disable no-fallthrough */ import { TSESTree } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; export type Options = [ diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 9577420fb9e..0cd54d6c786 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -4,7 +4,7 @@ import { } from '@typescript-eslint/experimental-utils'; import { getStaticValue } from 'eslint-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; -import ts from 'typescript'; +import * as ts from 'typescript'; import { createRule, getParserServices } from '../util'; export default createRule({ diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index e0beb74c79c..805f17d4f60 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -4,7 +4,7 @@ import { TSESLint, TSESTree, } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; export type Options = [ diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 4620d89cde4..d2aa135b99f 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,5 +1,5 @@ import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; import { typeIsOrHasBaseType } from '../util'; import { diff --git a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts index 1d220702e04..580b36f591d 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,5 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index 4db47f9e075..53c43e7a6b9 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -4,7 +4,7 @@ import { } from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/require-await'; import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; type Options = util.InferOptionsTypeFromRule; diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index c41587a169a..f07e624eeb2 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,5 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index 199664036c9..efedc786b51 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -2,7 +2,7 @@ import { TSESTree, AST_NODE_TYPES, } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 6594007651c..762d697fdbb 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -3,7 +3,7 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; -import ts, { SyntaxKind } from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; export default util.createRule({ @@ -59,7 +59,7 @@ export default util.createRule({ ): void { let child: ts.Node; - const isAwait = expression.kind === SyntaxKind.AwaitExpression; + const isAwait = expression.kind === ts.SyntaxKind.AwaitExpression; if (isAwait) { child = expression.getChildAt(1); diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 1b0d0de9462..e33b9c8a39e 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -2,7 +2,7 @@ import { TSESTree, AST_NODE_TYPES, } from '@typescript-eslint/experimental-utils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as tsutils from 'tsutils'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 16ee4787760..ac4dd6b28de 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -3,7 +3,7 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; import * as util from '../util'; //------------------------------------------------------------------------------ diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/eslint-plugin/src/util/types.ts index 6a3644acbb5..e53bfb35531 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/eslint-plugin/src/util/types.ts @@ -3,7 +3,7 @@ import { isUnionOrIntersectionType, unionTypeParts, } from 'tsutils'; -import ts from 'typescript'; +import * as ts from 'typescript'; /** * @param type Type being checked by name. diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 279e8d06bca..8cd63e5bfef 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -26,7 +26,6 @@ }, "license": "MIT", "main": "dist/index.js", - "types": "dist/index.d.ts", "scripts": { "build": "tsc -b tsconfig.build.json", "clean": "tsc -b tsconfig.build.json --clean", diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index a82d9941dbd..753e82f7b55 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -1,4 +1,4 @@ -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { forEachComment } from 'tsutils/util/util'; import { getLocFor } from './node-utils'; import { TSESTree } from './ts-estree'; diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index af48546d7f8..f65ac54867a 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -1,6 +1,6 @@ // There's lots of funny stuff due to the typing of ts.Node /* eslint-disable @typescript-eslint/no-explicit-any */ -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { canContainDirective, createError, diff --git a/packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts b/packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts index 7fb4663b985..471a6d6b6fe 100644 --- a/packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts +++ b/packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts @@ -2,7 +2,7 @@ // They have been trimmed down to only include the relevant bits // We use some special internal TS apis to help us do our parsing flexibly -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; // https://github.com/microsoft/TypeScript/blob/b84e65db4ea5c39dbaa2ccd6594efe4653318251/src/compiler/watchUtilities.ts#L6-L18 interface DirectoryStructureHost { diff --git a/packages/typescript-estree/src/create-program/createDefaultProgram.ts b/packages/typescript-estree/src/create-program/createDefaultProgram.ts index 383d10bd43d..11a6638d711 100644 --- a/packages/typescript-estree/src/create-program/createDefaultProgram.ts +++ b/packages/typescript-estree/src/create-program/createDefaultProgram.ts @@ -1,6 +1,6 @@ import debug from 'debug'; import path from 'path'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { Extra } from '../parser-options'; import { getTsconfigPath, diff --git a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts b/packages/typescript-estree/src/create-program/createIsolatedProgram.ts index 296aee2e5ba..c6c74b8c5ab 100644 --- a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts +++ b/packages/typescript-estree/src/create-program/createIsolatedProgram.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { Extra } from '../parser-options'; import { ASTAndProgram, diff --git a/packages/typescript-estree/src/create-program/createSourceFile.ts b/packages/typescript-estree/src/create-program/createSourceFile.ts index d1ab5f98d21..70820c1d217 100644 --- a/packages/typescript-estree/src/create-program/createSourceFile.ts +++ b/packages/typescript-estree/src/create-program/createSourceFile.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { Extra } from '../parser-options'; import { getScriptKind } from './shared'; diff --git a/packages/typescript-estree/src/create-program/createWatchProgram.ts b/packages/typescript-estree/src/create-program/createWatchProgram.ts index 73dc8ec426e..72b5535c578 100644 --- a/packages/typescript-estree/src/create-program/createWatchProgram.ts +++ b/packages/typescript-estree/src/create-program/createWatchProgram.ts @@ -1,6 +1,6 @@ import debug from 'debug'; import fs from 'fs'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { Extra } from '../parser-options'; import { WatchCompilerHostOfConfigFile } from './WatchCompilerHostOfConfigFile'; import { diff --git a/packages/typescript-estree/src/create-program/shared.ts b/packages/typescript-estree/src/create-program/shared.ts index 1ba44449867..b828478073e 100644 --- a/packages/typescript-estree/src/create-program/shared.ts +++ b/packages/typescript-estree/src/create-program/shared.ts @@ -1,5 +1,5 @@ import path from 'path'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { Extra } from '../parser-options'; interface ASTAndProgram { diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index f9abf8cca23..1995bbf57c5 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -1,5 +1,5 @@ import unescape from 'lodash.unescape'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from './ts-estree'; const SyntaxKind = ts.SyntaxKind; diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 27a10024dc8..882249b6bdd 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -1,5 +1,5 @@ import semver from 'semver'; -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; import { sync as globSync } from 'glob'; import isGlob from 'is-glob'; import { astConverter } from './ast-converter'; diff --git a/packages/typescript-estree/src/semantic-or-syntactic-errors.ts b/packages/typescript-estree/src/semantic-or-syntactic-errors.ts index d2b61efc856..f8a6e5be467 100644 --- a/packages/typescript-estree/src/semantic-or-syntactic-errors.ts +++ b/packages/typescript-estree/src/semantic-or-syntactic-errors.ts @@ -1,4 +1,4 @@ -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; interface SemanticOrSyntacticError extends ts.Diagnostic { message: string; diff --git a/packages/typescript-estree/src/ts-estree/ts-nodes.ts b/packages/typescript-estree/src/ts-estree/ts-nodes.ts index fbf10048157..eb99af20780 100644 --- a/packages/typescript-estree/src/ts-estree/ts-nodes.ts +++ b/packages/typescript-estree/src/ts-estree/ts-nodes.ts @@ -1,4 +1,4 @@ -import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports +import * as ts from 'typescript'; export type TSNode = ts.Node & ( diff --git a/packages/typescript-estree/tests/lib/convert.ts b/packages/typescript-estree/tests/lib/convert.ts index 71158dfb825..e4217be7d22 100644 --- a/packages/typescript-estree/tests/lib/convert.ts +++ b/packages/typescript-estree/tests/lib/convert.ts @@ -1,7 +1,7 @@ // deeplyCopy is private internal /* eslint-disable @typescript-eslint/no-explicit-any */ import { Converter } from '../../src/convert'; -import ts from 'typescript'; +import * as ts from 'typescript'; describe('convert', () => { function convertCode(code: string): ts.SourceFile { diff --git a/packages/typescript-estree/tests/lib/semanticInfo.ts b/packages/typescript-estree/tests/lib/semanticInfo.ts index 05e65137db4..3a99890c401 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { extname, join, resolve } from 'path'; -import ts from 'typescript'; +import * as ts from 'typescript'; import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, diff --git a/yarn.lock b/yarn.lock index d32b5a04141..154b6b2e23a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7949,9 +7949,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@*, "typescript@>=3.2.1 <3.8.0", typescript@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" - integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + version "3.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19" + integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw== uglify-js@^3.1.4: version "3.6.0"