From a7a03ce39f82fac47e9ef1ef052ee1366eeb8c8a Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Fri, 10 May 2019 09:10:04 -0700 Subject: [PATCH] feat: Move shared types into their own package (#425) --- .eslintignore | 1 - .eslintrc.json | 1 + packages/eslint-plugin/package.json | 2 +- .../src/rules/adjacent-overload-signatures.ts | 5 +- .../eslint-plugin/src/rules/array-type.ts | 2 +- .../eslint-plugin/src/rules/await-thenable.ts | 8 +- packages/eslint-plugin/src/rules/ban-types.ts | 9 +- packages/eslint-plugin/src/rules/camelcase.ts | 5 +- .../src/rules/class-name-casing.ts | 5 +- .../rules/explicit-function-return-type.ts | 7 +- .../rules/explicit-member-accessibility.ts | 5 +- .../src/rules/func-call-spacing.ts | 2 +- .../indent-new-do-not-use/BinarySearchTree.ts | 4 +- .../indent-new-do-not-use/OffsetStorage.ts | 4 +- .../rules/indent-new-do-not-use/TokenInfo.ts | 7 +- .../src/rules/indent-new-do-not-use/index.ts | 12 +- packages/eslint-plugin/src/rules/indent.ts | 5 +- .../src/rules/member-delimiter-style.ts | 5 +- .../eslint-plugin/src/rules/member-naming.ts | 2 +- .../src/rules/member-ordering.ts | 5 +- .../src/rules/no-array-constructor.ts | 5 +- .../src/rules/no-extra-parens.ts | 9 +- .../src/rules/no-extraneous-class.ts | 5 +- .../src/rules/no-inferrable-types.ts | 5 +- .../src/rules/no-magic-numbers.ts | 5 +- .../eslint-plugin/src/rules/no-misused-new.ts | 5 +- .../eslint-plugin/src/rules/no-namespace.ts | 5 +- .../rules/no-object-literal-type-assertion.ts | 5 +- .../src/rules/no-parameter-properties.ts | 5 +- .../src/rules/no-require-imports.ts | 2 +- .../eslint-plugin/src/rules/no-this-alias.ts | 5 +- .../eslint-plugin/src/rules/no-type-alias.ts | 9 +- .../src/rules/no-unnecessary-qualifier.ts | 2 +- .../rules/no-unnecessary-type-assertion.ts | 2 +- .../eslint-plugin/src/rules/no-unused-vars.ts | 5 +- .../src/rules/no-use-before-define.ts | 29 +- .../src/rules/no-useless-constructor.ts | 5 +- .../src/rules/no-var-requires.ts | 2 +- .../eslint-plugin/src/rules/prefer-for-of.ts | 9 +- .../src/rules/prefer-function-type.ts | 4 +- .../src/rules/prefer-includes.ts | 2 +- .../src/rules/prefer-interface.ts | 5 +- .../src/rules/prefer-namespace-keyword.ts | 2 +- .../rules/prefer-string-starts-ends-with.ts | 11 +- .../src/rules/promise-function-async.ts | 2 +- .../src/rules/require-array-sort-compare.ts | 4 +- .../src/rules/restrict-plus-operands.ts | 2 +- packages/eslint-plugin/src/rules/semi.ts | 11 +- .../src/rules/type-annotation-spacing.ts | 2 +- .../eslint-plugin/src/rules/unbound-method.ts | 8 +- .../src/rules/unified-signatures.ts | 5 +- packages/eslint-plugin/src/util/createRule.ts | 63 +- .../src/util/getParserServices.ts | 6 +- packages/eslint-plugin/src/util/index.ts | 8 +- packages/eslint-plugin/src/util/misc.ts | 16 +- packages/eslint-plugin/tests/RuleTester.ts | 126 +-- .../tests/eslint-rules/no-redeclare.test.ts | 2 +- .../tests/rules/func-call-spacing.test.ts | 17 +- .../tests/rules/indent/indent-eslint.test.ts | 2 +- .../tests/rules/indent/indent.test.ts | 10 +- .../eslint-plugin/tests/rules/indent/utils.ts | 10 +- .../tests/rules/no-array-constructor.test.ts | 2 +- .../tests/rules/no-extraneous-class.test.ts | 2 +- .../tests/rules/no-for-in-array.test.ts | 2 +- .../tests/rules/no-inferrable-types.test.ts | 8 +- .../tests/rules/no-this-alias.test.ts | 2 +- .../rules/no-unnecessary-qualifier.test.ts | 2 +- .../tests/rules/no-use-before-define.test.ts | 2 +- .../tests/rules/prefer-function-type.test.ts | 2 +- .../eslint-plugin/tests/rules/semi.test.ts | 7 +- .../rules/type-annotation-spacing.test.ts | 7 +- packages/eslint-plugin/tests/util.test.ts | 112 --- .../eslint-plugin/typings/eslint-rules.d.ts | 85 +-- .../eslint-plugin/typings/eslint-utils.d.ts | 25 +- packages/eslint-plugin/typings/ts-eslint.d.ts | 716 ------------------ packages/experimental-utils/LICENSE | 21 + packages/experimental-utils/README.md | 33 + packages/experimental-utils/jest.config.js | 13 + packages/experimental-utils/package.json | 40 + .../src/eslint-utils/RuleCreator.ts | 65 ++ .../src/eslint-utils}/applyDefault.ts | 0 .../eslint-utils/batchedSingleLineTests.ts | 59 ++ .../src/eslint-utils}/deepMerge.ts | 0 .../src/eslint-utils/index.ts | 4 + packages/experimental-utils/src/index.ts | 13 + .../experimental-utils/src/ts-eslint/AST.ts | 18 + .../src/ts-eslint/Linter.ts | 132 ++++ .../src/ts-eslint/ParserOptions.ts | 21 + .../experimental-utils/src/ts-eslint/Rule.ts | 400 ++++++++++ .../src/ts-eslint/RuleTester.ts | 76 ++ .../experimental-utils/src/ts-eslint/Scope.ts | 106 +++ .../src/ts-eslint/SourceCode.ts | 193 +++++ .../experimental-utils/src/ts-eslint/index.ts | 7 + .../tests/eslint-utils/applyDefault.test.ts | 58 ++ .../tests/eslint-utils/deepMerge.test.ts | 60 ++ .../experimental-utils/tsconfig.build.json | 9 + packages/experimental-utils/tsconfig.json | 8 + packages/parser/package.json | 2 +- packages/parser/src/analyze-scope.ts | 13 +- packages/parser/src/parser.ts | 10 +- packages/parser/src/scope/scope-manager.ts | 3 +- packages/parser/src/scope/scopes.ts | 2 +- packages/parser/tests/lib/parser.ts | 6 +- packages/parser/typings/eslint-scope.d.ts | 16 +- .../typescript-estree/src/ast-converter.ts | 4 +- .../typescript-estree/src/convert-comments.ts | 2 +- packages/typescript-estree/src/convert.ts | 5 +- packages/typescript-estree/src/node-utils.ts | 2 +- .../typescript-estree/src/parser-options.ts | 15 +- packages/typescript-estree/src/parser.ts | 34 +- .../typescript-estree/src/semantic-errors.ts | 2 +- .../typescript-estree/src/ts-estree/index.ts | 4 +- .../src/ts-estree/ts-estree.ts | 2 +- .../src/{ => ts-estree}/ts-nodes.ts | 2 +- .../typescript-estree/src/tsconfig-parser.ts | 2 +- .../tests/ast-alignment/fixtures-to-test.ts | 2 +- .../tests/ast-alignment/parse.ts | 2 +- .../tests/ast-alignment/utils.ts | 2 +- .../typescript-estree/tests/lib/comments.ts | 4 +- .../typescript-estree/tests/lib/javascript.ts | 4 +- packages/typescript-estree/tests/lib/jsx.ts | 4 +- packages/typescript-estree/tests/lib/parse.ts | 10 +- .../tests/lib/semantic-diagnostics-enabled.ts | 2 +- .../tests/lib/semanticInfo.ts | 17 +- packages/typescript-estree/tests/lib/tsx.ts | 4 +- .../typescript-estree/tests/lib/typescript.ts | 4 +- .../typescript-estree/tools/test-utils.ts | 8 +- .../typescript-estree/tsconfig.build.json | 3 +- packages/typescript-estree/tsconfig.json | 5 +- yarn.lock | 2 +- 130 files changed, 1729 insertions(+), 1313 deletions(-) delete mode 100644 packages/eslint-plugin/typings/ts-eslint.d.ts create mode 100644 packages/experimental-utils/LICENSE create mode 100644 packages/experimental-utils/README.md create mode 100644 packages/experimental-utils/jest.config.js create mode 100644 packages/experimental-utils/package.json create mode 100644 packages/experimental-utils/src/eslint-utils/RuleCreator.ts rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/applyDefault.ts (100%) create mode 100644 packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/deepMerge.ts (100%) create mode 100644 packages/experimental-utils/src/eslint-utils/index.ts create mode 100644 packages/experimental-utils/src/index.ts create mode 100644 packages/experimental-utils/src/ts-eslint/AST.ts create mode 100644 packages/experimental-utils/src/ts-eslint/Linter.ts create mode 100644 packages/experimental-utils/src/ts-eslint/ParserOptions.ts create mode 100644 packages/experimental-utils/src/ts-eslint/Rule.ts create mode 100644 packages/experimental-utils/src/ts-eslint/RuleTester.ts create mode 100644 packages/experimental-utils/src/ts-eslint/Scope.ts create mode 100644 packages/experimental-utils/src/ts-eslint/SourceCode.ts create mode 100644 packages/experimental-utils/src/ts-eslint/index.ts create mode 100644 packages/experimental-utils/tests/eslint-utils/applyDefault.test.ts create mode 100644 packages/experimental-utils/tests/eslint-utils/deepMerge.test.ts create mode 100644 packages/experimental-utils/tsconfig.build.json create mode 100644 packages/experimental-utils/tsconfig.json rename packages/typescript-estree/src/{ => ts-estree}/ts-nodes.ts (97%) diff --git a/.eslintignore b/.eslintignore index c1536a77bd3..92693b86382 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,5 +5,4 @@ fixtures shared-fixtures coverage -packages/typescript-estree/src/estree packages/eslint-plugin-tslint/tests diff --git a/.eslintrc.json b/.eslintrc.json index 91c11fbba92..00e766eaaef 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,6 +12,7 @@ "no-dupe-class-members": "off", "no-mixed-operators": "error", "no-console": "off", + "no-dupe-class-members": "off", "no-undef": "off", "@typescript-eslint/indent": "off", "@typescript-eslint/no-explicit-any": "off", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index e85f8489268..ae2f544fa93 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "@typescript-eslint/parser": "1.7.0", - "@typescript-eslint/typescript-estree": "1.7.0", + "@typescript-eslint/experimental-utils": "1.7.0", "eslint-utils": "^1.3.1", "regexpp": "^2.0.1", "requireindex": "^1.2.0", diff --git a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts index 8e864c9c4a2..80c8b131587 100644 --- a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts +++ b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type RuleNode = diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index 4aef0268fa1..62ace5d4317 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -2,7 +2,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree, -} from '@typescript-eslint/typescript-estree'; +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; /** diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 3bee5b029f7..f9981920fab 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 * as ts from 'typescript'; +import ts from 'typescript'; import * as util from '../util'; @@ -26,9 +26,9 @@ export default util.createRule({ return { AwaitExpression(node) { - const originalNode = parserServices.esTreeNodeToTSNodeMap.get( - node, - ) as ts.AwaitExpression; + const originalNode = parserServices.esTreeNodeToTSNodeMap.get< + ts.AwaitExpression + >(node); const type = checker.getTypeAtLocation(originalNode.expression); if ( diff --git a/packages/eslint-plugin/src/rules/ban-types.ts b/packages/eslint-plugin/src/rules/ban-types.ts index 77756ad15a8..25c0a08f3ab 100644 --- a/packages/eslint-plugin/src/rules/ban-types.ts +++ b/packages/eslint-plugin/src/rules/ban-types.ts @@ -1,5 +1,8 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; -import { ReportFixFunction } from 'ts-eslint'; +import { + TSESLint, + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ @@ -94,7 +97,7 @@ export default util.createRule({ let customMessage = ''; const bannedCfgValue = bannedTypes[node.name]; - let fix: ReportFixFunction | null = null; + let fix: TSESLint.ReportFixFunction | null = null; if (typeof bannedCfgValue === 'string') { customMessage += ` ${bannedCfgValue}`; diff --git a/packages/eslint-plugin/src/rules/camelcase.ts b/packages/eslint-plugin/src/rules/camelcase.ts index ec7ba9ea4fe..f3cb5948e5d 100644 --- a/packages/eslint-plugin/src/rules/camelcase.ts +++ b/packages/eslint-plugin/src/rules/camelcase.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/camelcase'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/class-name-casing.ts b/packages/eslint-plugin/src/rules/class-name-casing.ts index 2e9a15ffde7..829f29f24b8 100644 --- a/packages/eslint-plugin/src/rules/class-name-casing.ts +++ b/packages/eslint-plugin/src/rules/class-name-casing.ts @@ -1,5 +1,8 @@ +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; export default util.createRule({ name: 'class-name-casing', diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index 6228f014311..914e4172c79 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -1,11 +1,13 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ { allowExpressions?: boolean; allowTypedFunctionExpressions?: boolean; - allowUntypedSetters?: boolean; } ]; type MessageIds = 'missingReturnType'; @@ -42,7 +44,6 @@ export default util.createRule({ { allowExpressions: false, allowTypedFunctionExpressions: false, - allowUntypedSetters: true, }, ], create(context, [options]) { diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index be79d684a69..d760f18ea94 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type AccessibilityLevel = diff --git a/packages/eslint-plugin/src/rules/func-call-spacing.ts b/packages/eslint-plugin/src/rules/func-call-spacing.ts index 63f9d05e19e..fd395887480 100644 --- a/packages/eslint-plugin/src/rules/func-call-spacing.ts +++ b/packages/eslint-plugin/src/rules/func-call-spacing.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { isOpeningParenToken } from 'eslint-utils'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/BinarySearchTree.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/BinarySearchTree.ts index 002fbd3d8ee..e530efb4099 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/BinarySearchTree.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/BinarySearchTree.ts @@ -1,8 +1,8 @@ // The following code is adapted from the the code in eslint. // License: https://github.com/eslint/eslint/blob/48700fc8408f394887cdedd071b22b757700fdcb/LICENSE -import { TSESTree } from '@typescript-eslint/typescript-estree'; -import createTree = require('functional-red-black-tree'); +import { TSESTree } from '@typescript-eslint/experimental-utils'; +import createTree from 'functional-red-black-tree'; export type TokenOrComment = TSESTree.Token | TSESTree.Comment; export interface TreeValue { diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts index 1ab3dd71ebb..deacc272bb3 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts @@ -1,9 +1,9 @@ // The following code is adapted from the the code in eslint. // License: https://github.com/eslint/eslint/blob/48700fc8408f394887cdedd071b22b757700fdcb/LICENSE -import { TokenInfo } from './TokenInfo'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { BinarySearchTree, TokenOrComment } from './BinarySearchTree'; -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TokenInfo } from './TokenInfo'; /** * A class to store information on desired offsets of tokens from each other diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/TokenInfo.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/TokenInfo.ts index 29aaecdaa6d..9b7d345fe3d 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/TokenInfo.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/TokenInfo.ts @@ -1,18 +1,17 @@ // The following code is adapted from the the code in eslint. // License: https://github.com/eslint/eslint/blob/48700fc8408f394887cdedd071b22b757700fdcb/LICENSE -import { TSESTree } from '@typescript-eslint/typescript-estree'; -import { SourceCode } from 'ts-eslint'; +import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import { TokenOrComment } from './BinarySearchTree'; /** * A helper class to get token-based info related to indentation */ export class TokenInfo { - private sourceCode: SourceCode; + private sourceCode: TSESLint.SourceCode; public firstTokensByLineNumber: Map; - constructor(sourceCode: SourceCode) { + constructor(sourceCode: TSESLint.SourceCode) { this.sourceCode = sourceCode; this.firstTokensByLineNumber = sourceCode.tokensAndComments.reduce( (map, token) => { diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts index f9a3ebcfb49..1944fdf2bf5 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts @@ -6,7 +6,8 @@ import { AST_NODE_TYPES, TSESTree, AST_TOKEN_TYPES, -} from '@typescript-eslint/typescript-estree'; + TSESLint, +} from '@typescript-eslint/experimental-utils'; import { createGlobalLinebreakMatcher } from 'eslint/lib/util/ast-utils'; import { isOpeningParenToken, @@ -20,7 +21,6 @@ import { isColonToken, isCommentToken, } from 'eslint-utils'; -import { RuleListener, RuleFunction } from 'ts-eslint'; import { TokenOrComment } from './BinarySearchTree'; import { OffsetStorage } from './OffsetStorage'; import { TokenInfo } from './TokenInfo'; @@ -848,7 +848,7 @@ export default createRule({ const ignoredNodeFirstTokens = new Set(); - const baseOffsetListeners: RuleListener = { + const baseOffsetListeners: TSESLint.RuleListener = { 'ArrayExpression, ArrayPattern'( node: TSESTree.ArrayExpression | TSESTree.ArrayPattern, ) { @@ -1547,7 +1547,7 @@ export default createRule({ }; const listenerCallQueue: { - listener: RuleFunction; + listener: TSESLint.RuleFunction; node: TSESTree.Node; }[] = []; @@ -1558,7 +1558,7 @@ export default createRule({ * 3. Call `ignoreNode` on the node sometime after exiting it and before validating offsets. */ const offsetListeners = Object.keys(baseOffsetListeners).reduce< - RuleListener + TSESLint.RuleListener >( /* * Offset listener calls are deferred until traversal is finished, and are called as @@ -1577,7 +1577,7 @@ export default createRule({ * ignored nodes are known. */ (acc, key) => { - const listener = baseOffsetListeners[key] as RuleFunction< + const listener = baseOffsetListeners[key] as TSESLint.RuleFunction< TSESTree.Node >; acc[key] = node => listenerCallQueue.push({ listener, node }); diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index 85187a7046b..6a7a5c31e13 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -4,7 +4,10 @@ * This is done intentionally based on the internal implementation of the base indent rule. */ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/indent'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index bfa2ca94439..326a0d961e5 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Delimiter = 'comma' | 'none' | 'semi'; diff --git a/packages/eslint-plugin/src/rules/member-naming.ts b/packages/eslint-plugin/src/rules/member-naming.ts index c0252331f79..7c221360c0c 100644 --- a/packages/eslint-plugin/src/rules/member-naming.ts +++ b/packages/eslint-plugin/src/rules/member-naming.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; interface Config { diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index 6811cf5a2e4..ffcc6985073 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type MessageIds = 'incorrectOrder'; diff --git a/packages/eslint-plugin/src/rules/no-array-constructor.ts b/packages/eslint-plugin/src/rules/no-array-constructor.ts index d6c92491be1..5de11364ab8 100644 --- a/packages/eslint-plugin/src/rules/no-array-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-array-constructor.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/no-extra-parens.ts b/packages/eslint-plugin/src/rules/no-extra-parens.ts index 78065969afb..7dd71ad583b 100644 --- a/packages/eslint-plugin/src/rules/no-extra-parens.ts +++ b/packages/eslint-plugin/src/rules/no-extra-parens.ts @@ -1,5 +1,8 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; -import { RuleListener } from 'ts-eslint'; +import { + AST_NODE_TYPES, + TSESTree, + TSESLint, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/no-extra-parens'; import * as util from '../util'; @@ -85,7 +88,7 @@ export default util.createRule({ return rule(node); } - const overrides: RuleListener = { + const overrides: TSESLint.RuleListener = { // ArrayExpression ArrowFunctionExpression(node) { if (node.body.type !== AST_NODE_TYPES.TSAsExpression) { diff --git a/packages/eslint-plugin/src/rules/no-extraneous-class.ts b/packages/eslint-plugin/src/rules/no-extraneous-class.ts index 461b8c6efa8..b0917b5ae72 100644 --- a/packages/eslint-plugin/src/rules/no-extraneous-class.ts +++ b/packages/eslint-plugin/src/rules/no-extraneous-class.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index 9ee66b44564..3546cd1112d 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 049aa2b35b8..49689213992 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -3,7 +3,10 @@ * @author Scott O'Hara */ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/no-magic-numbers'; import * as util from '../util'; import { JSONSchema4 } from 'json-schema'; diff --git a/packages/eslint-plugin/src/rules/no-misused-new.ts b/packages/eslint-plugin/src/rules/no-misused-new.ts index 5730475cd0d..56c5eb5f296 100644 --- a/packages/eslint-plugin/src/rules/no-misused-new.ts +++ b/packages/eslint-plugin/src/rules/no-misused-new.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/no-namespace.ts b/packages/eslint-plugin/src/rules/no-namespace.ts index ad6eaf61107..2ab66102dd4 100644 --- a/packages/eslint-plugin/src/rules/no-namespace.ts +++ b/packages/eslint-plugin/src/rules/no-namespace.ts @@ -1,4 +1,7 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-object-literal-type-assertion.ts b/packages/eslint-plugin/src/rules/no-object-literal-type-assertion.ts index d8362013321..d946c879257 100644 --- a/packages/eslint-plugin/src/rules/no-object-literal-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-object-literal-type-assertion.ts @@ -1,4 +1,7 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-parameter-properties.ts b/packages/eslint-plugin/src/rules/no-parameter-properties.ts index 0d92c855aa8..6d1ffa80870 100644 --- a/packages/eslint-plugin/src/rules/no-parameter-properties.ts +++ b/packages/eslint-plugin/src/rules/no-parameter-properties.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Modifier = diff --git a/packages/eslint-plugin/src/rules/no-require-imports.ts b/packages/eslint-plugin/src/rules/no-require-imports.ts index 98039a91b7a..69b4887c925 100644 --- a/packages/eslint-plugin/src/rules/no-require-imports.ts +++ b/packages/eslint-plugin/src/rules/no-require-imports.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/no-this-alias.ts b/packages/eslint-plugin/src/rules/no-this-alias.ts index e98c9c39659..30201acf6a0 100644 --- a/packages/eslint-plugin/src/rules/no-this-alias.ts +++ b/packages/eslint-plugin/src/rules/no-this-alias.ts @@ -1,4 +1,7 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index 890e6b04aa5..b4a4274c274 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -1,5 +1,8 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; -import { ReportDescriptor } from 'ts-eslint'; +import { + AST_NODE_TYPES, + TSESLint, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ @@ -194,7 +197,7 @@ export default util.createRule({ compositionType: string | undefined, isRoot: boolean, type?: string, - ): ReportDescriptor { + ): TSESLint.ReportDescriptor { if (isRoot) { return { node, diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index d11b2527190..f382e7262e0 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import ts from 'typescript'; import * as tsutils from 'tsutils'; import * as util 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 1e78c75338d..c98b619eab4 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { isCallExpression, isNewExpression, diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index ede16241eed..9fc32f6fc1c 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -1,4 +1,7 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/no-unused-vars'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index 085bb02975d..c18e8e0cc11 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -1,5 +1,8 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; -import { Scope } from 'ts-eslint'; +import { + AST_NODE_TYPES, + TSESLint, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; @@ -28,14 +31,14 @@ function parseOptions(options: string | Config | null): Required { /** * Checks whether or not a given scope is a top level scope. */ -function isTopLevelScope(scope: Scope.Scope): boolean { +function isTopLevelScope(scope: TSESLint.Scope.Scope): boolean { return scope.type === 'module' || scope.type === 'global'; } /** * Checks whether or not a given variable is a function declaration. */ -function isFunction(variable: Scope.Variable): boolean { +function isFunction(variable: TSESLint.Scope.Variable): boolean { return variable.defs[0].type === 'FunctionName'; } @@ -43,8 +46,8 @@ function isFunction(variable: Scope.Variable): boolean { * Checks whether or not a given variable is a class declaration in an upper function scope. */ function isOuterClass( - variable: Scope.Variable, - reference: Scope.Reference, + variable: TSESLint.Scope.Variable, + reference: TSESLint.Scope.Reference, ): boolean { if (variable.defs[0].type !== 'ClassName') { return false; @@ -64,8 +67,8 @@ function isOuterClass( * Checks whether or not a given variable is a variable declaration in an upper function scope. */ function isOuterVariable( - variable: Scope.Variable, - reference: Scope.Reference, + variable: TSESLint.Scope.Variable, + reference: TSESLint.Scope.Reference, ): boolean { if (variable.defs[0].type !== 'Variable') { return false; @@ -102,8 +105,8 @@ function isInRange( * - for (var a of a) {} */ function isInInitializer( - variable: Scope.Variable, - reference: Scope.Reference, + variable: TSESLint.Scope.Variable, + reference: TSESLint.Scope.Reference, ): boolean { if (variable.scope !== reference.from) { return false; @@ -199,8 +202,8 @@ export default util.createRule({ * @param reference The reference to the variable */ function isForbidden( - variable: Scope.Variable, - reference: Scope.Reference, + variable: TSESLint.Scope.Variable, + reference: TSESLint.Scope.Reference, ): boolean { if (isFunction(variable)) { return !!options.functions; @@ -217,7 +220,7 @@ export default util.createRule({ /** * Finds and validates all variables in a given scope. */ - function findVariablesInScope(scope: Scope.Scope): void { + function findVariablesInScope(scope: TSESLint.Scope.Scope): void { scope.references.forEach(reference => { const variable = reference.resolved; diff --git a/packages/eslint-plugin/src/rules/no-useless-constructor.ts b/packages/eslint-plugin/src/rules/no-useless-constructor.ts index dcac02df846..e6b48a055ed 100644 --- a/packages/eslint-plugin/src/rules/no-useless-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-useless-constructor.ts @@ -1,4 +1,7 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/no-useless-constructor'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/no-var-requires.ts b/packages/eslint-plugin/src/rules/no-var-requires.ts index 67b61d13175..a8acccd8af9 100644 --- a/packages/eslint-plugin/src/rules/no-var-requires.ts +++ b/packages/eslint-plugin/src/rules/no-var-requires.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = []; diff --git a/packages/eslint-plugin/src/rules/prefer-for-of.ts b/packages/eslint-plugin/src/rules/prefer-for-of.ts index 4b542cd9109..8e829b48e9c 100644 --- a/packages/eslint-plugin/src/rules/prefer-for-of.ts +++ b/packages/eslint-plugin/src/rules/prefer-for-of.ts @@ -1,6 +1,9 @@ -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESLint, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; -import { Scope } from 'ts-eslint'; export default util.createRule({ name: 'prefer-for-of', @@ -159,7 +162,7 @@ export default util.createRule({ function isIndexOnlyUsedWithArray( body: TSESTree.Statement, - indexVar: Scope.Variable, + indexVar: TSESLint.Scope.Variable, arrayExpression: TSESTree.Expression, ): boolean { const sourceCode = context.getSourceCode(); diff --git a/packages/eslint-plugin/src/rules/prefer-function-type.ts b/packages/eslint-plugin/src/rules/prefer-function-type.ts index e7a95d705e9..95f1a8ee3ca 100644 --- a/packages/eslint-plugin/src/rules/prefer-function-type.ts +++ b/packages/eslint-plugin/src/rules/prefer-function-type.ts @@ -1,8 +1,8 @@ import { AST_NODE_TYPES, - TSESTree, AST_TOKEN_TYPES, -} from '@typescript-eslint/typescript-estree'; + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index f7b3eb153ee..2db17e11d1d 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { getStaticValue } from 'eslint-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; import ts from 'typescript'; diff --git a/packages/eslint-plugin/src/rules/prefer-interface.ts b/packages/eslint-plugin/src/rules/prefer-interface.ts index 10308d7e70e..6efbf62d6a6 100644 --- a/packages/eslint-plugin/src/rules/prefer-interface.ts +++ b/packages/eslint-plugin/src/rules/prefer-interface.ts @@ -1,5 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; -import { RuleFix } from 'ts-eslint'; +import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ @@ -33,7 +32,7 @@ export default util.createRule({ messageId: 'interfaceOverType', fix(fixer) { const typeNode = node.typeParameters || node.id; - const fixes: RuleFix[] = []; + const fixes: TSESLint.RuleFix[] = []; const firstToken = sourceCode.getFirstToken(node); if (firstToken) { diff --git a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts index 37eced4e545..9d60e0eed4f 100644 --- a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts +++ b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts @@ -1,7 +1,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, -} from '@typescript-eslint/typescript-estree'; +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index 6b3079cdfdf..565a4cb83db 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -1,11 +1,10 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import { isNotClosingParenToken, getPropertyName, getStaticValue, } from 'eslint-utils'; import { RegExpParser, AST as RegExpAST } from 'regexpp'; -import { RuleFixer, RuleFix } from 'ts-eslint'; import ts from 'typescript'; import { createRule, getParserServices } from '../util'; @@ -314,11 +313,11 @@ export default createRule({ * @param negative The flag to fix to negative condition. */ function* fixWithRightOperand( - fixer: RuleFixer, + fixer: TSESLint.RuleFixer, node: TSESTree.BinaryExpression, kind: 'start' | 'end', negative: boolean, - ): IterableIterator { + ): IterableIterator { // left is CallExpression or MemberExpression. const leftNode = (node.left.type === 'CallExpression' ? node.left.callee @@ -344,11 +343,11 @@ export default createRule({ * @param negative The flag to fix to negative condition. */ function* fixWithArgument( - fixer: RuleFixer, + fixer: TSESLint.RuleFixer, node: TSESTree.BinaryExpression, kind: 'start' | 'end', negative: boolean, - ): IterableIterator { + ): IterableIterator { const callNode = node.left as TSESTree.CallExpression; const calleeNode = callNode.callee as TSESTree.MemberExpression; diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 75d2ccdacc7..0eb96e99143 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; type Options = [ 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 8699c0cf073..a9745be16e0 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 * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; +import ts from 'typescript'; import * as util from '../util'; export default util.createRule({ diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index ef73ae7478d..9a3a42c8f32 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import ts from 'typescript'; import * as util from '../util'; diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 89fe6180333..6e40651dd2e 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -1,6 +1,9 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + TSESTree, + TSESLint, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import baseRule from 'eslint/lib/rules/semi'; -import { RuleListener, RuleFunction } from 'ts-eslint'; import * as util from '../util'; export type Options = util.InferOptionsTypeFromRule; @@ -28,7 +31,7 @@ export default util.createRule({ ], create(context) { const rules = baseRule.create(context); - const checkForSemicolon = rules.ExpressionStatement as RuleFunction< + const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction< TSESTree.Node >; @@ -48,7 +51,7 @@ export default util.createRule({ AST_NODE_TYPES.TSExportAssignment, AST_NODE_TYPES.TSImportEqualsDeclaration, AST_NODE_TYPES.TSTypeAliasDeclaration, - ].reduce((acc, node) => { + ].reduce((acc, node) => { acc[node] = checkForSemicolon; return acc; }, {}); diff --git a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts index 9deac5cd977..19ef206119f 100644 --- a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts +++ b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts @@ -1,5 +1,5 @@ +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; -import { TSESTree } from '@typescript-eslint/typescript-estree'; type Options = [ { diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 6b177f1dccf..cd273a65456 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -1,7 +1,9 @@ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; -import * as ts from 'typescript'; - +import ts from 'typescript'; import * as util from '../util'; //------------------------------------------------------------------------------ diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index c1c1ad470da..d4ea472be5e 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -1,5 +1,8 @@ +import { + AST_NODE_TYPES, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import * as util from '../util'; -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; interface Failure { unify: Unify; diff --git a/packages/eslint-plugin/src/util/createRule.ts b/packages/eslint-plugin/src/util/createRule.ts index ac61c39cb55..5982f04c3d5 100644 --- a/packages/eslint-plugin/src/util/createRule.ts +++ b/packages/eslint-plugin/src/util/createRule.ts @@ -1,62 +1,9 @@ -import RuleModule, { - RuleListener, - RuleMetaData, - RuleMetaDataDocs, - RuleContext, -} from 'ts-eslint'; -import { applyDefault } from './applyDefault'; +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; -// Utility type to remove a list of properties from an object -type RemoveProps< - TObj extends Record, - TKeys extends keyof TObj -> = Pick>; - -// we'll automatically add the url + tslint description for people. -type CreateRuleMetaDocs = RemoveProps & { - tslintName?: string; -}; -type CreateRuleMeta = { - docs: CreateRuleMetaDocs; -} & RemoveProps, 'docs'>; - -// This function will get much easier to call when this is merged https://github.com/Microsoft/TypeScript/pull/26349 -// TODO - when the above rule lands; add type checking for the context.report `data` property -export function createRule< - TOptions extends any[], - TMessageIds extends string, - TRuleListener extends RuleListener = RuleListener ->({ - name, - meta, - defaultOptions, - create, -}: { - name: string; - meta: CreateRuleMeta; - defaultOptions: TOptions; - create: ( - context: RuleContext, - optionsWithDefault: TOptions, - ) => TRuleListener; -}): RuleModule { - return { - meta: { - ...meta, - docs: { - ...meta.docs, - url: `https://github.com/typescript-eslint/typescript-eslint/blob/v${version}/packages/eslint-plugin/docs/rules/${name}.md`, - extraDescription: meta.docs.tslintName - ? [`\`${meta.docs.tslintName}\` from TSLint`] - : undefined, - }, - }, - create(context) { - const optionsWithDefault = applyDefault(defaultOptions, context.options); - return create(context, optionsWithDefault); - }, - }; -} +export const createRule = ESLintUtils.RuleCreator( + name => + `https://github.com/typescript-eslint/typescript-eslint/blob/v${version}/packages/eslint-plugin/docs/rules/${name}.md`, +); diff --git a/packages/eslint-plugin/src/util/getParserServices.ts b/packages/eslint-plugin/src/util/getParserServices.ts index a63297708cc..2cc8b498159 100644 --- a/packages/eslint-plugin/src/util/getParserServices.ts +++ b/packages/eslint-plugin/src/util/getParserServices.ts @@ -1,5 +1,5 @@ import { ParserServices } from '@typescript-eslint/parser'; -import { RuleContext } from 'ts-eslint'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; type RequiredParserServices = { [k in keyof ParserServices]: Exclude @@ -11,7 +11,9 @@ type RequiredParserServices = { export function getParserServices< TMessageIds extends string, TOptions extends any[] ->(context: RuleContext): RequiredParserServices { +>( + context: TSESLint.RuleContext, +): RequiredParserServices { if ( !context.parserServices || !context.parserServices.program || diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index d2291cded47..b1aae71b357 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -1,7 +1,11 @@ -export * from './applyDefault'; +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; + export * from './astUtils'; export * from './createRule'; -export * from './deepMerge'; export * from './getParserServices'; export * from './misc'; export * from './types'; + +// this is done for convenience - saves migrating all of the old rules +const { applyDefault, deepMerge, isObjectNotArray } = ESLintUtils; +export { applyDefault, deepMerge, isObjectNotArray }; diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 07b6a0b3c3d..2a9ba2a1c93 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -2,9 +2,11 @@ * @fileoverview Really small utility functions that didn't deserve their own files */ -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; -import RuleModule from 'ts-eslint'; -import { SourceCode } from 'ts-eslint'; +import { + AST_NODE_TYPES, + TSESLint, + TSESTree, +} from '@typescript-eslint/experimental-utils'; /** * Check if the context file name is *.ts or *.tsx @@ -27,7 +29,7 @@ export function upperCaseFirst(str: string) { return str[0].toUpperCase() + str.slice(1); } -type InferOptionsTypeFromRuleNever = T extends RuleModule< +type InferOptionsTypeFromRuleNever = T extends TSESLint.RuleModule< never, infer TOptions > @@ -36,7 +38,7 @@ type InferOptionsTypeFromRuleNever = T extends RuleModule< /** * Uses type inference to fetch the TOptions type from the given RuleModule */ -export type InferOptionsTypeFromRule = T extends RuleModule< +export type InferOptionsTypeFromRule = T extends TSESLint.RuleModule< any, infer TOptions > @@ -46,7 +48,7 @@ export type InferOptionsTypeFromRule = T extends RuleModule< /** * Uses type inference to fetch the TMessageIds type from the given RuleModule */ -export type InferMessageIdsTypeFromRule = T extends RuleModule< +export type InferMessageIdsTypeFromRule = T extends TSESLint.RuleModule< infer TMessageIds, any > @@ -88,7 +90,7 @@ export function arraysAreEqual( */ export function getNameFromClassMember( methodDefinition: TSESTree.MethodDefinition | TSESTree.ClassProperty, - sourceCode: SourceCode, + sourceCode: TSESLint.SourceCode, ): string { if (keyCanBeReadAsPropertyName(methodDefinition.key)) { return getNameFromPropertyName(methodDefinition.key); diff --git a/packages/eslint-plugin/tests/RuleTester.ts b/packages/eslint-plugin/tests/RuleTester.ts index 2703d00b5c2..4db8bf3909c 100644 --- a/packages/eslint-plugin/tests/RuleTester.ts +++ b/packages/eslint-plugin/tests/RuleTester.ts @@ -1,131 +1,13 @@ -import { ParserOptions } from '@typescript-eslint/parser'; -import { - AST_NODE_TYPES, - AST_TOKEN_TYPES, -} from '@typescript-eslint/typescript-estree'; +import { TSESLint, ESLintUtils } from '@typescript-eslint/experimental-utils'; import { RuleTester as ESLintRuleTester } from 'eslint'; import * as path from 'path'; -import RuleModule from 'ts-eslint'; -interface ValidTestCase> { - code: string; - options?: TOptions; - filename?: string; - parserOptions?: ParserOptions; - settings?: Record; - parser?: string; - globals?: Record; - env?: { - browser?: boolean; - }; -} - -interface InvalidTestCase< - TMessageIds extends string, - TOptions extends Readonly -> extends ValidTestCase { - errors: TestCaseError[]; - output?: string | null; -} - -interface TestCaseError { - messageId: TMessageIds; - data?: Record; - type?: AST_NODE_TYPES | AST_TOKEN_TYPES; - line?: number; - column?: number; -} - -interface RunTests< - TMessageIds extends string, - TOptions extends Readonly -> { - // RuleTester.run also accepts strings for valid cases - valid: (ValidTestCase | string)[]; - invalid: InvalidTestCase[]; -} - -declare class RuleTesterTyped { - run>( - name: string, - rule: RuleModule, - tests: RunTests, - ): void; -} - -const RuleTester = (ESLintRuleTester as any) as { - new (config?: { - parser: '@typescript-eslint/parser'; - parserOptions?: ParserOptions; - }): RuleTesterTyped; -}; +const RuleTester: TSESLint.RuleTester = ESLintRuleTester as any; function getFixturesRootDir() { return path.join(process.cwd(), 'tests/fixtures/'); } -/** - * Converts a batch of single line tests into a number of separate test cases. - * This makes it easier to write tests which use the same options. - * - * Why wouldn't you just leave them as one test? - * Because it makes the test error messages harder to decipher. - * This way each line will fail separately, instead of them all failing together. - */ -function batchedSingleLineTests>( - test: ValidTestCase, -): ValidTestCase[]; -/** - * Converts a batch of single line tests into a number of separate test cases. - * This makes it easier to write tests which use the same options. - * - * Why wouldn't you just leave them as one test? - * Because it makes the test error messages harder to decipher. - * This way each line will fail separately, instead of them all failing together. - * - * Make sure you have your line numbers correct for error reporting, as it will match - * the line numbers up with the split tests! - */ -function batchedSingleLineTests< - TMessageIds extends string, - TOptions extends Readonly ->( - test: InvalidTestCase, -): InvalidTestCase[]; -function batchedSingleLineTests< - TMessageIds extends string, - TOptions extends Readonly ->( - options: ValidTestCase | InvalidTestCase, -): (ValidTestCase | InvalidTestCase)[] { - // eslint counts lines from 1 - const lineOffset = options.code[0] === '\n' ? 2 : 1; - return options.code - .trim() - .split('\n') - .map((code, i) => { - const lineNum = i + lineOffset; - const errors = - 'errors' in options - ? options.errors.filter(e => e.line === lineNum) - : []; - return { - ...options, - code, - errors: errors.map(e => ({ - ...e, - line: 1, - })), - }; - }); -} +const { batchedSingleLineTests } = ESLintUtils; -export { - RuleTester, - RunTests, - TestCaseError, - InvalidTestCase, - ValidTestCase, - batchedSingleLineTests, - getFixturesRootDir, -}; +export { RuleTester, getFixturesRootDir, batchedSingleLineTests }; diff --git a/packages/eslint-plugin/tests/eslint-rules/no-redeclare.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-redeclare.test.ts index 6baa018ebf6..1a1fb94a462 100644 --- a/packages/eslint-plugin/tests/eslint-rules/no-redeclare.test.ts +++ b/packages/eslint-plugin/tests/eslint-rules/no-redeclare.test.ts @@ -1,5 +1,5 @@ import rule from 'eslint/lib/rules/no-redeclare'; -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import { RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ diff --git a/packages/eslint-plugin/tests/rules/func-call-spacing.test.ts b/packages/eslint-plugin/tests/rules/func-call-spacing.test.ts index 580f2a57d30..d0b8afe9b19 100644 --- a/packages/eslint-plugin/tests/rules/func-call-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/func-call-spacing.test.ts @@ -1,5 +1,6 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; import rule, { MessageIds, Options } from '../../src/rules/func-call-spacing'; -import { RuleTester, ValidTestCase, InvalidTestCase } from '../RuleTester'; +import { RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -32,7 +33,7 @@ ruleTester.run('func-call-spacing', rule, { '( f )( 0 )', '( (f) )( (0) )', '( f()() )(0)', - ].map>(code => ({ + ].map>(code => ({ code, options: ['never'], })), @@ -59,7 +60,7 @@ ruleTester.run('func-call-spacing', rule, { '( f ) ( 0 )', '( (f) ) ( (0) )', '( f () ) (0)', - ].map>(code => ({ + ].map>(code => ({ code, options: ['always'], })), @@ -75,7 +76,7 @@ ruleTester.run('func-call-spacing', rule, { 'f\u2028();', 'f\u2029();', 'f\r\n();', - ].map>(code => ({ + ].map>(code => ({ code, options: ['always', { allowNewlines: true }], })), @@ -191,7 +192,7 @@ var a = foo code: 'f\r\n();', output: null, // no change }, - ].map>( + ].map>( code => ({ options: ['never'], @@ -226,7 +227,7 @@ var a = foo code: 'f(0) (1)', output: 'f (0) (1)', }, - ].map>( + ].map>( code => ({ options: ['always'], @@ -302,7 +303,7 @@ var a = foo code: 'f\r\n();', output: 'f ();', }, - ].map>( + ].map>( code => ({ options: ['always'], @@ -355,7 +356,7 @@ var a = foo output: 'f ();\n t ();', errors: [{ messageId: 'missing' }, { messageId: 'missing' }], }, - ].map>( + ].map>( code => ({ options: ['always', { allowNewlines: true }], diff --git a/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts b/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts index ea44a421249..e0515e869c9 100644 --- a/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts +++ b/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts @@ -7,7 +7,7 @@ import { AST_TOKEN_TYPES, AST_NODE_TYPES, -} from '@typescript-eslint/typescript-estree'; +} from '@typescript-eslint/experimental-utils'; import fs from 'fs'; import path from 'path'; import rule from '../../../src/rules/indent-new-do-not-use'; diff --git a/packages/eslint-plugin/tests/rules/indent/indent.test.ts b/packages/eslint-plugin/tests/rules/indent/indent.test.ts index 647cbf753fc..e992b440c6c 100644 --- a/packages/eslint-plugin/tests/rules/indent/indent.test.ts +++ b/packages/eslint-plugin/tests/rules/indent/indent.test.ts @@ -1,5 +1,6 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; +import { RuleTester } from '../../RuleTester'; import rule from '../../../src/rules/indent'; -import { RuleTester, RunTests, TestCaseError } from '../../RuleTester'; import { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule, @@ -608,7 +609,7 @@ type Foo = string | { `, ], }, -].reduce>( +].reduce>( (acc, testCase) => { const indent = ' '; @@ -630,7 +631,7 @@ type Foo = string | { output: code, errors: code .split('\n') - .map | null>((line, lineNum) => { + .map | null>((line, lineNum) => { const indentCount = line.split(indent).length - 1; const spaceCount = indentCount * indent.length; @@ -649,7 +650,8 @@ type Foo = string | { }; }) .filter( - (error): error is TestCaseError => error !== null, + (error): error is TSESLint.TestCaseError => + error !== null, ), }); }); diff --git a/packages/eslint-plugin/tests/rules/indent/utils.ts b/packages/eslint-plugin/tests/rules/indent/utils.ts index c4bf28c08fb..091f68740cd 100644 --- a/packages/eslint-plugin/tests/rules/indent/utils.ts +++ b/packages/eslint-plugin/tests/rules/indent/utils.ts @@ -4,8 +4,8 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, -} from '@typescript-eslint/typescript-estree'; -import { TestCaseError } from '../../RuleTester'; + TSESLint, +} from '@typescript-eslint/experimental-utils'; import rule from '../../../src/rules/indent'; import { InferMessageIdsTypeFromRule } from '../../../src/util'; @@ -54,7 +54,7 @@ function is2DProvidedErrorArr( */ export function expectedErrors( providedErrors: ProvidedError | ProvidedError[], -): TestCaseError[]; +): TSESLint.TestCaseError[]; /** * Create error message object for failure cases with a single 'found' indentation type * @param providedIndentType indent type of string or tab @@ -64,11 +64,11 @@ export function expectedErrors( export function expectedErrors( providedIndentType: string, providedErrors: ProvidedError | ProvidedError[], -): TestCaseError[]; +): TSESLint.TestCaseError[]; export function expectedErrors( providedIndentType: string | ProvidedError | ProvidedError[], providedErrors?: ProvidedError | ProvidedError[], -): TestCaseError[] { +): TSESLint.TestCaseError[] { let indentType: string; let errors: ProvidedError[]; diff --git a/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts b/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts index 5e920dd088f..6b8570bb4a4 100644 --- a/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts +++ b/packages/eslint-plugin/tests/rules/no-array-constructor.test.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-array-constructor'; import { RuleTester } from '../RuleTester'; diff --git a/packages/eslint-plugin/tests/rules/no-extraneous-class.test.ts b/packages/eslint-plugin/tests/rules/no-extraneous-class.test.ts index 0bee5ac6324..1d2742ed040 100644 --- a/packages/eslint-plugin/tests/rules/no-extraneous-class.test.ts +++ b/packages/eslint-plugin/tests/rules/no-extraneous-class.test.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-extraneous-class'; import { RuleTester } from '../RuleTester'; diff --git a/packages/eslint-plugin/tests/rules/no-for-in-array.test.ts b/packages/eslint-plugin/tests/rules/no-for-in-array.test.ts index ad2395a93d0..44a40942c9f 100644 --- a/packages/eslint-plugin/tests/rules/no-for-in-array.test.ts +++ b/packages/eslint-plugin/tests/rules/no-for-in-array.test.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-for-in-array'; import { RuleTester, getFixturesRootDir } from '../RuleTester'; diff --git a/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts b/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts index 007fe8042d9..fb2563ed4ee 100644 --- a/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts +++ b/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts @@ -1,5 +1,6 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-inferrable-types'; -import { RuleTester, InvalidTestCase } from '../RuleTester'; +import { RuleTester } from '../RuleTester'; import { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule, @@ -61,7 +62,10 @@ const testCases = [ const validTestCases = flatten( testCases.map(c => c.code.map(code => `const a = ${code}`)), ); -const invalidTestCases: InvalidTestCase[] = flatten( +const invalidTestCases: TSESLint.InvalidTestCase< + MessageIds, + Options +>[] = flatten( testCases.map(cas => cas.code.map(code => ({ code: `const a: ${cas.type} = ${code}`, diff --git a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts index ea0320ac343..c1ddce12186 100644 --- a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts +++ b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-this-alias'; import { RuleTester } from '../RuleTester'; diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-qualifier.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-qualifier.test.ts index 6c2a18dacc8..53a349e552e 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-qualifier.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-qualifier.test.ts @@ -1,7 +1,7 @@ import path from 'path'; import rule from '../../src/rules/no-unnecessary-qualifier'; import { RuleTester } from '../RuleTester'; -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; const messageId = 'unnecessaryQualifier'; const rootPath = path.join(process.cwd(), 'tests/fixtures/'); diff --git a/packages/eslint-plugin/tests/rules/no-use-before-define.test.ts b/packages/eslint-plugin/tests/rules/no-use-before-define.test.ts index e1bca791b33..7a0324308b2 100644 --- a/packages/eslint-plugin/tests/rules/no-use-before-define.test.ts +++ b/packages/eslint-plugin/tests/rules/no-use-before-define.test.ts @@ -1,6 +1,6 @@ import rule from '../../src/rules/no-use-before-define'; import { RuleTester } from '../RuleTester'; -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', diff --git a/packages/eslint-plugin/tests/rules/prefer-function-type.test.ts b/packages/eslint-plugin/tests/rules/prefer-function-type.test.ts index 5743bcc7f4d..a472d8619fe 100644 --- a/packages/eslint-plugin/tests/rules/prefer-function-type.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-function-type.test.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/prefer-function-type'; import { RuleTester } from '../RuleTester'; diff --git a/packages/eslint-plugin/tests/rules/semi.test.ts b/packages/eslint-plugin/tests/rules/semi.test.ts index c4569c79ba0..83bc750a235 100644 --- a/packages/eslint-plugin/tests/rules/semi.test.ts +++ b/packages/eslint-plugin/tests/rules/semi.test.ts @@ -1,5 +1,6 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; import rule, { MessageIds, Options } from '../../src/rules/semi'; -import { InvalidTestCase, RuleTester, ValidTestCase } from '../RuleTester'; +import { RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -87,7 +88,7 @@ class PanCamera extends FreeCamera { 'export default (foo) => foo.bar();', 'export default foo = 42;', 'export default foo += 42;', - ].reduce[]>( + ].reduce[]>( (acc, code) => { acc.push({ code, @@ -616,7 +617,7 @@ class PanCamera extends FreeCamera { }, ], }, - ].reduce[]>( + ].reduce[]>( (acc, test) => { acc.push({ code: test.code.replace(/;/g, ''), diff --git a/packages/eslint-plugin/tests/rules/type-annotation-spacing.test.ts b/packages/eslint-plugin/tests/rules/type-annotation-spacing.test.ts index 05f75faf408..6559c9b7140 100644 --- a/packages/eslint-plugin/tests/rules/type-annotation-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/type-annotation-spacing.test.ts @@ -1,5 +1,6 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; +import { RuleTester } from '../RuleTester'; import rule from '../../src/rules/type-annotation-spacing'; -import { RuleTester, InvalidTestCase, ValidTestCase } from '../RuleTester'; import { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule, @@ -6317,7 +6318,7 @@ type Foo = { const operators = ['+?:', '-?:']; ruleTester.run('type-annotation-spacing', rule, { - valid: operators.reduce[]>( + valid: operators.reduce[]>( (validCases, operator) => validCases.concat([ { @@ -6359,7 +6360,7 @@ ruleTester.run('type-annotation-spacing', rule, { ]), [], ), - invalid: operators.reduce[]>( + invalid: operators.reduce[]>( (invalidCases, operator) => invalidCases.concat([ // space before + after cases diff --git a/packages/eslint-plugin/tests/util.test.ts b/packages/eslint-plugin/tests/util.test.ts index 957b50b286e..59c820d28b9 100644 --- a/packages/eslint-plugin/tests/util.test.ts +++ b/packages/eslint-plugin/tests/util.test.ts @@ -69,118 +69,6 @@ describe('isDefinitionFile', () => { }); }); -describe('deepMerge', () => { - it('creates a brand new object', () => { - const a = {}; - const b = {}; - const result = util.deepMerge(a, b); - - assert.notStrictEqual(result, a); - assert.notStrictEqual(result, b); - }); - - it('deeply merges objects', () => { - const a = { - stringA1: 'asdf', - numberA1: 1, - boolA1: true, - arrayA1: [1, 2, 3], - objA1: { - stringA2: 'fsda', - numberA2: 2, - boolA2: false, - arrayA2: [3, 2, 1], - objA2: {}, - }, - }; - const b = { - stringB1: 'asdf', - numberB1: 1, - boolB1: true, - arrayB1: [1, 2, 3], - objB1: { - stringB2: 'fsda', - numberB2: 2, - boolB2: false, - arrayB2: [3, 2, 1], - objB2: {}, - }, - }; - - assert.deepStrictEqual(util.deepMerge(a, b), Object.assign({}, a, b)); - }); - - it('deeply overwrites properties in the first one with the second', () => { - const a = { - prop1: { - prop2: 'hi', - }, - }; - const b = { - prop1: { - prop2: 'bye', - }, - }; - - assert.deepStrictEqual(util.deepMerge(a, b), b); - }); -}); - -describe('applyDefault', () => { - it('returns a clone of the default if no options given', () => { - const defaults = [ - { - prop: 'setting', - }, - ]; - const user = null; - const result = util.applyDefault(defaults, user); - - assert.deepStrictEqual(result, defaults); - assert.notStrictEqual(result, defaults); - }); - - it('returns applies a deepMerge to each element in the array', () => { - const defaults = [ - { - prop: 'setting1', - other: 'other', - }, - { - prop: 'setting2', - }, - ] as Record[]; - const user = [ - { - prop: 'new', - other: 'something', - }, - ] as Record[]; - const result = util.applyDefault(defaults, user); - - assert.deepStrictEqual(result, [ - { - prop: 'new', - other: 'something', - }, - { - prop: 'setting2', - }, - ]); - assert.notStrictEqual(result, defaults); - assert.notStrictEqual(result, user); - }); - - it('returns a brand new array', () => { - const defaults: undefined[] = []; - const user: undefined[] = []; - const result = util.applyDefault(defaults, user); - - assert.notStrictEqual(result, defaults); - assert.notStrictEqual(result, user); - }); -}); - describe('upperCaseFirst', () => { it('upper cases first', () => { assert.strictEqual(util.upperCaseFirst('hello'), 'Hello'); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 7ea46da7c0b..98ee285d1a2 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -1,15 +1,13 @@ // don't provide a general import case so that people have to strictly type out a declaration -// declare module 'eslint/lib/rules/*' { -// import RuleModule from 'ts-eslint'; -// const rule: RuleModule; +// declare module 'eslint/lib/rules/*' TSESLint, { +// const rule: TSESLint.RuleModule; // export = rule; // } declare module 'eslint/lib/rules/arrow-parens' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< | 'unexpectedParens' | 'expectedParens' | 'unexpectedParensInline' @@ -28,10 +26,9 @@ declare module 'eslint/lib/rules/arrow-parens' { } declare module 'eslint/lib/rules/camelcase' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'notCamelCase', [ { @@ -48,12 +45,11 @@ declare module 'eslint/lib/rules/camelcase' { } declare module 'eslint/lib/rules/indent' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; type Listener = (node: TSESTree.Node) => void; type ElementList = number | 'first' | 'off'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'wrongIndentation', [ ('tab' | number)?, @@ -146,10 +142,9 @@ declare module 'eslint/lib/rules/indent' { } declare module 'eslint/lib/rules/no-dupe-args' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'unexpected', [], { @@ -161,10 +156,9 @@ declare module 'eslint/lib/rules/no-dupe-args' { } declare module 'eslint/lib/rules/no-implicit-globals' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, [], { @@ -175,10 +169,9 @@ declare module 'eslint/lib/rules/no-implicit-globals' { } declare module 'eslint/lib/rules/no-magic-numbers' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'noMagic', [ { @@ -197,10 +190,9 @@ declare module 'eslint/lib/rules/no-magic-numbers' { } declare module 'eslint/lib/rules/no-redeclare' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, [ { @@ -215,10 +207,9 @@ declare module 'eslint/lib/rules/no-redeclare' { } declare module 'eslint/lib/rules/no-restricted-globals' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, ( | string @@ -234,10 +225,9 @@ declare module 'eslint/lib/rules/no-restricted-globals' { } declare module 'eslint/lib/rules/no-shadow' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, [ { @@ -254,10 +244,9 @@ declare module 'eslint/lib/rules/no-shadow' { } declare module 'eslint/lib/rules/no-undef' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'undef', [ { @@ -272,10 +261,9 @@ declare module 'eslint/lib/rules/no-undef' { } declare module 'eslint/lib/rules/no-unused-vars' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, ( | 'all' @@ -297,10 +285,9 @@ declare module 'eslint/lib/rules/no-unused-vars' { } declare module 'eslint/lib/rules/no-use-before-define' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, ( | 'nofunc' @@ -317,10 +304,9 @@ declare module 'eslint/lib/rules/no-use-before-define' { } declare module 'eslint/lib/rules/strict' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< | 'function' | 'global' | 'multiple' @@ -340,10 +326,9 @@ declare module 'eslint/lib/rules/strict' { } declare module 'eslint/lib/rules/no-useless-constructor' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, [], { @@ -354,10 +339,9 @@ declare module 'eslint/lib/rules/no-useless-constructor' { } declare module 'eslint/lib/rules/no-extra-parens' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< 'unexpected', [ 'all' | 'functions', @@ -407,10 +391,9 @@ declare module 'eslint/lib/rules/no-extra-parens' { } declare module 'eslint/lib/rules/semi' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import RuleModule from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - const rule: RuleModule< + const rule: TSESLint.RuleModule< never, [ 'always' | 'never', diff --git a/packages/eslint-plugin/typings/eslint-utils.d.ts b/packages/eslint-plugin/typings/eslint-utils.d.ts index d93c90532da..e7cefb09367 100644 --- a/packages/eslint-plugin/typings/eslint-utils.d.ts +++ b/packages/eslint-plugin/typings/eslint-utils.d.ts @@ -1,13 +1,12 @@ declare module 'eslint-utils' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import { Scope, SourceCode } from 'ts-eslint'; + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; export function getFunctionHeadLocation( node: | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression, - sourceCode: SourceCode, + sourceCode: TSESLint.SourceCode, ): TSESTree.SourceLocation; export function getFunctionNameWithKind( @@ -22,22 +21,22 @@ declare module 'eslint-utils' { | TSESTree.MemberExpression | TSESTree.Property | TSESTree.MethodDefinition, - initialScope?: Scope.Scope, + initialScope?: TSESLint.Scope.Scope, ): string | null; export function getStaticValue( node: TSESTree.Node, - initialScope?: Scope.Scope, + initialScope?: TSESLint.Scope.Scope, ): { value: any } | null; export function getStringIfConstant( node: TSESTree.Node, - initialScope?: Scope.Scope, + initialScope?: TSESLint.Scope.Scope, ): string | null; export function hasSideEffect( node: TSESTree.Node, - sourceCode: SourceCode, + sourceCode: TSESLint.SourceCode, options?: { considerGetters?: boolean; considerImplicitTypeConversion?: boolean; @@ -46,7 +45,7 @@ declare module 'eslint-utils' { export function isParenthesized( node: TSESTree.Node, - sourceCode: SourceCode, + sourceCode: TSESLint.SourceCode, ): boolean; export class PatternMatcher { @@ -56,14 +55,14 @@ declare module 'eslint-utils' { } export function findVariable( - initialScope: Scope.Scope, + initialScope: TSESLint.Scope.Scope, name: string, - ): Scope.Variable | null; + ): TSESLint.Scope.Variable | null; export function getInnermostScope( - initialScope: Scope.Scope, + initialScope: TSESLint.Scope.Scope, node: TSESTree.Node, - ): Scope.Scope; + ): TSESLint.Scope.Scope; export class ReferenceTracker { static readonly READ: unique symbol; @@ -71,7 +70,7 @@ declare module 'eslint-utils' { static readonly CONSTRUCT: unique symbol; constructor( - globalScope: Scope.Scope, + globalScope: TSESLint.Scope.Scope, options?: { mode: 'strict' | 'legacy'; globalObjectNames: readonly string[]; diff --git a/packages/eslint-plugin/typings/ts-eslint.d.ts b/packages/eslint-plugin/typings/ts-eslint.d.ts deleted file mode 100644 index 62ef79199a2..00000000000 --- a/packages/eslint-plugin/typings/ts-eslint.d.ts +++ /dev/null @@ -1,716 +0,0 @@ -/* -Redefine these types for these reasons: -1) We can better control what properties are option and what are not. -2) We have to replace definitions with our definitions which use our typescript-estree types. -3) We can better document the fields so it's easier for new contributers to understand. - -The def is wrapped up in a fake module so that it can be used in eslint-rules.d.ts -*/ - -declare module 'ts-eslint' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; - import { ParserServices } from '@typescript-eslint/parser'; - import { Linter } from 'eslint'; - import { JSONSchema4 } from 'json-schema'; - - //#region SourceCode - - interface Program extends TSESTree.Program { - comments: TSESTree.Comment[]; - tokens: TSESTree.Token[]; - loc: TSESTree.SourceLocation; - range: TSESTree.Range; - } - - namespace SourceCode { - export interface Config { - text: string; - ast: Program; - parserServices?: ParserServices; - scopeManager?: Scope.ScopeManager; - visitorKeys?: VisitorKeys; - } - - export interface VisitorKeys { - [nodeType: string]: string[]; - } - - export type FilterPredicate = ( - tokenOrComment: TSESTree.Token | TSESTree.Comment, - ) => boolean; - - export type CursorWithSkipOptions = - | number - | FilterPredicate - | { - includeComments?: boolean; - filter?: FilterPredicate; - skip?: number; - }; - - export type CursorWithCountOptions = - | number - | FilterPredicate - | { - includeComments?: boolean; - filter?: FilterPredicate; - count?: number; - }; - } - - class SourceCode { - text: string; - ast: Program; - lines: string[]; - hasBOM: boolean; - parserServices: ParserServices; - scopeManager: Scope.ScopeManager; - visitorKeys: SourceCode.VisitorKeys; - tokensAndComments: (TSESTree.Comment | TSESTree.Token)[]; - - constructor(text: string, ast: Program); - constructor(config: SourceCode.Config); - - static splitLines(text: string): string[]; - - getText( - node?: TSESTree.Node, - beforeCount?: number, - afterCount?: number, - ): string; - - getLines(): string[]; - - getAllComments(): TSESTree.Comment[]; - - getComments( - node: TSESTree.Node, - ): { leading: TSESTree.Comment[]; trailing: TSESTree.Comment[] }; - - getJSDocComment(node: TSESTree.Node): TSESTree.Node | TSESTree.Token | null; - - getNodeByRangeIndex(index: number): TSESTree.Node | null; - - isSpaceBetweenTokens( - first: TSESTree.Token, - second: TSESTree.Token, - ): boolean; - - getLocFromIndex(index: number): TSESTree.LineAndColumnData; - - getIndexFromLoc(location: TSESTree.LineAndColumnData): number; - - // Inherited methods from TokenStore - // --------------------------------- - - getTokenByRangeStart( - offset: number, - options?: { includeComments?: boolean }, - ): TSESTree.Token | null; - - getFirstToken( - node: TSESTree.Node, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getFirstTokens( - node: TSESTree.Node, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getLastToken( - node: TSESTree.Node, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getLastTokens( - node: TSESTree.Node, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getTokenBefore( - node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getTokensBefore( - node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getTokenAfter( - node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getTokensAfter( - node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getFirstTokenBetween( - left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getFirstTokensBetween( - left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getLastTokenBetween( - left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithSkipOptions, - ): TSESTree.Token | null; - - getLastTokensBetween( - left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - options?: SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getTokensBetween( - left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, - padding?: - | number - | SourceCode.FilterPredicate - | SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - getTokens( - node: TSESTree.Node, - beforeCount?: number, - afterCount?: number, - ): TSESTree.Token[]; - getTokens( - node: TSESTree.Node, - options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions, - ): TSESTree.Token[]; - - commentsExistBetween( - left: TSESTree.Node | TSESTree.Token, - right: TSESTree.Node | TSESTree.Token, - ): boolean; - - getCommentsBefore( - nodeOrToken: TSESTree.Node | TSESTree.Token, - ): TSESTree.Comment[]; - - getCommentsAfter( - nodeOrToken: TSESTree.Node | TSESTree.Token, - ): TSESTree.Comment[]; - - getCommentsInside(node: TSESTree.Node): TSESTree.Comment[]; - } - - //#endregion SourceCode - - //#region Rule - - interface RuleMetaDataDocs { - /** - * The general category the rule falls within - */ - category: - | 'Best Practices' - | 'Stylistic Issues' - | 'Variables' - | 'Possible Errors'; - /** - * Concise description of the rule - */ - description: string; - /** - * Extra information linking the rule to a tslint rule - */ - extraDescription?: string[]; - /** - * The recommendation level for the rule. - * Used by the build tools to generate the recommended config. - * Set to false to not include it as a recommendation - */ - recommended: 'error' | 'warn' | false; - /** - * The URL of the rule's docs - */ - url: string; - } - interface RuleMetaData { - /** - * True if the rule is deprecated, false otherwise - */ - deprecated?: boolean; - /** - * Documentation for the rule - */ - docs: RuleMetaDataDocs; - /** - * The fixer category. Omit if there is no fixer - */ - fixable?: 'code' | 'whitespace'; - /** - * A map of messages which the rule can report. - * The key is the messageId, and the string is the parameterised error string. - * See: https://eslint.org/docs/developer-guide/working-with-rules#messageids - */ - messages: Record; - /** - * The type of rule. - * - `"problem"` means the rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve. - * - `"suggestion"` means the rule is identifying something that could be done in a better way but no errors will occur if the code isn’t changed. - * - `"layout"` means the rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren’t specified in the AST. - */ - type: 'suggestion' | 'problem' | 'layout'; - /** - * The name of the rule this rule was replaced by, if it was deprecated. - */ - replacedBy?: string; - /** - * The options schema. Supply an empty array if there are no options. - */ - schema: JSONSchema4 | JSONSchema4[]; - } - - interface RuleFix { - range: TSESTree.Range; - text: string; - } - - interface RuleFixer { - insertTextAfter( - nodeOrToken: TSESTree.Node | TSESTree.Token, - text: string, - ): RuleFix; - - insertTextAfterRange(range: TSESTree.Range, text: string): RuleFix; - - insertTextBefore( - nodeOrToken: TSESTree.Node | TSESTree.Token, - text: string, - ): RuleFix; - - insertTextBeforeRange(range: TSESTree.Range, text: string): RuleFix; - - remove(nodeOrToken: TSESTree.Node | TSESTree.Token): RuleFix; - - removeRange(range: TSESTree.Range): RuleFix; - - replaceText( - nodeOrToken: TSESTree.Node | TSESTree.Token, - text: string, - ): RuleFix; - - replaceTextRange(range: TSESTree.Range, text: string): RuleFix; - } - - type ReportFixFunction = ( - fixer: RuleFixer, - ) => null | RuleFix | RuleFix[] | IterableIterator; - - interface ReportDescriptor { - /** - * The parameters for the message string associated with `messageId`. - */ - data?: Record; - /** - * The fixer function. - */ - fix?: ReportFixFunction | null; - /** - * The messageId which is being reported. - */ - messageId: TMessageIds; - /** - * The Node or AST Token which the report is being attached to - */ - node: TSESTree.Node | TSESTree.Comment | TSESTree.Token; - /** - * An override of the location of the report - */ - loc?: TSESTree.SourceLocation | TSESTree.LineAndColumnData; - } - - interface RuleContext< - TMessageIds extends string, - TOptions extends Readonly - > { - /** - * The rule ID. - */ - id: string; - /** - * An array of the configured options for this rule. - * This array does not include the rule severity. - */ - options: TOptions; - /** - * The shared settings from configuration. - * We do not have any shared settings in this plugin. - */ - settings: {}; - /** - * The name of the parser from configuration. - */ - parserPath: string; - /** - * The parser options configured for this run - */ - parserOptions: Linter.ParserOptions; - /** - * An object containing parser-provided services for rules - */ - parserServices?: ParserServices; - - /** - * Returns an array of the ancestors of the currently-traversed node, starting at - * the root of the AST and continuing through the direct parent of the current node. - * This array does not include the currently-traversed node itself. - */ - getAncestors(): TSESTree.Node[]; - - /** - * Returns a list of variables declared by the given node. - * This information can be used to track references to variables. - */ - getDeclaredVariables(node: TSESTree.Node): Scope.Variable[]; - - /** - * Returns the filename associated with the source. - */ - getFilename(): string; - - /** - * Returns the scope of the currently-traversed node. - * This information can be used track references to variables. - */ - getScope(): Scope.Scope; - - /** - * Returns a SourceCode object that you can use to work with the source that - * was passed to ESLint. - */ - getSourceCode(): SourceCode; - - /** - * Marks a variable with the given name in the current scope as used. - * This affects the no-unused-vars rule. - */ - markVariableAsUsed(name: string): boolean; - - /** - * Reports a problem in the code. - */ - report(descriptor: ReportDescriptor): void; - } - - // This isn't the correct signature, but it makes it easier to do custom unions within reusable listneers - // never will break someone's code unless they specifically type the function argument - type RuleFunction = (node: T) => void; - - interface RuleListener { - [nodeSelector: string]: RuleFunction | undefined; - ArrayExpression?: RuleFunction; - ArrayPattern?: RuleFunction; - ArrowFunctionExpression?: RuleFunction; - AssignmentPattern?: RuleFunction; - AssignmentExpression?: RuleFunction; - AwaitExpression?: RuleFunction; - BlockStatement?: RuleFunction; - BreakStatement?: RuleFunction; - CallExpression?: RuleFunction; - CatchClause?: RuleFunction; - ClassBody?: RuleFunction; - ClassDeclaration?: RuleFunction; - ClassExpression?: RuleFunction; - ClassProperty?: RuleFunction; - Comment?: RuleFunction; - ConditionalExpression?: RuleFunction; - ContinueStatement?: RuleFunction; - DebuggerStatement?: RuleFunction; - Decorator?: RuleFunction; - DoWhileStatement?: RuleFunction; - EmptyStatement?: RuleFunction; - ExportAllDeclaration?: RuleFunction; - ExportDefaultDeclaration?: RuleFunction; - ExportNamedDeclaration?: RuleFunction; - ExportSpecifier?: RuleFunction; - ExpressionStatement?: RuleFunction; - ForInStatement?: RuleFunction; - ForOfStatement?: RuleFunction; - ForStatement?: RuleFunction; - Identifier?: RuleFunction; - IfStatement?: RuleFunction; - Import?: RuleFunction; - ImportDeclaration?: RuleFunction; - ImportDefaultSpecifier?: RuleFunction; - ImportNamespaceSpecifier?: RuleFunction; - ImportSpecifier?: RuleFunction; - JSXAttribute?: RuleFunction; - JSXClosingElement?: RuleFunction; - JSXClosingFragment?: RuleFunction; - JSXElement?: RuleFunction; - JSXEmptyExpression?: RuleFunction; - JSXExpressionContainer?: RuleFunction; - JSXFragment?: RuleFunction; - JSXIdentifier?: RuleFunction; - JSXMemberExpression?: RuleFunction; - JSXOpeningElement?: RuleFunction; - JSXOpeningFragment?: RuleFunction; - JSXSpreadAttribute?: RuleFunction; - JSXSpreadChild?: RuleFunction; - JSXText?: RuleFunction; - LabeledStatement?: RuleFunction; - MemberExpression?: RuleFunction; - MetaProperty?: RuleFunction; - MethodDefinition?: RuleFunction; - NewExpression?: RuleFunction; - ObjectExpression?: RuleFunction; - ObjectPattern?: RuleFunction; - Program?: RuleFunction; - Property?: RuleFunction; - RestElement?: RuleFunction; - ReturnStatement?: RuleFunction; - SequenceExpression?: RuleFunction; - SpreadElement?: RuleFunction; - Super?: RuleFunction; - SwitchCase?: RuleFunction; - SwitchStatement?: RuleFunction; - TaggedTemplateExpression?: RuleFunction; - TemplateElement?: RuleFunction; - TemplateLiteral?: RuleFunction; - ThisExpression?: RuleFunction; - ThrowStatement?: RuleFunction; - Token?: RuleFunction; - TryStatement?: RuleFunction; - TSAbstractKeyword?: RuleFunction; - TSAbstractMethodDefinition?: RuleFunction< - TSESTree.TSAbstractMethodDefinition - >; - TSAnyKeyword?: RuleFunction; - TSArrayType?: RuleFunction; - TSAsExpression?: RuleFunction; - TSAsyncKeyword?: RuleFunction; - TSBigIntKeyword?: RuleFunction; - TSBooleanKeyword?: RuleFunction; - TSCallSignatureDeclaration?: RuleFunction< - TSESTree.TSCallSignatureDeclaration - >; - TSConditionalType?: RuleFunction; - TSConstructSignatureDeclaration?: RuleFunction< - TSESTree.TSConstructSignatureDeclaration - >; - TSDeclareKeyword?: RuleFunction; - TSDeclareFunction?: RuleFunction; - TSEnumDeclaration?: RuleFunction; - TSEnumMember?: RuleFunction; - TSExportAssignment?: RuleFunction; - TSExportKeyword?: RuleFunction; - TSExternalModuleReference?: RuleFunction< - TSESTree.TSExternalModuleReference - >; - TSImportEqualsDeclaration?: RuleFunction< - TSESTree.TSImportEqualsDeclaration - >; - TSImportType?: RuleFunction; - TSIndexedAccessType?: RuleFunction; - TSIndexSignature?: RuleFunction; - TSInferType?: RuleFunction; - TSInterfaceBody?: RuleFunction; - TSInterfaceDeclaration?: RuleFunction; - TSIntersectionType?: RuleFunction; - TSLiteralType?: RuleFunction; - TSMappedType?: RuleFunction; - TSMethodSignature?: RuleFunction; - TSModuleBlock?: RuleFunction; - TSModuleDeclaration?: RuleFunction; - TSNamespaceExportDeclaration?: RuleFunction< - TSESTree.TSNamespaceExportDeclaration - >; - TSNeverKeyword?: RuleFunction; - TSNonNullExpression?: RuleFunction; - TSNullKeyword?: RuleFunction; - TSNumberKeyword?: RuleFunction; - TSObjectKeyword?: RuleFunction; - TSOptionalType?: RuleFunction; - TSParameterProperty?: RuleFunction; - TSParenthesizedType?: RuleFunction; - TSPrivateKeyword?: RuleFunction; - TSPropertySignature?: RuleFunction; - TSProtectedKeyword?: RuleFunction; - TSPublicKeyword?: RuleFunction; - TSQualifiedName?: RuleFunction; - TSReadonlyKeyword?: RuleFunction; - TSRestType?: RuleFunction; - TSStaticKeyword?: RuleFunction; - TSStringKeyword?: RuleFunction; - TSSymbolKeyword?: RuleFunction; - TSThisType?: RuleFunction; - TSTupleType?: RuleFunction; - TSTypeAliasDeclaration?: RuleFunction; - TSTypeAnnotation?: RuleFunction; - TSTypeAssertion?: RuleFunction; - TSTypeLiteral?: RuleFunction; - TSTypeOperator?: RuleFunction; - TSTypeParameter?: RuleFunction; - TSTypeParameterDeclaration?: RuleFunction< - TSESTree.TSTypeParameterDeclaration - >; - TSTypeParameterInstantiation?: RuleFunction< - TSESTree.TSTypeParameterInstantiation - >; - TSTypePredicate?: RuleFunction; - TSTypeQuery?: RuleFunction; - TSTypeReference?: RuleFunction; - TSUndefinedKeyword?: RuleFunction; - TSUnionType?: RuleFunction; - TSUnknownKeyword?: RuleFunction; - TSVoidKeyword?: RuleFunction; - UnaryExpression?: RuleFunction; - UpdateExpression?: RuleFunction; - VariableDeclaration?: RuleFunction; - VariableDeclarator?: RuleFunction; - WhileStatement?: RuleFunction; - WithStatement?: RuleFunction; - YieldExpression?: RuleFunction; - } - - interface RuleModule< - TMessageIds extends string, - TOptions extends Readonly, - // for extending base rules - TRuleListener extends RuleListener = RuleListener - > { - /** - * Metadata about the rule - */ - meta: RuleMetaData; - - /** - * Function which returns an object with methods that ESLint calls to “visit” - * nodes while traversing the abstract syntax tree. - */ - create(context: RuleContext): TRuleListener; - } - - //#endregion Rule - - namespace Scope { - interface ScopeManager { - scopes: Scope[]; - globalScope: Scope | null; - - acquire(node: TSESTree.Node, inner?: boolean): Scope | null; - - getDeclaredVariables(node: TSESTree.Node): Variable[]; - } - - interface Reference { - identifier: TSESTree.Identifier; - from: Scope; - resolved: Variable | null; - writeExpr: TSESTree.Node | null; - init: boolean; - - isWrite(): boolean; - - isRead(): boolean; - - isWriteOnly(): boolean; - - isReadOnly(): boolean; - - isReadWrite(): boolean; - } - - interface Variable { - name: string; - identifiers: TSESTree.Identifier[]; - references: Reference[]; - defs: Definition[]; - scope: Scope; - eslintUsed?: boolean; - } - - interface Scope { - type: - | 'block' - | 'catch' - | 'class' - | 'for' - | 'function' - | 'function-expression-name' - | 'global' - | 'module' - | 'switch' - | 'with' - | 'TDZ'; - isStrict: boolean; - upper: Scope | null; - childScopes: Scope[]; - variableScope: Scope; - block: TSESTree.Node; - variables: Variable[]; - set: Map; - references: Reference[]; - through: Reference[]; - functionExpressionScope: boolean; - } - - type DefinitionType = - | { type: 'CatchClause'; node: TSESTree.CatchClause; parent: null } - | { - type: 'ClassName'; - node: TSESTree.ClassDeclaration | TSESTree.ClassExpression; - parent: null; - } - | { - type: 'FunctionName'; - node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression; - parent: null; - } - | { type: 'ImplicitGlobalVariable'; node: TSESTree.Program; parent: null } - | { - type: 'ImportBinding'; - node: - | TSESTree.ImportSpecifier - | TSESTree.ImportDefaultSpecifier - | TSESTree.ImportNamespaceSpecifier; - parent: TSESTree.ImportDeclaration; - } - | { - type: 'Parameter'; - node: - | TSESTree.FunctionDeclaration - | TSESTree.FunctionExpression - | TSESTree.ArrowFunctionExpression; - parent: null; - } - | { type: 'TDZ'; node: any; parent: null } - | { - type: 'Variable'; - node: TSESTree.VariableDeclarator; - parent: TSESTree.VariableDeclaration; - }; - - type Definition = DefinitionType & { name: TSESTree.Identifier }; - } - - export { - ReportDescriptor, - ReportFixFunction, - RuleContext, - RuleFix, - RuleFixer, - RuleFunction, - RuleListener, - RuleMetaData, - RuleMetaDataDocs, - Scope, - SourceCode, - }; - export default RuleModule; -} diff --git a/packages/experimental-utils/LICENSE b/packages/experimental-utils/LICENSE new file mode 100644 index 00000000000..7e7370143b2 --- /dev/null +++ b/packages/experimental-utils/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 TypeScript ESLint and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/experimental-utils/README.md b/packages/experimental-utils/README.md new file mode 100644 index 00000000000..45ecc1a64f8 --- /dev/null +++ b/packages/experimental-utils/README.md @@ -0,0 +1,33 @@ +# @typescript-eslint/experimental-utils + +(Experimental) Utilities for working with TypeScript + ESLint together. + +## Note + +This package has inherited its version number from the @typescript-eslint project. +Meaning that even though this package is `1.x.y`, you shouldn't expect 100% stability between minor version bumps. +i.e. treat it as a `0.x.y` package. + +Feel free to use it now, and let us know what utilities you need or send us PRs with utilities you build on top of it. + +Once it is stable, it will be renamed to `@typescript-eslint/util` for a `2.0.0` release. + +## Exports + +| Name | Description | +| --------------------------- | ---------------------------------------------------------------------------------------------- | +| [`TSESTree`] | Types for the TypeScript flavour of ESTree created by `@typescript-eslint/typescript-estree`. | +| [`AST_NODE_TYPES`] | An enum with the names of every single _node_ found in `TSESTree`. | +| [`AST_TOKEN_TYPES`] | An enum with the names of every single _token_ found in `TSESTree`. | +| [`TSESLint`] | Types for ESLint, correctly typed to work with the types found in `TSESTree`. | +| [`ESLintUtils`] | Tools for creating eslint rules with TypeScript. | +| [`ESLintUtils.RuleCreator`] | A function for creating strictly typed eslint rules with TypeScript. | +| [`ParserServices`] | The parser services provided when parsing a file using `@typescript-eslint/typescript-estree`. | + +[`AST_NODE_TYPES`](../packages/typescript-estree/src/ts-estree/ast-node-types.ts) +[`AST_TOKEN_TYPES`](../packages/typescript-estree/src/ts-estree/ast-node-types.ts) +[`ESLintUtils`](./src/eslint-utils) +[`ESLintUtils.createRule`](./src/eslint-utils/createRule.ts) +[`ParserServices`](../packages/typescript-estree/src/ts-estree/parser.ts) +[`TSESTree`](../packages/typescript-estree/src/ts-estree/ts-estree.ts) +[`TSESLint`](./src/ts-eslint) diff --git a/packages/experimental-utils/jest.config.js b/packages/experimental-utils/jest.config.js new file mode 100644 index 00000000000..b64d433b01a --- /dev/null +++ b/packages/experimental-utils/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/experimental-utils/package.json b/packages/experimental-utils/package.json new file mode 100644 index 00000000000..d1ab0c20078 --- /dev/null +++ b/packages/experimental-utils/package.json @@ -0,0 +1,40 @@ +{ + "name": "@typescript-eslint/experimental-utils", + "version": "1.7.0", + "description": "(Experimental) Utilities for working with TypeScript + ESLint together", + "keywords": [ + "eslint", + "typescript", + "estree" + ], + "engines": { + "node": "^6.14.0 || ^8.10.0 || >=9.10.0" + }, + "files": [ + "dist", + "package.json", + "README.md", + "LICENSE" + ], + "repository": "typescript-eslint/typescript-eslint", + "bugs": { + "url": "https://github.com/typescript-eslint/typescript-eslint/issues" + }, + "license": "MIT", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "test": "jest --coverage", + "prebuild": "npm run clean", + "build": "tsc -p tsconfig.build.json", + "clean": "rimraf dist/", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@typescript-eslint/typescript-estree": "1.7.0" + }, + "devDependencies": {}, + "peerDependencies": { + "typescript": "*" + } +} diff --git a/packages/experimental-utils/src/eslint-utils/RuleCreator.ts b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts new file mode 100644 index 00000000000..b20e70af213 --- /dev/null +++ b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts @@ -0,0 +1,65 @@ +import { + RuleMetaData, + RuleMetaDataDocs, + RuleListener, + RuleContext, + RuleModule, +} from '../ts-eslint/Rule'; +import { applyDefault } from './applyDefault'; + +// Utility type to remove a list of properties from an object +type RemoveProps< + TObj extends Record, + TKeys extends keyof TObj +> = Pick>; + +// we'll automatically add the url + tslint description for people. +type CreateRuleMetaDocs = RemoveProps & { + tslintName?: string; +}; +type CreateRuleMeta = { + docs: CreateRuleMetaDocs; +} & RemoveProps, 'docs'>; + +export function RuleCreator(urlCreator: (ruleName: string) => string) { + // This function will get much easier to call when this is merged https://github.com/Microsoft/TypeScript/pull/26349 + // TODO - when the above PR lands; add type checking for the context.report `data` property + return function createRule< + TOptions extends any[], + TMessageIds extends string, + TRuleListener extends RuleListener = RuleListener + >({ + name, + meta, + defaultOptions, + create, + }: { + name: string; + meta: CreateRuleMeta; + defaultOptions: TOptions; + create: ( + context: RuleContext, + optionsWithDefault: TOptions, + ) => TRuleListener; + }): RuleModule { + return { + meta: { + ...meta, + docs: { + ...meta.docs, + url: urlCreator(name), + extraDescription: meta.docs.tslintName + ? [`\`${meta.docs.tslintName}\` from TSLint`] + : undefined, + }, + }, + create(context) { + const optionsWithDefault = applyDefault( + defaultOptions, + context.options, + ); + return create(context, optionsWithDefault); + }, + }; + }; +} diff --git a/packages/eslint-plugin/src/util/applyDefault.ts b/packages/experimental-utils/src/eslint-utils/applyDefault.ts similarity index 100% rename from packages/eslint-plugin/src/util/applyDefault.ts rename to packages/experimental-utils/src/eslint-utils/applyDefault.ts diff --git a/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts b/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts new file mode 100644 index 00000000000..0812adade32 --- /dev/null +++ b/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts @@ -0,0 +1,59 @@ +import { ValidTestCase, InvalidTestCase } from '../ts-eslint'; + +/** + * Converts a batch of single line tests into a number of separate test cases. + * This makes it easier to write tests which use the same options. + * + * Why wouldn't you just leave them as one test? + * Because it makes the test error messages harder to decipher. + * This way each line will fail separately, instead of them all failing together. + */ +function batchedSingleLineTests>( + test: ValidTestCase, +): ValidTestCase[]; +/** + * Converts a batch of single line tests into a number of separate test cases. + * This makes it easier to write tests which use the same options. + * + * Why wouldn't you just leave them as one test? + * Because it makes the test error messages harder to decipher. + * This way each line will fail separately, instead of them all failing together. + * + * Make sure you have your line numbers correct for error reporting, as it will match + * the line numbers up with the split tests! + */ +function batchedSingleLineTests< + TMessageIds extends string, + TOptions extends Readonly +>( + test: InvalidTestCase, +): InvalidTestCase[]; +function batchedSingleLineTests< + TMessageIds extends string, + TOptions extends Readonly +>( + options: ValidTestCase | InvalidTestCase, +): (ValidTestCase | InvalidTestCase)[] { + // eslint counts lines from 1 + const lineOffset = options.code[0] === '\n' ? 2 : 1; + return options.code + .trim() + .split('\n') + .map((code, i) => { + const lineNum = i + lineOffset; + const errors = + 'errors' in options + ? options.errors.filter(e => e.line === lineNum) + : []; + return { + ...options, + code, + errors: errors.map(e => ({ + ...e, + line: 1, + })), + }; + }); +} + +export { batchedSingleLineTests }; diff --git a/packages/eslint-plugin/src/util/deepMerge.ts b/packages/experimental-utils/src/eslint-utils/deepMerge.ts similarity index 100% rename from packages/eslint-plugin/src/util/deepMerge.ts rename to packages/experimental-utils/src/eslint-utils/deepMerge.ts diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts new file mode 100644 index 00000000000..c8069ca6fc2 --- /dev/null +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -0,0 +1,4 @@ +export * from './applyDefault'; +export * from './batchedSingleLineTests'; +export * from './RuleCreator'; +export * from './deepMerge'; diff --git a/packages/experimental-utils/src/index.ts b/packages/experimental-utils/src/index.ts new file mode 100644 index 00000000000..8b3a7f039ff --- /dev/null +++ b/packages/experimental-utils/src/index.ts @@ -0,0 +1,13 @@ +import * as ESLintUtils from './eslint-utils'; +import * as TSESLint from './ts-eslint'; + +export { ESLintUtils, TSESLint }; + +// for convenience's sake - export the types directly from here so consumers +// don't need to reference/install both packages in their code +export { + AST_NODE_TYPES, + AST_TOKEN_TYPES, + ParserServices, + TSESTree, +} from '@typescript-eslint/typescript-estree'; diff --git a/packages/experimental-utils/src/ts-eslint/AST.ts b/packages/experimental-utils/src/ts-eslint/AST.ts new file mode 100644 index 00000000000..1c77caafedf --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/AST.ts @@ -0,0 +1,18 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import { + TSESTree, + AST_TOKEN_TYPES, +} from '@typescript-eslint/typescript-estree'; + +namespace AST { + export type TokenType = AST_TOKEN_TYPES; + + export type Token = TSESTree.Token; + + export type SourceLocation = TSESTree.SourceLocation; + + export type Range = TSESTree.Range; +} + +export { AST }; diff --git a/packages/experimental-utils/src/ts-eslint/Linter.ts b/packages/experimental-utils/src/ts-eslint/Linter.ts new file mode 100644 index 00000000000..cff921e048c --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/Linter.ts @@ -0,0 +1,132 @@ +/* eslint-disable @typescript-eslint/no-namespace, no-redeclare */ + +import { TSESTree, ParserServices } from '@typescript-eslint/typescript-estree'; +import { RuleModule, RuleFix } from './Rule'; +import { Scope } from './Scope'; +import { SourceCode } from './SourceCode'; + +declare class Linter { + version: string; + + verify( + code: SourceCode | string, + config: Linter.Config, + filename?: string, + ): Linter.LintMessage[]; + verify( + code: SourceCode | string, + config: Linter.Config, + options: Linter.LintOptions, + ): Linter.LintMessage[]; + + verifyAndFix( + code: string, + config: Linter.Config, + filename?: string, + ): Linter.FixReport; + verifyAndFix( + code: string, + config: Linter.Config, + options: Linter.FixOptions, + ): Linter.FixReport; + + getSourceCode(): SourceCode; + + defineRule( + name: string, + rule: RuleModule, + ): void; + + defineRules( + rules: Record>, + ): void; + + getRules(): Map< + string, + RuleModule + >; + + defineParser(name: string, parser: Linter.ParserModule): void; +} + +namespace Linter { + export type Severity = 0 | 1 | 2; + export type RuleLevel = Severity | 'off' | 'warn' | 'error'; + + export interface RuleLevelAndOptions extends Array { + 0: RuleLevel; + } + + export interface Config { + rules?: { + [name: string]: RuleLevel | RuleLevelAndOptions; + }; + parser?: string; + parserOptions?: ParserOptions; + settings?: { [name: string]: any }; + env?: { [name: string]: boolean }; + globals?: { [name: string]: boolean }; + } + + export interface ParserOptions { + ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 2015 | 2016 | 2017 | 2018; + sourceType?: 'script' | 'module'; + ecmaFeatures?: { + globalReturn?: boolean; + impliedStrict?: boolean; + jsx?: boolean; + experimentalObjectRestSpread?: boolean; + [key: string]: any; + }; + [key: string]: any; + } + + export interface LintOptions { + filename?: string; + preprocess?: (code: string) => string[]; + postprocess?: (problemLists: LintMessage[][]) => LintMessage[]; + allowInlineConfig?: boolean; + reportUnusedDisableDirectives?: boolean; + } + + export interface LintMessage { + column: number; + line: number; + endColumn?: number; + endLine?: number; + ruleId: string | null; + message: string; + nodeType: string; + fatal?: true; + severity: Severity; + fix?: RuleFix; + source: string | null; + } + + export interface FixOptions extends LintOptions { + fix?: boolean; + } + + export interface FixReport { + fixed: boolean; + output: string; + messages: LintMessage[]; + } + + export type ParserModule = + | { + parse(text: string, options?: any): TSESTree.Program; + } + | { + parseForESLint(text: string, options?: any): ESLintParseResult; + }; + + export interface ESLintParseResult { + ast: TSESTree.Program; + parserServices?: ParserServices; + scopeManager?: Scope.ScopeManager; + visitorKeys?: SourceCode.VisitorKeys; + } +} + +export { Linter }; diff --git a/packages/experimental-utils/src/ts-eslint/ParserOptions.ts b/packages/experimental-utils/src/ts-eslint/ParserOptions.ts new file mode 100644 index 00000000000..d374ac57b91 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/ParserOptions.ts @@ -0,0 +1,21 @@ +export interface ParserOptions { + loc?: boolean; + comment?: boolean; + range?: boolean; + tokens?: boolean; + sourceType?: 'script' | 'module'; + ecmaVersion?: number; + ecmaFeatures?: { + globalReturn?: boolean; + jsx?: boolean; + }; + // ts-estree specific + filePath?: string; + project?: string | string[]; + useJSXTextNode?: boolean; + errorOnUnknownASTType?: boolean; + errorOnTypeScriptSyntacticAndSemanticIssues?: boolean; + tsconfigRootDir?: string; + extraFileExtensions?: string[]; + warnOnUnsupportedTypeScriptVersion?: boolean; +} diff --git a/packages/experimental-utils/src/ts-eslint/Rule.ts b/packages/experimental-utils/src/ts-eslint/Rule.ts new file mode 100644 index 00000000000..48162df0867 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/Rule.ts @@ -0,0 +1,400 @@ +import { ParserServices, TSESTree } from '@typescript-eslint/typescript-estree'; +import { JSONSchema4 } from 'json-schema'; +import { AST } from './AST'; +import { Linter } from './Linter'; +import { Scope } from './Scope'; +import { SourceCode } from './SourceCode'; + +interface RuleMetaDataDocs { + /** + * The general category the rule falls within + */ + category: + | 'Best Practices' + | 'Stylistic Issues' + | 'Variables' + | 'Possible Errors'; + /** + * Concise description of the rule + */ + description: string; + /** + * Extra information linking the rule to a tslint rule + */ + extraDescription?: string[]; + /** + * The recommendation level for the rule. + * Used by the build tools to generate the recommended config. + * Set to false to not include it as a recommendation + */ + recommended: 'error' | 'warn' | false; + /** + * The URL of the rule's docs + */ + url: string; +} +interface RuleMetaData { + /** + * True if the rule is deprecated, false otherwise + */ + deprecated?: boolean; + /** + * Documentation for the rule + */ + docs: RuleMetaDataDocs; + /** + * The fixer category. Omit if there is no fixer + */ + fixable?: 'code' | 'whitespace'; + /** + * A map of messages which the rule can report. + * The key is the messageId, and the string is the parameterised error string. + * See: https://eslint.org/docs/developer-guide/working-with-rules#messageids + */ + messages: Record; + /** + * The type of rule. + * - `"problem"` means the rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve. + * - `"suggestion"` means the rule is identifying something that could be done in a better way but no errors will occur if the code isn’t changed. + * - `"layout"` means the rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren’t specified in the AST. + */ + type: 'suggestion' | 'problem' | 'layout'; + /** + * The name of the rule this rule was replaced by, if it was deprecated. + */ + replacedBy?: string; + /** + * The options schema. Supply an empty array if there are no options. + */ + schema: JSONSchema4 | JSONSchema4[]; +} + +interface RuleFix { + range: AST.Range; + text: string; +} + +interface RuleFixer { + insertTextAfter( + nodeOrToken: TSESTree.Node | TSESTree.Token, + text: string, + ): RuleFix; + + insertTextAfterRange(range: AST.Range, text: string): RuleFix; + + insertTextBefore( + nodeOrToken: TSESTree.Node | TSESTree.Token, + text: string, + ): RuleFix; + + insertTextBeforeRange(range: AST.Range, text: string): RuleFix; + + remove(nodeOrToken: TSESTree.Node | TSESTree.Token): RuleFix; + + removeRange(range: AST.Range): RuleFix; + + replaceText( + nodeOrToken: TSESTree.Node | TSESTree.Token, + text: string, + ): RuleFix; + + replaceTextRange(range: AST.Range, text: string): RuleFix; +} + +type ReportFixFunction = ( + fixer: RuleFixer, +) => null | RuleFix | RuleFix[] | IterableIterator; + +interface ReportDescriptor { + /** + * The parameters for the message string associated with `messageId`. + */ + data?: Record; + /** + * The fixer function. + */ + fix?: ReportFixFunction | null; + /** + * The messageId which is being reported. + */ + messageId: TMessageIds; + /** + * The Node or AST Token which the report is being attached to + */ + node: TSESTree.Node | TSESTree.Comment | TSESTree.Token; + /** + * An override of the location of the report + */ + loc?: TSESTree.SourceLocation | TSESTree.LineAndColumnData; +} + +interface RuleContext< + TMessageIds extends string, + TOptions extends Readonly +> { + /** + * The rule ID. + */ + id: string; + /** + * An array of the configured options for this rule. + * This array does not include the rule severity. + */ + options: TOptions; + /** + * The shared settings from configuration. + * We do not have any shared settings in this plugin. + */ + settings: {}; + /** + * The name of the parser from configuration. + */ + parserPath: string; + /** + * The parser options configured for this run + */ + parserOptions: Linter.ParserOptions; + /** + * An object containing parser-provided services for rules + */ + parserServices?: ParserServices; + + /** + * Returns an array of the ancestors of the currently-traversed node, starting at + * the root of the AST and continuing through the direct parent of the current node. + * This array does not include the currently-traversed node itself. + */ + getAncestors(): TSESTree.Node[]; + + /** + * Returns a list of variables declared by the given node. + * This information can be used to track references to variables. + */ + getDeclaredVariables(node: TSESTree.Node): Scope.Variable[]; + + /** + * Returns the filename associated with the source. + */ + getFilename(): string; + + /** + * Returns the scope of the currently-traversed node. + * This information can be used track references to variables. + */ + getScope(): Scope.Scope; + + /** + * Returns a SourceCode object that you can use to work with the source that + * was passed to ESLint. + */ + getSourceCode(): SourceCode; + + /** + * Marks a variable with the given name in the current scope as used. + * This affects the no-unused-vars rule. + */ + markVariableAsUsed(name: string): boolean; + + /** + * Reports a problem in the code. + */ + report(descriptor: ReportDescriptor): void; +} + +// This isn't the correct signature, but it makes it easier to do custom unions within reusable listneers +// never will break someone's code unless they specifically type the function argument +type RuleFunction = (node: T) => void; + +interface RuleListener { + [nodeSelector: string]: RuleFunction | undefined; + ArrayExpression?: RuleFunction; + ArrayPattern?: RuleFunction; + ArrowFunctionExpression?: RuleFunction; + AssignmentPattern?: RuleFunction; + AssignmentExpression?: RuleFunction; + AwaitExpression?: RuleFunction; + BlockStatement?: RuleFunction; + BreakStatement?: RuleFunction; + CallExpression?: RuleFunction; + CatchClause?: RuleFunction; + ClassBody?: RuleFunction; + ClassDeclaration?: RuleFunction; + ClassExpression?: RuleFunction; + ClassProperty?: RuleFunction; + Comment?: RuleFunction; + ConditionalExpression?: RuleFunction; + ContinueStatement?: RuleFunction; + DebuggerStatement?: RuleFunction; + Decorator?: RuleFunction; + DoWhileStatement?: RuleFunction; + EmptyStatement?: RuleFunction; + ExportAllDeclaration?: RuleFunction; + ExportDefaultDeclaration?: RuleFunction; + ExportNamedDeclaration?: RuleFunction; + ExportSpecifier?: RuleFunction; + ExpressionStatement?: RuleFunction; + ForInStatement?: RuleFunction; + ForOfStatement?: RuleFunction; + ForStatement?: RuleFunction; + Identifier?: RuleFunction; + IfStatement?: RuleFunction; + Import?: RuleFunction; + ImportDeclaration?: RuleFunction; + ImportDefaultSpecifier?: RuleFunction; + ImportNamespaceSpecifier?: RuleFunction; + ImportSpecifier?: RuleFunction; + JSXAttribute?: RuleFunction; + JSXClosingElement?: RuleFunction; + JSXClosingFragment?: RuleFunction; + JSXElement?: RuleFunction; + JSXEmptyExpression?: RuleFunction; + JSXExpressionContainer?: RuleFunction; + JSXFragment?: RuleFunction; + JSXIdentifier?: RuleFunction; + JSXMemberExpression?: RuleFunction; + JSXOpeningElement?: RuleFunction; + JSXOpeningFragment?: RuleFunction; + JSXSpreadAttribute?: RuleFunction; + JSXSpreadChild?: RuleFunction; + JSXText?: RuleFunction; + LabeledStatement?: RuleFunction; + MemberExpression?: RuleFunction; + MetaProperty?: RuleFunction; + MethodDefinition?: RuleFunction; + NewExpression?: RuleFunction; + ObjectExpression?: RuleFunction; + ObjectPattern?: RuleFunction; + Program?: RuleFunction; + Property?: RuleFunction; + RestElement?: RuleFunction; + ReturnStatement?: RuleFunction; + SequenceExpression?: RuleFunction; + SpreadElement?: RuleFunction; + Super?: RuleFunction; + SwitchCase?: RuleFunction; + SwitchStatement?: RuleFunction; + TaggedTemplateExpression?: RuleFunction; + TemplateElement?: RuleFunction; + TemplateLiteral?: RuleFunction; + ThisExpression?: RuleFunction; + ThrowStatement?: RuleFunction; + Token?: RuleFunction; + TryStatement?: RuleFunction; + TSAbstractKeyword?: RuleFunction; + TSAbstractMethodDefinition?: RuleFunction< + TSESTree.TSAbstractMethodDefinition + >; + TSAnyKeyword?: RuleFunction; + TSArrayType?: RuleFunction; + TSAsExpression?: RuleFunction; + TSAsyncKeyword?: RuleFunction; + TSBigIntKeyword?: RuleFunction; + TSBooleanKeyword?: RuleFunction; + TSCallSignatureDeclaration?: RuleFunction< + TSESTree.TSCallSignatureDeclaration + >; + TSConditionalType?: RuleFunction; + TSConstructSignatureDeclaration?: RuleFunction< + TSESTree.TSConstructSignatureDeclaration + >; + TSDeclareKeyword?: RuleFunction; + TSDeclareFunction?: RuleFunction; + TSEnumDeclaration?: RuleFunction; + TSEnumMember?: RuleFunction; + TSExportAssignment?: RuleFunction; + TSExportKeyword?: RuleFunction; + TSExternalModuleReference?: RuleFunction; + TSImportEqualsDeclaration?: RuleFunction; + TSImportType?: RuleFunction; + TSIndexedAccessType?: RuleFunction; + TSIndexSignature?: RuleFunction; + TSInferType?: RuleFunction; + TSInterfaceBody?: RuleFunction; + TSInterfaceDeclaration?: RuleFunction; + TSIntersectionType?: RuleFunction; + TSLiteralType?: RuleFunction; + TSMappedType?: RuleFunction; + TSMethodSignature?: RuleFunction; + TSModuleBlock?: RuleFunction; + TSModuleDeclaration?: RuleFunction; + TSNamespaceExportDeclaration?: RuleFunction< + TSESTree.TSNamespaceExportDeclaration + >; + TSNeverKeyword?: RuleFunction; + TSNonNullExpression?: RuleFunction; + TSNullKeyword?: RuleFunction; + TSNumberKeyword?: RuleFunction; + TSObjectKeyword?: RuleFunction; + TSOptionalType?: RuleFunction; + TSParameterProperty?: RuleFunction; + TSParenthesizedType?: RuleFunction; + TSPrivateKeyword?: RuleFunction; + TSPropertySignature?: RuleFunction; + TSProtectedKeyword?: RuleFunction; + TSPublicKeyword?: RuleFunction; + TSQualifiedName?: RuleFunction; + TSReadonlyKeyword?: RuleFunction; + TSRestType?: RuleFunction; + TSStaticKeyword?: RuleFunction; + TSStringKeyword?: RuleFunction; + TSSymbolKeyword?: RuleFunction; + TSThisType?: RuleFunction; + TSTupleType?: RuleFunction; + TSTypeAliasDeclaration?: RuleFunction; + TSTypeAnnotation?: RuleFunction; + TSTypeAssertion?: RuleFunction; + TSTypeLiteral?: RuleFunction; + TSTypeOperator?: RuleFunction; + TSTypeParameter?: RuleFunction; + TSTypeParameterDeclaration?: RuleFunction< + TSESTree.TSTypeParameterDeclaration + >; + TSTypeParameterInstantiation?: RuleFunction< + TSESTree.TSTypeParameterInstantiation + >; + TSTypePredicate?: RuleFunction; + TSTypeQuery?: RuleFunction; + TSTypeReference?: RuleFunction; + TSUndefinedKeyword?: RuleFunction; + TSUnionType?: RuleFunction; + TSUnknownKeyword?: RuleFunction; + TSVoidKeyword?: RuleFunction; + UnaryExpression?: RuleFunction; + UpdateExpression?: RuleFunction; + VariableDeclaration?: RuleFunction; + VariableDeclarator?: RuleFunction; + WhileStatement?: RuleFunction; + WithStatement?: RuleFunction; + YieldExpression?: RuleFunction; +} + +interface RuleModule< + TMessageIds extends string, + TOptions extends Readonly, + // for extending base rules + TRuleListener extends RuleListener = RuleListener +> { + /** + * Metadata about the rule + */ + meta: RuleMetaData; + + /** + * Function which returns an object with methods that ESLint calls to “visit” + * nodes while traversing the abstract syntax tree. + */ + create(context: RuleContext): TRuleListener; +} + +export { + ReportDescriptor, + ReportFixFunction, + RuleContext, + RuleFix, + RuleFixer, + RuleFunction, + RuleListener, + RuleMetaData, + RuleMetaDataDocs, + RuleModule, +}; diff --git a/packages/experimental-utils/src/ts-eslint/RuleTester.ts b/packages/experimental-utils/src/ts-eslint/RuleTester.ts new file mode 100644 index 00000000000..fe9b4b80396 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/RuleTester.ts @@ -0,0 +1,76 @@ +import { + AST_NODE_TYPES, + AST_TOKEN_TYPES, +} from '@typescript-eslint/typescript-estree'; +import { ParserOptions } from './ParserOptions'; +import { RuleModule } from './Rule'; + +interface ValidTestCase> { + code: string; + options?: TOptions; + filename?: string; + parserOptions?: ParserOptions; + settings?: Record; + parser?: string; + globals?: Record; + env?: { + browser?: boolean; + }; +} + +interface InvalidTestCase< + TMessageIds extends string, + TOptions extends Readonly +> extends ValidTestCase { + errors: TestCaseError[]; + output?: string | null; +} + +interface TestCaseError { + messageId: TMessageIds; + data?: Record; + type?: AST_NODE_TYPES | AST_TOKEN_TYPES; + line?: number; + column?: number; +} + +interface RunTests< + TMessageIds extends string, + TOptions extends Readonly +> { + // RuleTester.run also accepts strings for valid cases + valid: (ValidTestCase | string)[]; + invalid: InvalidTestCase[]; +} + +interface RunTests< + TMessageIds extends string, + TOptions extends Readonly +> { + // RuleTester.run also accepts strings for valid cases + valid: (ValidTestCase | string)[]; + invalid: InvalidTestCase[]; +} +interface RuleTesterConfig { + parser: '@typescript-eslint/parser'; + parserOptions?: ParserOptions; +} +interface RuleTester { + // eslint-disable-next-line @typescript-eslint/no-misused-new + new (config?: RuleTesterConfig): RuleTester; + + run>( + name: string, + rule: RuleModule, + tests: RunTests, + ): void; +} + +export { + InvalidTestCase, + RuleTester, + RuleTesterConfig, + RunTests, + TestCaseError, + ValidTestCase, +}; diff --git a/packages/experimental-utils/src/ts-eslint/Scope.ts b/packages/experimental-utils/src/ts-eslint/Scope.ts new file mode 100644 index 00000000000..e6922d9df19 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/Scope.ts @@ -0,0 +1,106 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import { TSESTree } from '@typescript-eslint/typescript-estree'; + +namespace Scope { + export interface ScopeManager { + scopes: Scope[]; + globalScope: Scope | null; + + acquire(node: TSESTree.Node, inner?: boolean): Scope | null; + + getDeclaredVariables(node: TSESTree.Node): Variable[]; + } + + export interface Reference { + identifier: TSESTree.Identifier; + from: Scope; + resolved: Variable | null; + writeExpr: TSESTree.Node | null; + init: boolean; + + isWrite(): boolean; + + isRead(): boolean; + + isWriteOnly(): boolean; + + isReadOnly(): boolean; + + isReadWrite(): boolean; + } + + export interface Variable { + name: string; + identifiers: TSESTree.Identifier[]; + references: Reference[]; + defs: Definition[]; + scope: Scope; + eslintUsed?: boolean; + } + + export interface Scope { + type: + | 'block' + | 'catch' + | 'class' + | 'for' + | 'function' + | 'function-expression-name' + | 'global' + | 'module' + | 'switch' + | 'with' + | 'TDZ'; + isStrict: boolean; + upper: Scope | null; + childScopes: Scope[]; + variableScope: Scope; + block: TSESTree.Node; + variables: Variable[]; + set: Map; + references: Reference[]; + through: Reference[]; + functionExpressionScope: boolean; + } + + export type DefinitionType = + | { type: 'CatchClause'; node: TSESTree.CatchClause; parent: null } + | { + type: 'ClassName'; + node: TSESTree.ClassDeclaration | TSESTree.ClassExpression; + parent: null; + } + | { + type: 'FunctionName'; + node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression; + parent: null; + } + | { type: 'ImplicitGlobalVariable'; node: TSESTree.Program; parent: null } + | { + type: 'ImportBinding'; + node: + | TSESTree.ImportSpecifier + | TSESTree.ImportDefaultSpecifier + | TSESTree.ImportNamespaceSpecifier; + parent: TSESTree.ImportDeclaration; + } + | { + type: 'Parameter'; + node: + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression + | TSESTree.ArrowFunctionExpression; + parent: null; + } + | { type: 'TDZ'; node: any; parent: null } + | { + type: 'Variable'; + node: TSESTree.VariableDeclarator; + parent: TSESTree.VariableDeclaration; + }; + + export type Definition = DefinitionType & { name: TSESTree.Identifier }; +} + +export { Scope }; diff --git a/packages/experimental-utils/src/ts-eslint/SourceCode.ts b/packages/experimental-utils/src/ts-eslint/SourceCode.ts new file mode 100644 index 00000000000..abf3c3e6e8f --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/SourceCode.ts @@ -0,0 +1,193 @@ +/* eslint-disable @typescript-eslint/no-namespace, no-redeclare */ + +import { ParserServices, TSESTree } from '@typescript-eslint/typescript-estree'; +import { Scope } from './Scope'; + +namespace SourceCode { + export interface Program extends TSESTree.Program { + comments: TSESTree.Comment[]; + tokens: TSESTree.Token[]; + } + + export interface Config { + text: string; + ast: Program; + parserServices?: ParserServices; + scopeManager?: Scope.ScopeManager; + visitorKeys?: VisitorKeys; + } + + export interface VisitorKeys { + [nodeType: string]: string[]; + } + + export type FilterPredicate = ( + tokenOrComment: TSESTree.Token | TSESTree.Comment, + ) => boolean; + + export type CursorWithSkipOptions = + | number + | FilterPredicate + | { + includeComments?: boolean; + filter?: FilterPredicate; + skip?: number; + }; + + export type CursorWithCountOptions = + | number + | FilterPredicate + | { + includeComments?: boolean; + filter?: FilterPredicate; + count?: number; + }; +} + +declare class SourceCode { + text: string; + ast: SourceCode.Program; + lines: string[]; + hasBOM: boolean; + parserServices: ParserServices; + scopeManager: Scope.ScopeManager; + visitorKeys: SourceCode.VisitorKeys; + tokensAndComments: (TSESTree.Comment | TSESTree.Token)[]; + + constructor(text: string, ast: SourceCode.Program); + constructor(config: SourceCode.Config); + + static splitLines(text: string): string[]; + + getText( + node?: TSESTree.Node, + beforeCount?: number, + afterCount?: number, + ): string; + + getLines(): string[]; + + getAllComments(): TSESTree.Comment[]; + + getComments( + node: TSESTree.Node, + ): { leading: TSESTree.Comment[]; trailing: TSESTree.Comment[] }; + + getJSDocComment(node: TSESTree.Node): TSESTree.Node | TSESTree.Token | null; + + getNodeByRangeIndex(index: number): TSESTree.Node | null; + + isSpaceBetweenTokens(first: TSESTree.Token, second: TSESTree.Token): boolean; + + getLocFromIndex(index: number): TSESTree.LineAndColumnData; + + getIndexFromLoc(location: TSESTree.LineAndColumnData): number; + + // Inherited methods from TokenStore + // --------------------------------- + + getTokenByRangeStart( + offset: number, + options?: { includeComments?: boolean }, + ): TSESTree.Token | null; + + getFirstToken( + node: TSESTree.Node, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getFirstTokens( + node: TSESTree.Node, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getLastToken( + node: TSESTree.Node, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getLastTokens( + node: TSESTree.Node, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getTokenBefore( + node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getTokensBefore( + node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getTokenAfter( + node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getTokensAfter( + node: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getFirstTokenBetween( + left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getFirstTokensBetween( + left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getLastTokenBetween( + left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithSkipOptions, + ): TSESTree.Token | null; + + getLastTokensBetween( + left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + options?: SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getTokensBetween( + left: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + right: TSESTree.Node | TSESTree.Token | TSESTree.Comment, + padding?: + | number + | SourceCode.FilterPredicate + | SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + getTokens( + node: TSESTree.Node, + beforeCount?: number, + afterCount?: number, + ): TSESTree.Token[]; + getTokens( + node: TSESTree.Node, + options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions, + ): TSESTree.Token[]; + + commentsExistBetween( + left: TSESTree.Node | TSESTree.Token, + right: TSESTree.Node | TSESTree.Token, + ): boolean; + + getCommentsBefore( + nodeOrToken: TSESTree.Node | TSESTree.Token, + ): TSESTree.Comment[]; + + getCommentsAfter( + nodeOrToken: TSESTree.Node | TSESTree.Token, + ): TSESTree.Comment[]; + + getCommentsInside(node: TSESTree.Node): TSESTree.Comment[]; +} + +export { SourceCode }; diff --git a/packages/experimental-utils/src/ts-eslint/index.ts b/packages/experimental-utils/src/ts-eslint/index.ts new file mode 100644 index 00000000000..05a5b0b54ad --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint/index.ts @@ -0,0 +1,7 @@ +export * from './AST'; +export * from './Linter'; +export * from './ParserOptions'; +export * from './Rule'; +export * from './RuleTester'; +export * from './Scope'; +export * from './SourceCode'; diff --git a/packages/experimental-utils/tests/eslint-utils/applyDefault.test.ts b/packages/experimental-utils/tests/eslint-utils/applyDefault.test.ts new file mode 100644 index 00000000000..3ff4a843ec2 --- /dev/null +++ b/packages/experimental-utils/tests/eslint-utils/applyDefault.test.ts @@ -0,0 +1,58 @@ +import assert from 'assert'; + +import * as util from '../../src/eslint-utils/applyDefault'; + +describe('applyDefault', () => { + it('returns a clone of the default if no options given', () => { + const defaults = [ + { + prop: 'setting', + }, + ]; + const user = null; + const result = util.applyDefault(defaults, user); + + assert.deepStrictEqual(result, defaults); + assert.notStrictEqual(result, defaults); + }); + + it('returns applies a deepMerge to each element in the array', () => { + const defaults = [ + { + prop: 'setting1', + other: 'other', + }, + { + prop: 'setting2', + }, + ] as Record[]; + const user = [ + { + prop: 'new', + other: 'something', + }, + ] as Record[]; + const result = util.applyDefault(defaults, user); + + assert.deepStrictEqual(result, [ + { + prop: 'new', + other: 'something', + }, + { + prop: 'setting2', + }, + ]); + assert.notStrictEqual(result, defaults); + assert.notStrictEqual(result, user); + }); + + it('returns a brand new array', () => { + const defaults: undefined[] = []; + const user: undefined[] = []; + const result = util.applyDefault(defaults, user); + + assert.notStrictEqual(result, defaults); + assert.notStrictEqual(result, user); + }); +}); diff --git a/packages/experimental-utils/tests/eslint-utils/deepMerge.test.ts b/packages/experimental-utils/tests/eslint-utils/deepMerge.test.ts new file mode 100644 index 00000000000..27e55c996a9 --- /dev/null +++ b/packages/experimental-utils/tests/eslint-utils/deepMerge.test.ts @@ -0,0 +1,60 @@ +import assert from 'assert'; + +import * as util from '../../src/eslint-utils/deepMerge'; + +describe('deepMerge', () => { + it('creates a brand new object', () => { + const a = {}; + const b = {}; + const result = util.deepMerge(a, b); + + assert.notStrictEqual(result, a); + assert.notStrictEqual(result, b); + }); + + it('deeply merges objects', () => { + const a = { + stringA1: 'asdf', + numberA1: 1, + boolA1: true, + arrayA1: [1, 2, 3], + objA1: { + stringA2: 'fsda', + numberA2: 2, + boolA2: false, + arrayA2: [3, 2, 1], + objA2: {}, + }, + }; + const b = { + stringB1: 'asdf', + numberB1: 1, + boolB1: true, + arrayB1: [1, 2, 3], + objB1: { + stringB2: 'fsda', + numberB2: 2, + boolB2: false, + arrayB2: [3, 2, 1], + objB2: {}, + }, + }; + + assert.deepStrictEqual(util.deepMerge(a, b), Object.assign({}, a, b)); + }); + + it('deeply overwrites properties in the first one with the second', () => { + const a = { + prop1: { + prop2: 'hi', + }, + }; + const b = { + prop1: { + prop2: 'bye', + }, + }; + + assert.deepStrictEqual(util.deepMerge(a, b), b); + }); +}); diff --git a/packages/experimental-utils/tsconfig.build.json b/packages/experimental-utils/tsconfig.build.json new file mode 100644 index 00000000000..0ce1565b0d0 --- /dev/null +++ b/packages/experimental-utils/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "resolveJsonModule": true + }, + "include": ["src"] +} diff --git a/packages/experimental-utils/tsconfig.json b/packages/experimental-utils/tsconfig.json new file mode 100644 index 00000000000..f469d044ef4 --- /dev/null +++ b/packages/experimental-utils/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "resolveJsonModule": true + }, + "include": ["src", "typings", "tests", "tools"] +} diff --git a/packages/parser/package.json b/packages/parser/package.json index 5beae5aa527..a982469625f 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -38,11 +38,11 @@ }, "dependencies": { "@typescript-eslint/typescript-estree": "1.7.0", + "@typescript-eslint/experimental-utils": "1.7.0", "eslint-scope": "^4.0.0", "eslint-visitor-keys": "^1.0.0" }, "devDependencies": { - "@types/eslint": "^4.16.5", "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/shared-fixtures": "1.7.0" } diff --git a/packages/parser/src/analyze-scope.ts b/packages/parser/src/analyze-scope.ts index 92390dbf0d3..b131104ce87 100644 --- a/packages/parser/src/analyze-scope.ts +++ b/packages/parser/src/analyze-scope.ts @@ -1,16 +1,17 @@ -import { ScopeManager } from './scope/scope-manager'; +import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; import { Definition, ParameterDefinition } from 'eslint-scope/lib/definition'; +import { + PatternVisitorCallback, + PatternVisitorOptions, +} from 'eslint-scope/lib/options'; import OriginalPatternVisitor from 'eslint-scope/lib/pattern-visitor'; import Reference from 'eslint-scope/lib/reference'; import OriginalReferencer from 'eslint-scope/lib/referencer'; import { getKeys as fallback } from 'eslint-visitor-keys'; + import { ParserOptions } from './parser-options'; +import { ScopeManager } from './scope/scope-manager'; import { visitorKeys as childVisitorKeys } from './visitor-keys'; -import { - PatternVisitorCallback, - PatternVisitorOptions, -} from 'eslint-scope/lib/options'; -import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; /** * Define the override function of `Scope#__define` for global augmentation. diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index fa5aa39dfdc..71478ee2ad6 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -1,14 +1,16 @@ -import traverser from 'eslint/lib/util/traverser'; import { AST_NODE_TYPES, parseAndGenerateServices, - ParserOptions as ParserOptionsTsESTree, + TSESTreeOptions, ParserServices, } from '@typescript-eslint/typescript-estree'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; +import traverser from 'eslint/lib/util/traverser'; import { analyzeScope } from './analyze-scope'; -import { ParserOptions } from './parser-options'; import { visitorKeys } from './visitor-keys'; +type ParserOptions = TSESLint.ParserOptions; + // note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder const packageJSON = require('../package.json'); @@ -57,7 +59,7 @@ export function parseForESLint( options.ecmaFeatures = {}; } - const parserOptions: ParserOptionsTsESTree = {}; + const parserOptions: TSESTreeOptions = {}; Object.assign(parserOptions, options, { useJSXTextNode: validateBoolean(options.useJSXTextNode, true), jsx: validateBoolean(options.ecmaFeatures.jsx), diff --git a/packages/parser/src/scope/scope-manager.ts b/packages/parser/src/scope/scope-manager.ts index fcdb88175cc..7b7e53c9e84 100644 --- a/packages/parser/src/scope/scope-manager.ts +++ b/packages/parser/src/scope/scope-manager.ts @@ -1,10 +1,9 @@ import { TSESTree } from '@typescript-eslint/typescript-estree'; - import EslintScopeManager, { ScopeManagerOptions, } from 'eslint-scope/lib/scope-manager'; -import { EmptyFunctionScope, EnumScope } from './scopes'; import { Scope } from 'eslint-scope/lib/scope'; +import { EmptyFunctionScope, EnumScope } from './scopes'; /** * based on eslint-scope diff --git a/packages/parser/src/scope/scopes.ts b/packages/parser/src/scope/scopes.ts index f5c27a69f79..9dff225a721 100644 --- a/packages/parser/src/scope/scopes.ts +++ b/packages/parser/src/scope/scopes.ts @@ -1,6 +1,6 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; import { Scope } from 'eslint-scope/lib/scope'; import { ScopeManager } from './scope-manager'; -import { TSESTree } from '@typescript-eslint/typescript-estree'; /** The scope class for enum. */ export class EnumScope extends Scope { diff --git a/packages/parser/tests/lib/parser.ts b/packages/parser/tests/lib/parser.ts index 47d816fe048..c3c205509dd 100644 --- a/packages/parser/tests/lib/parser.ts +++ b/packages/parser/tests/lib/parser.ts @@ -2,6 +2,8 @@ import * as typescriptESTree from '@typescript-eslint/typescript-estree'; import { parse, parseForESLint, Syntax } from '../../src/parser'; import * as scope from '../../src/analyze-scope'; +const { AST_NODE_TYPES } = typescriptESTree; + describe('parser', () => { it('parse() should return just the AST from parseForESLint()', () => { const code = 'const valid = true;'; @@ -60,8 +62,8 @@ describe('parser', () => { }); }); - it('Syntax should contain a frozen object of typescriptESTree.AST_NODE_TYPES', () => { - expect(Syntax).toEqual(typescriptESTree.AST_NODE_TYPES); + it('Syntax should contain a frozen object of AST_NODE_TYPES', () => { + expect(Syntax).toEqual(AST_NODE_TYPES); expect( () => ((Syntax as any).ArrayExpression = 'foo'), ).toThrowErrorMatchingInlineSnapshot( diff --git a/packages/parser/typings/eslint-scope.d.ts b/packages/parser/typings/eslint-scope.d.ts index 62172fd30b7..ec876c63716 100644 --- a/packages/parser/typings/eslint-scope.d.ts +++ b/packages/parser/typings/eslint-scope.d.ts @@ -8,7 +8,7 @@ //----------------------------------------------------------------------- declare module 'eslint-scope/lib/options' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; export type PatternVisitorCallback = ( pattern: TSESTree.Identifier, info: { @@ -31,7 +31,7 @@ declare module 'eslint-scope/lib/options' { } declare module 'eslint-scope/lib/variable' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import Reference from 'eslint-scope/lib/reference'; import { Definition } from 'eslint-scope/lib/definition'; @@ -45,7 +45,7 @@ declare module 'eslint-scope/lib/variable' { } declare module 'eslint-scope/lib/definition' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; export class Definition { type: string; @@ -78,7 +78,7 @@ declare module 'eslint-scope/lib/definition' { declare module 'eslint-scope/lib/pattern-visitor' { import ScopeManager from 'eslint-scope/lib/scope-manager'; - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import { PatternVisitorCallback, PatternVisitorOptions, @@ -115,7 +115,7 @@ declare module 'eslint-scope/lib/pattern-visitor' { declare module 'eslint-scope/lib/referencer' { import { Scope } from 'eslint-scope/lib/scope'; import ScopeManager from 'eslint-scope/lib/scope-manager'; - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import { PatternVisitorCallback, PatternVisitorOptions, @@ -192,7 +192,7 @@ declare module 'eslint-scope/lib/referencer' { } declare module 'eslint-scope/lib/scope' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import Reference from 'eslint-scope/lib/reference'; import Variable from 'eslint-scope/lib/variable'; import ScopeManager from 'eslint-scope/lib/scope-manager'; @@ -378,7 +378,7 @@ declare module 'eslint-scope/lib/scope' { } declare module 'eslint-scope/lib/reference' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import { Scope } from 'eslint-scope/lib/scope'; import Variable from 'eslint-scope/lib/variable'; @@ -402,7 +402,7 @@ declare module 'eslint-scope/lib/reference' { } declare module 'eslint-scope/lib/scope-manager' { - import { TSESTree } from '@typescript-eslint/typescript-estree'; + import { TSESTree } from '@typescript-eslint/experimental-utils'; import { Scope } from 'eslint-scope/lib/scope'; import Variable from 'eslint-scope/lib/variable'; diff --git a/packages/typescript-estree/src/ast-converter.ts b/packages/typescript-estree/src/ast-converter.ts index 72ff381f87e..25d291dee4c 100644 --- a/packages/typescript-estree/src/ast-converter.ts +++ b/packages/typescript-estree/src/ast-converter.ts @@ -1,11 +1,11 @@ +import { SourceFile } from 'typescript'; import { convertError, Converter } from './convert'; import { convertComments } from './convert-comments'; import { convertTokens } from './node-utils'; -import ts from 'typescript'; import { Extra } from './parser-options'; export default function astConverter( - ast: ts.SourceFile, + ast: SourceFile, extra: Extra, shouldPreserveNodeMaps: boolean, ) { diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index 5474a71d66d..026500da7d3 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -1,4 +1,4 @@ -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import { getLocFor, getNodeContainer } 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 1c70dbf8642..e0e535c774a 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -1,4 +1,4 @@ -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import { canContainDirective, createError, @@ -18,8 +18,7 @@ import { isOptional, unescapeStringLiteralText, } from './node-utils'; -import { AST_NODE_TYPES, TSESTree } from './ts-estree'; -import { TSNode } from './ts-nodes'; +import { AST_NODE_TYPES, TSESTree, TSNode } from './ts-estree'; const SyntaxKind = ts.SyntaxKind; diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index 80793df4e2d..d682bb091b4 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -1,5 +1,5 @@ -import ts from 'typescript'; 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 { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from './ts-estree'; const SyntaxKind = ts.SyntaxKind; diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts index 5d1821bd50c..585effea268 100644 --- a/packages/typescript-estree/src/parser-options.ts +++ b/packages/typescript-estree/src/parser-options.ts @@ -1,17 +1,16 @@ import { Program } from 'typescript'; -import { Token, Comment, Node } from './ts-estree/ts-estree'; -import { TSNode } from './ts-nodes'; +import { TSESTree, TSNode } from './ts-estree'; export interface Extra { errorOnUnknownASTType: boolean; errorOnTypeScriptSyntacticAndSemanticIssues: boolean; useJSXTextNode: boolean; - tokens: null | Token[]; + tokens: null | TSESTree.Token[]; comment: boolean; code: string; range: boolean; loc: boolean; - comments: Comment[]; + comments: TSESTree.Comment[]; strict: boolean; jsx: boolean; log: Function; @@ -21,7 +20,7 @@ export interface Extra { preserveNodeMaps?: boolean; } -export interface ParserOptions { +export interface TSESTreeOptions { range?: boolean; loc?: boolean; tokens?: boolean; @@ -38,6 +37,8 @@ export interface ParserOptions { preserveNodeMaps?: boolean; } +// This lets us use generics to type the return value, and removes the need to +// handle the undefined type in the get method export interface ParserWeakMap { get(key: TKey): TValue; has(key: any): boolean; @@ -45,6 +46,6 @@ export interface ParserWeakMap { export interface ParserServices { program: Program | undefined; - esTreeNodeToTSNodeMap: ParserWeakMap | undefined; - tsNodeToESTreeNodeMap: ParserWeakMap | undefined; + esTreeNodeToTSNodeMap: ParserWeakMap | undefined; + tsNodeToESTreeNodeMap: ParserWeakMap | undefined; } diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 2f4003c8e3d..1a963859d96 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -1,15 +1,15 @@ -import { - calculateProjectParserOptions, - createProgram, -} from './tsconfig-parser'; import semver from 'semver'; -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import convert from './ast-converter'; import { convertError } from './convert'; import { firstDefined } from './node-utils'; -import { TSESTree } from './ts-estree'; -import { Extra, ParserOptions, ParserServices } from './parser-options'; +import { Extra, TSESTreeOptions, ParserServices } from './parser-options'; import { getFirstSemanticOrSyntacticError } from './semantic-errors'; +import { TSESTree } from './ts-estree'; +import { + calculateProjectParserOptions, + createProgram, +} from './tsconfig-parser'; /** * This needs to be kept in sync with the top-level README.md in the @@ -66,7 +66,7 @@ function resetExtra(): void { * @param options The config object * @returns If found, returns the source file corresponding to the code and the containing program */ -function getASTFromProject(code: string, options: ParserOptions) { +function getASTFromProject(code: string, options: TSESTreeOptions) { return firstDefined( calculateProjectParserOptions( code, @@ -87,7 +87,7 @@ function getASTFromProject(code: string, options: ParserOptions) { * @param options The config object * @returns If found, returns the source file corresponding to the code and the containing program */ -function getASTAndDefaultProject(code: string, options: ParserOptions) { +function getASTAndDefaultProject(code: string, options: TSESTreeOptions) { const fileName = options.filePath || getFileName(options); const program = createProgram(code, fileName, extra); const ast = program && program.getSourceFile(fileName); @@ -159,7 +159,7 @@ function createNewProgram(code: string) { */ function getProgramAndAST( code: string, - options: ParserOptions, + options: TSESTreeOptions, shouldProvideParserServices: boolean, ) { return ( @@ -169,7 +169,7 @@ function getProgramAndAST( ); } -function applyParserOptionsToExtra(options: ParserOptions): void { +function applyParserOptionsToExtra(options: TSESTreeOptions): void { /** * Track range information in the AST */ @@ -277,12 +277,12 @@ function warnAboutTSVersion(): void { // Parser //------------------------------------------------------------------------------ -type AST = TSESTree.Program & +type AST = TSESTree.Program & (T['range'] extends true ? { range: [number, number] } : {}) & (T['tokens'] extends true ? { tokens: TSESTree.Token[] } : {}) & (T['comment'] extends true ? { comments: TSESTree.Comment[] } : {}); -export interface ParseAndGenerateServicesResult { +export interface ParseAndGenerateServicesResult { ast: AST; services: ParserServices; } @@ -293,7 +293,7 @@ export interface ParseAndGenerateServicesResult { export const version: string = require('../package.json').version; -export function parse( +export function parse( code: string, options?: T, ): AST { @@ -344,7 +344,7 @@ export function parse( } export function parseAndGenerateServices< - T extends ParserOptions = ParserOptions + T extends TSESTreeOptions = TSESTreeOptions >(code: string, options: T): ParseAndGenerateServicesResult { /** * Reset the parse configuration @@ -427,5 +427,5 @@ export function parseAndGenerateServices< }; } -export { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from './ts-estree'; -export { ParserOptions, ParserServices }; +export { TSESTreeOptions, ParserServices }; +export * from './ts-estree'; diff --git a/packages/typescript-estree/src/semantic-errors.ts b/packages/typescript-estree/src/semantic-errors.ts index 14568aba123..f31eb634068 100644 --- a/packages/typescript-estree/src/semantic-errors.ts +++ b/packages/typescript-estree/src/semantic-errors.ts @@ -1,4 +1,4 @@ -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports interface SemanticOrSyntacticError extends ts.Diagnostic { message: string; diff --git a/packages/typescript-estree/src/ts-estree/index.ts b/packages/typescript-estree/src/ts-estree/index.ts index 4a6b74aef1f..5bed681f209 100644 --- a/packages/typescript-estree/src/ts-estree/index.ts +++ b/packages/typescript-estree/src/ts-estree/index.ts @@ -1,5 +1,5 @@ import * as TSESTree from './ts-estree'; -export * from './ast-node-types'; -export * from '../ts-nodes'; export { TSESTree }; +export * from './ast-node-types'; +export * from './ts-nodes'; diff --git a/packages/typescript-estree/src/ts-estree/ts-estree.ts b/packages/typescript-estree/src/ts-estree/ts-estree.ts index 7043cafa046..ec7640b56b2 100644 --- a/packages/typescript-estree/src/ts-estree/ts-estree.ts +++ b/packages/typescript-estree/src/ts-estree/ts-estree.ts @@ -70,7 +70,7 @@ export type OptionalRangeAndLoc = Pick< T, Exclude > & { - range?: [number, number]; + range?: Range; loc?: SourceLocation; }; diff --git a/packages/typescript-estree/src/ts-nodes.ts b/packages/typescript-estree/src/ts-estree/ts-nodes.ts similarity index 97% rename from packages/typescript-estree/src/ts-nodes.ts rename to packages/typescript-estree/src/ts-estree/ts-nodes.ts index b917584cf38..b4298fa1530 100644 --- a/packages/typescript-estree/src/ts-nodes.ts +++ b/packages/typescript-estree/src/ts-estree/ts-nodes.ts @@ -1,4 +1,4 @@ -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports export type TSNode = ts.Node & ( diff --git a/packages/typescript-estree/src/tsconfig-parser.ts b/packages/typescript-estree/src/tsconfig-parser.ts index 0f4a9b7c35e..44e1f13b28b 100644 --- a/packages/typescript-estree/src/tsconfig-parser.ts +++ b/packages/typescript-estree/src/tsconfig-parser.ts @@ -1,5 +1,5 @@ import path from 'path'; -import ts from 'typescript'; +import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import { Extra } from './parser-options'; //------------------------------------------------------------------------------ diff --git a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts index f30b35c3283..4b8e05d166b 100644 --- a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts +++ b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts @@ -1,5 +1,5 @@ -import glob from 'glob'; import fs from 'fs'; +import glob from 'glob'; import path from 'path'; import jsxKnownIssues from '../../../shared-fixtures/jsx-known-issues'; diff --git a/packages/typescript-estree/tests/ast-alignment/parse.ts b/packages/typescript-estree/tests/ast-alignment/parse.ts index 6113f4ab5b8..84fb70f5b81 100644 --- a/packages/typescript-estree/tests/ast-alignment/parse.ts +++ b/packages/typescript-estree/tests/ast-alignment/parse.ts @@ -1,7 +1,7 @@ +import { ParserPlugin } from '@babel/parser'; import codeFrame from 'babel-code-frame'; import * as parser from '../../src/parser'; import * as parseUtils from './utils'; -import { ParserPlugin } from '@babel/parser'; function createError(message: string, line: number, column: number) { // Construct an error similar to the ones thrown by Babylon. diff --git a/packages/typescript-estree/tests/ast-alignment/utils.ts b/packages/typescript-estree/tests/ast-alignment/utils.ts index f661245be7f..58a7926ca9a 100644 --- a/packages/typescript-estree/tests/ast-alignment/utils.ts +++ b/packages/typescript-estree/tests/ast-alignment/utils.ts @@ -1,5 +1,5 @@ -import isPlainObject from 'lodash.isplainobject'; import { AST_NODE_TYPES } from '../../src/ts-estree'; +import isPlainObject from 'lodash.isplainobject'; /** * By default, pretty-format (within Jest matchers) retains the names/types of nodes from the babylon AST, diff --git a/packages/typescript-estree/tests/lib/comments.ts b/packages/typescript-estree/tests/lib/comments.ts index 7371388acdc..68f9cd800d3 100644 --- a/packages/typescript-estree/tests/lib/comments.ts +++ b/packages/typescript-estree/tests/lib/comments.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { extname } from 'path'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, @@ -16,7 +16,7 @@ describe('Comments', () => { testFiles.forEach(filename => { const code = readFileSync(filename, 'utf8'); const fileExtension = extname(filename); - const config: ParserOptions = { + const config: TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tests/lib/javascript.ts b/packages/typescript-estree/tests/lib/javascript.ts index 0d12ac4cc13..1cce991c0f4 100644 --- a/packages/typescript-estree/tests/lib/javascript.ts +++ b/packages/typescript-estree/tests/lib/javascript.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'fs'; import glob from 'glob'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, @@ -13,7 +13,7 @@ const testFiles = glob.sync(`${FIXTURES_DIR}/**/*.src.js`); describe('javascript', () => { testFiles.forEach(filename => { const code = readFileSync(filename, 'utf8'); - const config: ParserOptions = { + const config: TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tests/lib/jsx.ts b/packages/typescript-estree/tests/lib/jsx.ts index 39da5735a8a..52b6debdf6b 100644 --- a/packages/typescript-estree/tests/lib/jsx.ts +++ b/packages/typescript-estree/tests/lib/jsx.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'fs'; import glob from 'glob'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, @@ -29,7 +29,7 @@ describe('JSX', () => { ): (filename: string) => void { return filename => { const code = readFileSync(filename, 'utf8'); - const config: ParserOptions = { + const config: TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tests/lib/parse.ts b/packages/typescript-estree/tests/lib/parse.ts index c757bad7cde..3c34f705556 100644 --- a/packages/typescript-estree/tests/lib/parse.ts +++ b/packages/typescript-estree/tests/lib/parse.ts @@ -1,6 +1,6 @@ import * as parser from '../../src/parser'; import * as astConverter from '../../src/ast-converter'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock } from '../../tools/test-utils'; describe('parse()', () => { @@ -23,7 +23,7 @@ describe('parse()', () => { describe('general', () => { const code = 'let foo = bar;'; - const config: ParserOptions = { + const config: TSESTreeOptions = { comment: true, tokens: true, range: true, @@ -38,7 +38,7 @@ describe('parse()', () => { describe('non string code', () => { const code = (12345 as any) as string; - const config: ParserOptions = { + const config: TSESTreeOptions = { comment: true, tokens: true, range: true, @@ -97,7 +97,7 @@ describe('parse()', () => { describe('errorOnTypeScriptSyntacticAndSemanticIssues', () => { const code = '@test const foo = 2'; - const options: ParserOptions = { + const options: TSESTreeOptions = { comment: true, tokens: true, range: true, @@ -130,7 +130,7 @@ describe('parse()', () => { describe('preserveNodeMaps', () => { const code = 'var a = true'; - const baseConfig: ParserOptions = { + const baseConfig: TSESTreeOptions = { comment: true, tokens: true, range: true, diff --git a/packages/typescript-estree/tests/lib/semantic-diagnostics-enabled.ts b/packages/typescript-estree/tests/lib/semantic-diagnostics-enabled.ts index bfae9601a14..fc05b04ec58 100644 --- a/packages/typescript-estree/tests/lib/semantic-diagnostics-enabled.ts +++ b/packages/typescript-estree/tests/lib/semantic-diagnostics-enabled.ts @@ -16,7 +16,7 @@ describe('Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" testFiles.forEach(filename => { const code = readFileSync(filename, 'utf8'); const fileExtension = extname(filename); - const config: parser.ParserOptions = { + const config: parser.TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tests/lib/semanticInfo.ts b/packages/typescript-estree/tests/lib/semanticInfo.ts index df3fed691a4..189816f08c6 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.ts @@ -2,23 +2,19 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { extname, join, resolve } from 'path'; import ts from 'typescript'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, parseCodeAndGenerateServices, } from '../../tools/test-utils'; import { parseAndGenerateServices } from '../../src/parser'; -import { - VariableDeclaration, - ClassDeclaration, - ClassProperty, -} from '../../src/ts-estree/ts-estree'; +import { TSESTree } from '../../src/ts-estree'; const FIXTURES_DIR = './tests/fixtures/semanticInfo'; const testFiles = glob.sync(`${FIXTURES_DIR}/**/*.src.ts`); -function createOptions(fileName: string): ParserOptions & { cwd?: string } { +function createOptions(fileName: string): TSESTreeOptions & { cwd?: string } { return { loc: true, range: true, @@ -144,15 +140,16 @@ describe('semanticInfo', () => { ); expect(parseResult).toHaveProperty('services.esTreeNodeToTSNodeMap'); - const binaryExpression = (parseResult.ast.body[0] as VariableDeclaration) - .declarations[0].init!; + const binaryExpression = (parseResult.ast + .body[0] as TSESTree.VariableDeclaration).declarations[0].init!; const tsBinaryExpression = parseResult.services.esTreeNodeToTSNodeMap!.get( binaryExpression, ); expect(tsBinaryExpression.kind).toEqual(ts.SyntaxKind.BinaryExpression); const computedPropertyString = ((parseResult.ast - .body[1] as ClassDeclaration).body.body[0] as ClassProperty).key; + .body[1] as TSESTree.ClassDeclaration).body + .body[0] as TSESTree.ClassProperty).key; const tsComputedPropertyString = parseResult.services.esTreeNodeToTSNodeMap!.get( computedPropertyString, ); diff --git a/packages/typescript-estree/tests/lib/tsx.ts b/packages/typescript-estree/tests/lib/tsx.ts index e9fbdad600d..84160d2b4b8 100644 --- a/packages/typescript-estree/tests/lib/tsx.ts +++ b/packages/typescript-estree/tests/lib/tsx.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { extname } from 'path'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, @@ -16,7 +16,7 @@ describe('TSX', () => { testFiles.forEach(filename => { const code = readFileSync(filename, 'utf8'); const fileExtension = extname(filename); - const config: ParserOptions = { + const config: TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tests/lib/typescript.ts b/packages/typescript-estree/tests/lib/typescript.ts index d11136dfdae..2e5e70b04cf 100644 --- a/packages/typescript-estree/tests/lib/typescript.ts +++ b/packages/typescript-estree/tests/lib/typescript.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { extname } from 'path'; -import { ParserOptions } from '../../src/parser-options'; +import { TSESTreeOptions } from '../../src/parser-options'; import { createSnapshotTestBlock, formatSnapshotName, @@ -16,7 +16,7 @@ describe('typescript', () => { testFiles.forEach(filename => { const code = readFileSync(filename, 'utf8'); const fileExtension = extname(filename); - const config: ParserOptions = { + const config: TSESTreeOptions = { loc: true, range: true, tokens: true, diff --git a/packages/typescript-estree/tools/test-utils.ts b/packages/typescript-estree/tools/test-utils.ts index 4fd54335ebc..f1c587df237 100644 --- a/packages/typescript-estree/tools/test-utils.ts +++ b/packages/typescript-estree/tools/test-utils.ts @@ -1,5 +1,5 @@ import * as parser from '../src/parser'; -import { ParserOptions } from '../src/parser-options'; +import { TSESTreeOptions } from '../src/parser-options'; /** * Returns a raw copy of the given AST @@ -19,7 +19,7 @@ export function getRaw(ast: any) { export function parseCodeAndGenerateServices( code: string, - config: ParserOptions, + config: TSESTreeOptions, ) { return parser.parseAndGenerateServices(code, config); } @@ -28,13 +28,13 @@ export function parseCodeAndGenerateServices( * Returns a function which can be used as the callback of a Jest test() block, * and which performs an assertion on the snapshot for the given code and config. * @param {string} code The source code to parse - * @param {ParserOptions} config the parser configuration + * @param {TSESTreeOptions} config the parser configuration * @param {boolean} generateServices Flag determining whether to generate ast maps and program or not * @returns {jest.ProvidesCallback} callback for Jest it() block */ export function createSnapshotTestBlock( code: string, - config: ParserOptions, + config: TSESTreeOptions, generateServices?: true, ) { /** diff --git a/packages/typescript-estree/tsconfig.build.json b/packages/typescript-estree/tsconfig.build.json index b0fced27d72..792172fb82f 100644 --- a/packages/typescript-estree/tsconfig.build.json +++ b/packages/typescript-estree/tsconfig.build.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "outDir": "./dist" + "outDir": "./dist", + "rootDir": "./src" }, "include": ["src"] } diff --git a/packages/typescript-estree/tsconfig.json b/packages/typescript-estree/tsconfig.json index 1fdde9ad21c..e389d7edef3 100644 --- a/packages/typescript-estree/tsconfig.json +++ b/packages/typescript-estree/tsconfig.json @@ -1,4 +1,7 @@ { - "extends": "./tsconfig.build.json", + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist" + }, "include": ["src", "tests", "tools"] } diff --git a/yarn.lock b/yarn.lock index ddecb6a80ef..b296e145ad2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1187,7 +1187,7 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== -"@types/eslint@^4.16.3", "@types/eslint@^4.16.5": +"@types/eslint@^4.16.3": version "4.16.6" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.6.tgz#96d4ecddbea618ab0b55eaf0dffedf387129b06c" integrity sha512-GL7tGJig55FeclpOytU7nCCqtR143jBoC7AUdH0DO9xBSIFiNNUFCY/S3KNWsHeQJuU3hjw/OC1+kRTFNXqUZQ==