diff --git a/.eslintignore b/.eslintignore index c1536a77bd33..92693b863825 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 91c11fbba922..00e766eaaef1 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 e85f84892687..ae2f544fa938 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 8e864c9c4a2a..80c8b1315877 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 4aef0268fa11..62ace5d43171 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 3bee5b029f74..f9981920fabb 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 77756ad15a87..25c0a08f3ab1 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 ec7ba9ea4fe2..f3cb5948e5d0 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 2e9a15ffde71..829f29f24b84 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 6228f0143112..914e4172c79a 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 be79d684a690..d760f18ea94b 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 63f9d05e19ec..fd3958874807 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 002fbd3d8ee3..e530efb40991 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 1ab3dd71ebb4..deacc272bb33 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 29aaecdaa6d0..9b7d345fe3d6 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 f9a3ebcfb495..1944fdf2bf54 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 85187a7046ba..6a7a5c31e139 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 bfa2ca944395..326a0d961e52 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 c0252331f792..7c221360c0c8 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 6811cf5a2e42..ffcc6985073a 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 d6c92491be12..5de11364ab81 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 78065969afb6..7dd71ad583b5 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 461b8c6efa80..b0917b5ae72e 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 9ee66b445643..3546cd1112d2 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 049aa2b35b89..49689213992d 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 5730475cd0de..56c5eb5f2964 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 ad6eaf611075..2ab66102dd46 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 d83620133217..d946c8792572 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 0d92c855aa8c..6d1ffa80870f 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 98039a91b7a8..69b4887c925f 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 e98c9c39659e..30201acf6a02 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 890e6b04aa5d..b4a4274c274a 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 d11b25271905..f382e7262e08 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 1e78c75338d7..c98b619eab49 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 ede16241eed0..9fc32f6fc1c5 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 085bb02975dc..c18e8e0cc11a 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 dcac02df8460..e6b48a055ed1 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 67b61d13175a..a8acccd8af95 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 4b542cd91092..8e829b48e9c7 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 e7a95d705e90..95f1a8ee3cab 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 f7b3eb153eef..2db17e11d1dd 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 10308d7e70ec..6efbf62d6a65 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 37eced4e545d..9d60e0eed4fc 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 6b3079cdfdf3..565a4cb83db2 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 75d2ccdacc7e..0eb96e991437 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 8699c0cf0730..a9745be16e02 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 ef73ae7478d6..9a3a42c8f32a 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 89fe6180333f..6e40651dd2e8 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 9deac5cd9774..19ef206119f6 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 6b177f1dccf0..cd273a65456f 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 c1c1ad470dae..d4ea472be5e1 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 ac61c39cb559..5982f04c3d5c 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 a63297708cce..2cc8b4981596 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 d2291cded47a..b1aae71b3571 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 07b6a0b3c3d1..2a9ba2a1c934 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 2703d00b5c28..4db8bf3909c7 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 6baa018ebf67..1a1fb94a462d 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 580f2a57d30b..d0b8afe9b194 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 ea44a4212498..e0515e869c95 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 647cbf753fc9..e992b440c6cc 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 c4bf28c08fb7..091f68740cd1 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 5e920dd088fc..6b8570bb4a45 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 0bee5ac63244..1d2742ed0402 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 ad2395a93d00..44a40942c9fa 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 007fe8042d98..fb2563ed4eeb 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 ea0320ac343e..c1ddce12186f 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 6c2a18dacc89..53a349e552ee 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 e1bca791b33e..7a0324308b2c 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 5743bcc7f4d8..a472d8619fe3 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 c4569c79ba04..83bc750a2353 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 05f75faf4086..6559c9b71408 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 957b50b286e3..59c820d28b9c 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 7ea46da7c0b9..98ee285d1a28 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 d93c90532daa..e7cefb09367f 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 62ef79199a24..000000000000 --- 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 000000000000..7e7370143b26 --- /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 000000000000..45ecc1a64f86 --- /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 000000000000..b64d433b01aa --- /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 000000000000..d1ab0c20078c --- /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 000000000000..b20e70af2135 --- /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 000000000000..0812adade321 --- /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 000000000000..c8069ca6fc29 --- /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 000000000000..8b3a7f039ff3 --- /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 000000000000..1c77caafedf6 --- /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 000000000000..cff921e048cc --- /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 000000000000..d374ac57b912 --- /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 000000000000..48162df0867f --- /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 000000000000..fe9b4b803968 --- /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 000000000000..e6922d9df190 --- /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 000000000000..abf3c3e6e8f5 --- /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 000000000000..05a5b0b54ada --- /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 000000000000..3ff4a843ec2e --- /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 000000000000..27e55c996a92 --- /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 000000000000..0ce1565b0d05 --- /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 000000000000..f469d044ef4b --- /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 5beae5aa5271..a982469625f0 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 92390dbf0d34..b131104ce87b 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 fa5aa39dfdc4..71478ee2ad62 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 fcdb88175cce..7b7e53c9e84c 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 f5c27a69f798..9dff225a7213 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 47d816fe0489..c3c205509dd9 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 62172fd30b70..ec876c63716a 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 72ff381f87ee..25d291dee4c2 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 5474a71d66db..026500da7d35 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 1c70dbf86429..e0e535c774aa 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 80793df4e2dc..d682bb091b4e 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 5d1821bd50c5..585effea268e 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 2f4003c8e3d6..1a963859d969 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 14568aba123c..f31eb6340682 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 4a6b74aef1fc..5bed681f209b 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 7043cafa046d..ec7640b56b2d 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 b917584cf380..b4298fa1530a 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 0f4a9b7c35e2..44e1f13b28bd 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 f30b35c32838..4b8e05d166b3 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 6113f4ab5b80..84fb70f5b815 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 f661245be7f9..58a7926ca9ad 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 7371388acdc2..68f9cd800d3b 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 0d12ac4cc13a..1cce991c0f43 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 39da5735a8a1..52b6debdf6b4 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 c757bad7cde6..3c34f7055565 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 bfae9601a14e..fc05b04ec58b 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 df3fed691a40..189816f08c64 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 e9fbdad600d9..84160d2b4b85 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 d11136dfdaef..2e5e70b04cf6 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 4fd54335ebc9..f1c587df237b 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 b0fced27d72d..792172fb82f6 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 1fdde9ad21c5..e389d7edef33 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 ddecb6a80ef2..b296e145ad2c 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==