diff --git a/packages/eslint-plugin/tsconfig.json b/packages/eslint-plugin/tsconfig.json index fc93e91c26d3..fb7e21da237d 100644 --- a/packages/eslint-plugin/tsconfig.json +++ b/packages/eslint-plugin/tsconfig.json @@ -1,11 +1,4 @@ { "extends": "./tsconfig.build.json", - "include": [ - "src", - "typings", - // include the parser's ambient typings because the parser exports them in its type defs - "../parser/typings", - "tests", - "tools" - ] + "include": ["src", "typings", "tests", "tools"] } diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 8d7cb94092fd..9d51a32c4fd1 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -28,10 +28,12 @@ "prebuild": "npm run clean", "build": "tsc -p tsconfig.build.json", "clean": "rimraf dist/", + "format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore", "typecheck": "tsc --noEmit" }, "dependencies": { - "@typescript-eslint/typescript-estree": "1.9.0" + "@typescript-eslint/typescript-estree": "1.9.0", + "eslint-scope": "^4.0.0" }, "peerDependencies": { "eslint": "*", diff --git a/packages/experimental-utils/src/index.ts b/packages/experimental-utils/src/index.ts index 8b3a7f039ff3..93b3831817c7 100644 --- a/packages/experimental-utils/src/index.ts +++ b/packages/experimental-utils/src/index.ts @@ -1,7 +1,8 @@ import * as ESLintUtils from './eslint-utils'; import * as TSESLint from './ts-eslint'; +import * as TSESLintScope from './ts-eslint-scope'; -export { ESLintUtils, TSESLint }; +export { ESLintUtils, TSESLint, TSESLintScope }; // for convenience's sake - export the types directly from here so consumers // don't need to reference/install both packages in their code diff --git a/packages/experimental-utils/src/ts-eslint-scope/Definition.ts b/packages/experimental-utils/src/ts-eslint-scope/Definition.ts new file mode 100644 index 000000000000..b2f4b91383e5 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Definition.ts @@ -0,0 +1,39 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { + Definition as ESLintDefinition, + ParameterDefinition as ESLintParameterDefinition, +} from 'eslint-scope/lib/definition'; + +interface Definition { + type: string; + name: TSESTree.BindingName; + node: TSESTree.Node; + parent?: TSESTree.Node | null; + index?: number | null; + kind?: string | null; + rest?: boolean; +} +interface DefinitionConstructor { + new ( + type: string, + name: TSESTree.BindingName | TSESTree.PropertyName, + node: TSESTree.Node, + parent?: TSESTree.Node | null, + index?: number | null, + kind?: string | null, + ): Definition; +} +const Definition = ESLintDefinition as DefinitionConstructor; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface ParameterDefinition extends Definition {} +const ParameterDefinition = ESLintParameterDefinition as DefinitionConstructor & { + new ( + name: TSESTree.Node, + node: TSESTree.Node, + index?: number | null, + rest?: boolean, + ): ParameterDefinition; +}; + +export { Definition, ParameterDefinition }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Options.ts b/packages/experimental-utils/src/ts-eslint-scope/Options.ts new file mode 100644 index 000000000000..f06fe4e42e8d --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Options.ts @@ -0,0 +1,21 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; + +type PatternVisitorCallback = ( + pattern: TSESTree.Identifier, + info: { + rest: boolean; + topLevel: boolean; + assignments: TSESTree.AssignmentPattern[]; + }, +) => void; + +interface PatternVisitorOptions { + processRightHandNodes?: boolean; +} + +interface Visitor { + visitChildren(node?: T): void; + visit(node?: T): void; +} + +export { PatternVisitorCallback, PatternVisitorOptions, Visitor }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/PatternVisitor.ts b/packages/experimental-utils/src/ts-eslint-scope/PatternVisitor.ts new file mode 100644 index 000000000000..a31645b12285 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/PatternVisitor.ts @@ -0,0 +1,38 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import ESLintPatternVisitor from 'eslint-scope/lib/pattern-visitor'; +import { ScopeManager } from './ScopeManager'; +import { + PatternVisitorCallback, + PatternVisitorOptions, + Visitor, +} from './Options'; + +interface PatternVisitor extends Visitor { + options: any; + scopeManager: ScopeManager; + parent?: TSESTree.Node; + rightHandNodes: TSESTree.Node[]; + + Identifier(pattern: TSESTree.Node): void; + Property(property: TSESTree.Node): void; + ArrayPattern(pattern: TSESTree.Node): void; + AssignmentPattern(pattern: TSESTree.Node): void; + RestElement(pattern: TSESTree.Node): void; + MemberExpression(node: TSESTree.Node): void; + SpreadElement(node: TSESTree.Node): void; + ArrayExpression(node: TSESTree.Node): void; + AssignmentExpression(node: TSESTree.Node): void; + CallExpression(node: TSESTree.Node): void; +} +const PatternVisitor = ESLintPatternVisitor as { + new ( + options: PatternVisitorOptions, + rootPattern: any, + callback: PatternVisitorCallback, + ): PatternVisitor; + + // static methods + isPattern(node: TSESTree.Node): boolean; +}; + +export { PatternVisitor }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Reference.ts b/packages/experimental-utils/src/ts-eslint-scope/Reference.ts new file mode 100644 index 000000000000..15afc7dcdc14 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Reference.ts @@ -0,0 +1,27 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import ESLintReference from 'eslint-scope/lib/reference'; +import { Scope } from './Scope'; +import { Variable } from './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; +} +const Reference = ESLintReference as { + new (): Reference; + + READ: 0x1; + WRITE: 0x2; + RW: 0x3; +}; + +export { Reference }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Referencer.ts b/packages/experimental-utils/src/ts-eslint-scope/Referencer.ts new file mode 100644 index 000000000000..b430047c01ec --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Referencer.ts @@ -0,0 +1,80 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import ESLintReferencer from 'eslint-scope/lib/referencer'; +import { + PatternVisitorCallback, + PatternVisitorOptions, + Visitor, +} from './Options'; +import { Scope } from './Scope'; +import { ScopeManager } from './ScopeManager'; + +interface Referencer extends Visitor { + isInnerMethodDefinition: boolean; + options: any; + scopeManager: SM; + parent?: TSESTree.Node; + + currentScope(): Scope; + close(node: TSESTree.Node): void; + pushInnerMethodDefinition(isInnerMethodDefinition: boolean): boolean; + popInnerMethodDefinition(isInnerMethodDefinition: boolean): void; + + referencingDefaultValue( + pattern: any, + assignments: any, + maybeImplicitGlobal: any, + init: boolean, + ): void; + visitPattern( + node: TSESTree.Node, + options: PatternVisitorOptions, + callback: PatternVisitorCallback, + ): void; + visitFunction(node: TSESTree.Node): void; + visitClass(node: TSESTree.Node): void; + visitProperty(node: TSESTree.Node): void; + visitForIn(node: TSESTree.Node): void; + visitVariableDeclaration( + variableTargetScope: any, + type: any, + node: TSESTree.Node, + index: any, + ): void; + + AssignmentExpression(node: TSESTree.Node): void; + CatchClause(node: TSESTree.Node): void; + Program(node: TSESTree.Node): void; + Identifier(node: TSESTree.Node): void; + UpdateExpression(node: TSESTree.Node): void; + MemberExpression(node: TSESTree.Node): void; + Property(node: TSESTree.Node): void; + MethodDefinition(node: TSESTree.Node): void; + BreakStatement(): void; + ContinueStatement(): void; + LabeledStatement(node: TSESTree.Node): void; + ForStatement(node: TSESTree.Node): void; + ClassExpression(node: TSESTree.Node): void; + ClassDeclaration(node: TSESTree.Node): void; + CallExpression(node: TSESTree.Node): void; + BlockStatement(node: TSESTree.Node): void; + ThisExpression(): void; + WithStatement(node: TSESTree.Node): void; + VariableDeclaration(node: TSESTree.Node): void; + SwitchStatement(node: TSESTree.Node): void; + FunctionDeclaration(node: TSESTree.Node): void; + FunctionExpression(node: TSESTree.Node): void; + ForOfStatement(node: TSESTree.Node): void; + ForInStatement(node: TSESTree.Node): void; + ArrowFunctionExpression(node: TSESTree.Node): void; + ImportDeclaration(node: TSESTree.Node): void; + visitExportDeclaration(node: TSESTree.Node): void; + ExportDeclaration(node: TSESTree.Node): void; + ExportNamedDeclaration(node: TSESTree.Node): void; + ExportSpecifier(node: TSESTree.Node): void; + MetaProperty(): void; +} +const Referencer = ESLintReferencer as { + new (options: any, scopeManager: SM): Referencer; +}; + +export { Referencer }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Scope.ts b/packages/experimental-utils/src/ts-eslint-scope/Scope.ts new file mode 100644 index 000000000000..71b8dbf42a4c --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Scope.ts @@ -0,0 +1,193 @@ +/* eslint-disable @typescript-eslint/no-empty-interface */ + +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { + Scope as ESLintScope, + GlobalScope as ESLintGlobalScope, + ModuleScope as ESLintModuleScope, + FunctionExpressionNameScope as ESLintFunctionExpressionNameScope, + CatchScope as ESLintCatchScope, + WithScope as ESLintWithScope, + BlockScope as ESLintBlockScope, + SwitchScope as ESLintSwitchScope, + FunctionScope as ESLintFunctionScope, + ForScope as ESLintForScope, + ClassScope as ESLintClassScope, +} from 'eslint-scope/lib/scope'; +import { Definition } from './Definition'; +import { Reference } from './Reference'; +import { ScopeManager } from './ScopeManager'; +import { Variable } from './Variable'; + +type ScopeType = + | 'block' + | 'catch' + | 'class' + | 'for' + | 'function' + | 'function-expression-name' + | 'global' + | 'module' + | 'switch' + | 'with' + | 'TDZ' + | 'enum' + | 'empty-function'; + +interface Scope { + type: ScopeType; + isStrict: boolean; + upper: Scope | null; + childScopes: Scope[]; + variableScope: Scope; + block: TSESTree.Node; + variables: Variable[]; + set: Map; + references: Reference[]; + through: Reference[]; + thisFound?: boolean; + functionExpressionScope: boolean; + + __shouldStaticallyClose(scopeManager: ScopeManager): boolean; + __shouldStaticallyCloseForGlobal(ref: any): boolean; + __staticCloseRef(ref: any): void; + __dynamicCloseRef(ref: any): void; + __globalCloseRef(ref: any): void; + __close(scopeManager: ScopeManager): Scope; + __isValidResolution(ref: any, variable: any): boolean; + __resolve(ref: any): boolean; + __delegateToUpperScope(ref: any): void; + __addDeclaredVariablesOfNode(variable: any, node: TSESTree.Node): void; + __defineGeneric( + name: any, + set: any, + variables: any, + node: any, + def: Definition, + ): void; + + __define(node: TSESTree.Node, def: Definition): void; + + __referencing( + node: TSESTree.Node, + assign: number, + writeExpr: TSESTree.Node, + maybeImplicitGlobal: any, + partial: any, + init: any, + ): void; + + __detectEval(): void; + __detectThis(): void; + __isClosed(): boolean; + /** + * returns resolved {Reference} + * @method Scope#resolve + * @param {Espree.Identifier} ident - identifier to be resolved. + * @returns {Reference} reference + */ + resolve(ident: TSESTree.Node): Reference; + + /** + * returns this scope is static + * @method Scope#isStatic + * @returns {boolean} static + */ + isStatic(): boolean; + + /** + * returns this scope has materialized arguments + * @method Scope#isArgumentsMaterialized + * @returns {boolean} arguemnts materialized + */ + isArgumentsMaterialized(): boolean; + + /** + * returns this scope has materialized `this` reference + * @method Scope#isThisMaterialized + * @returns {boolean} this materialized + */ + isThisMaterialized(): boolean; + + isUsedName(name: any): boolean; +} +interface ScopeConstructor { + new ( + scopeManager: ScopeManager, + type: ScopeType, + upperScope: Scope | null, + block: TSESTree.Node | null, + isMethodDefinition: boolean, + ): Scope; +} +const Scope = ESLintScope as ScopeConstructor; + +interface ScopeChildConstructorWithUpperScope { + new ( + scopeManager: ScopeManager, + upperScope: Scope, + block: TSESTree.Node | null, + ): T; +} + +interface GlobalScope extends Scope {} +const GlobalScope = ESLintGlobalScope as ScopeConstructor & { + new (scopeManager: ScopeManager, block: TSESTree.Node | null): GlobalScope; +}; + +interface ModuleScope extends Scope {} +const ModuleScope = ESLintModuleScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface FunctionExpressionNameScope extends Scope {} +const FunctionExpressionNameScope = ESLintFunctionExpressionNameScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface CatchScope extends Scope {} +const CatchScope = ESLintCatchScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface WithScope extends Scope {} +const WithScope = ESLintWithScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface BlockScope extends Scope {} +const BlockScope = ESLintBlockScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface SwitchScope extends Scope {} +const SwitchScope = ESLintSwitchScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface FunctionScope extends Scope {} +const FunctionScope = ESLintFunctionScope as ScopeConstructor & { + new ( + scopeManager: ScopeManager, + upperScope: Scope, + block: TSESTree.Node | null, + isMethodDefinition: boolean, + ): FunctionScope; +}; + +interface ForScope extends Scope {} +const ForScope = ESLintForScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +interface ClassScope extends Scope {} +const ClassScope = ESLintClassScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; + +export { + ScopeType, + Scope, + GlobalScope, + ModuleScope, + FunctionExpressionNameScope, + CatchScope, + WithScope, + BlockScope, + SwitchScope, + FunctionScope, + ForScope, + ClassScope, +}; diff --git a/packages/experimental-utils/src/ts-eslint-scope/ScopeManager.ts b/packages/experimental-utils/src/ts-eslint-scope/ScopeManager.ts new file mode 100644 index 000000000000..e90c3cf4b11f --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/ScopeManager.ts @@ -0,0 +1,57 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import ESLintScopeManager from 'eslint-scope/lib/scope-manager'; +import { Scope } from './Scope'; +import { Variable } from './Variable'; + +interface ScopeManagerOptions { + directive?: boolean; + optimistic?: boolean; + ignoreEval?: boolean; + nodejsScope?: boolean; + sourceType?: 'module' | 'script'; + impliedStrict?: boolean; + ecmaVersion?: number; +} + +interface ScopeManager { + __options: ScopeManagerOptions; + __currentScope: Scope; + scopes: Scope[]; + globalScope: Scope; + + __useDirective(): boolean; + __isOptimistic(): boolean; + __ignoreEval(): boolean; + __isNodejsScope(): boolean; + isModule(): boolean; + isImpliedStrict(): boolean; + isStrictModeSupported(): boolean; + + // Returns appropriate scope for this node. + __get(node: TSESTree.Node): Scope; + getDeclaredVariables(node: TSESTree.Node): Variable[]; + acquire(node: TSESTree.Node, inner?: boolean): Scope | null; + acquireAll(node: TSESTree.Node): Scope | null; + release(node: TSESTree.Node, inner?: boolean): Scope | null; + attach(): void; + detach(): void; + + __nestScope(scope: Scope): Scope; + __nestGlobalScope(node: TSESTree.Node): Scope; + __nestBlockScope(node: TSESTree.Node): Scope; + __nestFunctionScope(node: TSESTree.Node, isMethodDefinition: boolean): Scope; + __nestForScope(node: TSESTree.Node): Scope; + __nestCatchScope(node: TSESTree.Node): Scope; + __nestWithScope(node: TSESTree.Node): Scope; + __nestClassScope(node: TSESTree.Node): Scope; + __nestSwitchScope(node: TSESTree.Node): Scope; + __nestModuleScope(node: TSESTree.Node): Scope; + __nestFunctionExpressionNameScope(node: TSESTree.Node): Scope; + + __isES6(): boolean; +} +const ScopeManager = ESLintScopeManager as { + new (options: ScopeManagerOptions): ScopeManager; +}; + +export { ScopeManager, ScopeManagerOptions }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Variable.ts b/packages/experimental-utils/src/ts-eslint-scope/Variable.ts new file mode 100644 index 000000000000..306d5bfca498 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/Variable.ts @@ -0,0 +1,18 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import ESLintVariable from 'eslint-scope/lib/variable'; +import { Reference } from './Reference'; +import { Definition } from './Definition'; + +interface Variable { + name: string; + identifiers: TSESTree.Identifier[]; + references: Reference[]; + defs: Definition[]; + eslintUsed?: boolean; +} + +const Variable = ESLintVariable as { + new (): Variable; +}; + +export { Variable }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/analyze.ts b/packages/experimental-utils/src/ts-eslint-scope/analyze.ts new file mode 100644 index 000000000000..c4ab4514c8cd --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/analyze.ts @@ -0,0 +1,19 @@ +import { analyze as ESLintAnalyze } from 'eslint-scope'; +import { ScopeManager } from './ScopeManager'; + +interface AnalysisOptions { + optimistic?: boolean; + directive?: boolean; + ignoreEval?: boolean; + nodejsScope?: boolean; + impliedStrict?: boolean; + fallback?: string | ((node: {}) => string[]); + sourceType?: 'script' | 'module'; + ecmaVersion?: number; +} +const analyze = ESLintAnalyze as ( + ast: {}, + options?: AnalysisOptions, +) => ScopeManager; + +export { analyze, AnalysisOptions }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/index.ts b/packages/experimental-utils/src/ts-eslint-scope/index.ts new file mode 100644 index 000000000000..d713845f9f46 --- /dev/null +++ b/packages/experimental-utils/src/ts-eslint-scope/index.ts @@ -0,0 +1,12 @@ +import { version as ESLintVersion } from 'eslint-scope'; + +export * from './analyze'; +export * from './Definition'; +export * from './Options'; +export * from './PatternVisitor'; +export * from './Reference'; +export * from './Referencer'; +export * from './Scope'; +export * from './ScopeManager'; +export * from './Variable'; +export const version: string = ESLintVersion; diff --git a/packages/experimental-utils/typings/eslint-scope.d.ts b/packages/experimental-utils/typings/eslint-scope.d.ts new file mode 100644 index 000000000000..7b4d0bc1b2e9 --- /dev/null +++ b/packages/experimental-utils/typings/eslint-scope.d.ts @@ -0,0 +1,63 @@ +/* +We intentionally do not include @types/eslint-scope. + +This is to ensure that nobody accidentally uses those incorrect types +instead of the ones declared within this package +*/ + +declare module 'eslint-scope/lib/variable' { + const Variable: unknown; + export = Variable; +} +declare module 'eslint-scope/lib/definition' { + const Definition: unknown; + const ParameterDefinition: unknown; + export { Definition, ParameterDefinition }; +} +declare module 'eslint-scope/lib/pattern-visitor' { + const PatternVisitor: unknown; + export = PatternVisitor; +} +declare module 'eslint-scope/lib/referencer' { + const Referencer: unknown; + export = Referencer; +} +declare module 'eslint-scope/lib/scope' { + const Scope: unknown; + const GlobalScope: unknown; + const ModuleScope: unknown; + const FunctionExpressionNameScope: unknown; + const CatchScope: unknown; + const WithScope: unknown; + const BlockScope: unknown; + const SwitchScope: unknown; + const FunctionScope: unknown; + const ForScope: unknown; + const ClassScope: unknown; + export { + Scope, + GlobalScope, + ModuleScope, + FunctionExpressionNameScope, + CatchScope, + WithScope, + BlockScope, + SwitchScope, + FunctionScope, + ForScope, + ClassScope, + }; +} +declare module 'eslint-scope/lib/reference' { + const Reference: unknown; + export = Reference; +} +declare module 'eslint-scope/lib/scope-manager' { + const ScopeManager: unknown; + export = ScopeManager; +} +declare module 'eslint-scope' { + const version: string; + const analyze: unknown; + export { analyze, version }; +} diff --git a/packages/parser/package.json b/packages/parser/package.json index 0389785b401f..d33fa890f503 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -37,13 +37,12 @@ "eslint": "^5.0.0" }, "dependencies": { + "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/experimental-utils": "1.9.0", "@typescript-eslint/typescript-estree": "1.9.0", - "eslint-scope": "^4.0.0", "eslint-visitor-keys": "^1.0.0" }, "devDependencies": { - "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/shared-fixtures": "1.9.0" } } diff --git a/packages/parser/src/analyze-scope.ts b/packages/parser/src/analyze-scope.ts index b131104ce87b..165d560583f2 100644 --- a/packages/parser/src/analyze-scope.ts +++ b/packages/parser/src/analyze-scope.ts @@ -1,12 +1,8 @@ -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'; + TSESTree, + TSESLintScope, + AST_NODE_TYPES, +} from '@typescript-eslint/experimental-utils'; import { getKeys as fallback } from 'eslint-visitor-keys'; import { ParserOptions } from './parser-options'; @@ -30,11 +26,11 @@ function overrideDefine(define: any) { }; } -class PatternVisitor extends OriginalPatternVisitor { +class PatternVisitor extends TSESLintScope.PatternVisitor { constructor( - options: PatternVisitorOptions, + options: TSESLintScope.PatternVisitorOptions, rootPattern: any, - callback: PatternVisitorCallback, + callback: TSESLintScope.PatternVisitorCallback, ) { super(options, rootPattern, callback); } @@ -87,7 +83,7 @@ class PatternVisitor extends OriginalPatternVisitor { } } -class Referencer extends OriginalReferencer { +class Referencer extends TSESLintScope.Referencer { protected typeMode: boolean; constructor(options: any, scopeManager: ScopeManager) { @@ -103,8 +99,8 @@ class Referencer extends OriginalReferencer { */ visitPattern( node: T, - options: PatternVisitorOptions, - callback: PatternVisitorCallback, + options: TSESLintScope.PatternVisitorOptions, + callback: TSESLintScope.PatternVisitorCallback, ): void { if (!node) { return; @@ -143,7 +139,14 @@ class Referencer extends OriginalReferencer { if (type === 'FunctionDeclaration' && id) { upperScope.__define( id, - new Definition('FunctionName', id, node, null, null, null), + new TSESLintScope.Definition( + 'FunctionName', + id, + node, + null, + null, + null, + ), ); // Remove overload definition to avoid confusion of no-redeclare rule. @@ -183,7 +186,12 @@ class Referencer extends OriginalReferencer { ) { innerScope.__define( pattern, - new ParameterDefinition(pattern, node, i, info.rest), + new TSESLintScope.ParameterDefinition( + pattern, + node, + i, + info.rest, + ), ); this.referencingDefaultValue(pattern, info.assignments, null, true); } @@ -344,7 +352,14 @@ class Referencer extends OriginalReferencer { if (!existed) { upperScope.__define( id, - new Definition('FunctionName', id, node, null, null, null), + new TSESLintScope.Definition( + 'FunctionName', + id, + node, + null, + null, + null, + ), ); } } @@ -364,7 +379,7 @@ class Referencer extends OriginalReferencer { (pattern, info) => { innerScope.__define( pattern, - new ParameterDefinition(pattern, node, i, info.rest), + new TSESLintScope.ParameterDefinition(pattern, node, i, info.rest), ); // Set `variable.eslintUsed` to tell ESLint that the variable is used. @@ -657,7 +672,7 @@ class Referencer extends OriginalReferencer { const scope = this.currentScope(); if (id) { - scope.__define(id, new Definition('EnumName', id, node)); + scope.__define(id, new TSESLintScope.Definition('EnumName', id, node)); } scopeManager.__nestEnumScope(node); @@ -677,9 +692,19 @@ class Referencer extends OriginalReferencer { const { id, initializer } = node; const scope = this.currentScope(); - scope.__define(id, new Definition('EnumMemberName', id, node)); + scope.__define( + id, + new TSESLintScope.Definition('EnumMemberName', id, node), + ); if (initializer) { - scope.__referencing(id, Reference.WRITE, initializer, null, false, true); + scope.__referencing( + id, + TSESLintScope.Reference.WRITE, + initializer, + null, + false, + true, + ); this.visit(initializer); } } @@ -700,7 +725,14 @@ class Referencer extends OriginalReferencer { if (id && id.type === 'Identifier') { scope.__define( id, - new Definition('NamespaceName', id, node, null, null, null), + new TSESLintScope.Definition( + 'NamespaceName', + id, + node, + null, + null, + null, + ), ); } this.visit(body); @@ -738,7 +770,14 @@ class Referencer extends OriginalReferencer { if (id && id.type === 'Identifier') { this.currentScope().__define( id, - new Definition('ImportBinding', id, node, null, null, null), + new TSESLintScope.Definition( + 'ImportBinding', + id, + node, + null, + null, + null, + ), ); } this.visit(moduleReference); diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index 71478ee2ad62..edc5d12bf67d 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -88,12 +88,12 @@ export function parseForESLint( ast.sourceType = options.sourceType; traverser.traverse(ast, { - enter(node: any) { + enter(node) { switch (node.type) { // Function#body cannot be null in ESTree spec. case 'FunctionExpression': if (!node.body) { - node.type = `TSEmptyBody${node.type}` as AST_NODE_TYPES; + node.type = `TSEmptyBody${node.type}` as any; } break; // no default diff --git a/packages/parser/src/scope/scope-manager.ts b/packages/parser/src/scope/scope-manager.ts index 7b7e53c9e84c..648e24b77f8b 100644 --- a/packages/parser/src/scope/scope-manager.ts +++ b/packages/parser/src/scope/scope-manager.ts @@ -1,18 +1,14 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; -import EslintScopeManager, { - ScopeManagerOptions, -} from 'eslint-scope/lib/scope-manager'; -import { Scope } from 'eslint-scope/lib/scope'; +import { TSESTree, TSESLintScope } from '@typescript-eslint/experimental-utils'; import { EmptyFunctionScope, EnumScope } from './scopes'; /** * based on eslint-scope */ -export class ScopeManager extends EslintScopeManager { - scopes!: Scope[]; - globalScope!: Scope; +export class ScopeManager extends TSESLintScope.ScopeManager { + scopes!: TSESLintScope.Scope[]; + globalScope!: TSESLintScope.Scope; - constructor(options: ScopeManagerOptions) { + constructor(options: TSESLintScope.ScopeManagerOptions) { super(options); } diff --git a/packages/parser/src/scope/scopes.ts b/packages/parser/src/scope/scopes.ts index 9dff225a7213..4ddaa297d535 100644 --- a/packages/parser/src/scope/scopes.ts +++ b/packages/parser/src/scope/scopes.ts @@ -1,12 +1,11 @@ -import { TSESTree } from '@typescript-eslint/typescript-estree'; -import { Scope } from 'eslint-scope/lib/scope'; +import { TSESTree, TSESLintScope } from '@typescript-eslint/experimental-utils'; import { ScopeManager } from './scope-manager'; /** The scope class for enum. */ -export class EnumScope extends Scope { +export class EnumScope extends TSESLintScope.Scope { constructor( scopeManager: ScopeManager, - upperScope: Scope, + upperScope: TSESLintScope.Scope, block: TSESTree.TSEnumDeclaration | null, ) { super(scopeManager, 'enum', upperScope, block, false); @@ -14,10 +13,10 @@ export class EnumScope extends Scope { } /** The scope class for empty functions. */ -export class EmptyFunctionScope extends Scope { +export class EmptyFunctionScope extends TSESLintScope.Scope { constructor( scopeManager: ScopeManager, - upperScope: Scope, + upperScope: TSESLintScope.Scope, block: TSESTree.TSDeclareFunction | null, ) { super(scopeManager, 'empty-function', upperScope, block, false); diff --git a/packages/parser/typings/eslint-scope.d.ts b/packages/parser/typings/eslint-scope.d.ts deleted file mode 100644 index ec876c63716a..000000000000 --- a/packages/parser/typings/eslint-scope.d.ts +++ /dev/null @@ -1,494 +0,0 @@ -// Type definitions for eslint-scope 4.0.0 -// Project: http://github.com/eslint/eslint-scope -// Definitions by: Armano - -//----------------------------------------------------------------------- -// TODO - figure out how to make ScopeManager exportable so that -// the module's type declaration files don't break -//----------------------------------------------------------------------- - -declare module 'eslint-scope/lib/options' { - import { TSESTree } from '@typescript-eslint/experimental-utils'; - export type PatternVisitorCallback = ( - pattern: TSESTree.Identifier, - info: { - rest: boolean; - topLevel: boolean; - assignments: TSESTree.AssignmentPattern[]; - }, - ) => void; - - export interface PatternVisitorOptions { - processRightHandNodes?: boolean; - } - - export abstract class Visitor { - visitChildren( - node?: T, - ): void; - visit(node?: T): void; - } -} - -declare module 'eslint-scope/lib/variable' { - import { TSESTree } from '@typescript-eslint/experimental-utils'; - import Reference from 'eslint-scope/lib/reference'; - import { Definition } from 'eslint-scope/lib/definition'; - - export default class Variable { - name: string; - identifiers: TSESTree.Identifier[]; - references: Reference[]; - defs: Definition[]; - eslintUsed?: boolean; - } -} - -declare module 'eslint-scope/lib/definition' { - import { TSESTree } from '@typescript-eslint/experimental-utils'; - - export class Definition { - type: string; - name: TSESTree.BindingName; - node: TSESTree.Node; - parent?: TSESTree.Node | null; - index?: number | null; - kind?: string | null; - rest?: boolean; - - constructor( - type: string, - name: TSESTree.BindingName | TSESTree.PropertyName, - node: TSESTree.Node, - parent?: TSESTree.Node | null, - index?: number | null, - kind?: string | null, - ); - } - - export class ParameterDefinition extends Definition { - constructor( - name: TSESTree.Node, - node: TSESTree.Node, - index?: number | null, - rest?: boolean, - ); - } -} - -declare module 'eslint-scope/lib/pattern-visitor' { - import ScopeManager from 'eslint-scope/lib/scope-manager'; - import { TSESTree } from '@typescript-eslint/experimental-utils'; - import { - PatternVisitorCallback, - PatternVisitorOptions, - Visitor, - } from 'eslint-scope/lib/options'; - - export default class PatternVisitor extends Visitor { - protected options: any; - protected scopeManager: ScopeManager; - protected parent?: TSESTree.Node; - public rightHandNodes: TSESTree.Node[]; - - static isPattern(node: TSESTree.Node): boolean; - - constructor( - options: PatternVisitorOptions, - rootPattern: any, - callback: PatternVisitorCallback, - ); - - Identifier(pattern: TSESTree.Node): void; - Property(property: TSESTree.Node): void; - ArrayPattern(pattern: TSESTree.Node): void; - AssignmentPattern(pattern: TSESTree.Node): void; - RestElement(pattern: TSESTree.Node): void; - MemberExpression(node: TSESTree.Node): void; - SpreadElement(node: TSESTree.Node): void; - ArrayExpression(node: TSESTree.Node): void; - AssignmentExpression(node: TSESTree.Node): void; - CallExpression(node: TSESTree.Node): void; - } -} - -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/experimental-utils'; - import { - PatternVisitorCallback, - PatternVisitorOptions, - Visitor, - } from 'eslint-scope/lib/options'; - - export default class Referencer extends Visitor { - protected isInnerMethodDefinition: boolean; - protected options: any; - protected scopeManager: SM; - protected parent?: TSESTree.Node; - - constructor(options: any, scopeManager: SM); - - currentScope(): Scope; - close(node: TSESTree.Node): void; - pushInnerMethodDefinition(isInnerMethodDefinition: boolean): boolean; - popInnerMethodDefinition(isInnerMethodDefinition: boolean): void; - - referencingDefaultValue( - pattern: any, - assignments: any, - maybeImplicitGlobal: any, - init: boolean, - ): void; - visitPattern( - node: TSESTree.Node, - options: PatternVisitorOptions, - callback: PatternVisitorCallback, - ): void; - visitFunction(node: TSESTree.Node): void; - visitClass(node: TSESTree.Node): void; - visitProperty(node: TSESTree.Node): void; - visitForIn(node: TSESTree.Node): void; - visitVariableDeclaration( - variableTargetScope: any, - type: any, - node: TSESTree.Node, - index: any, - ): void; - - AssignmentExpression(node: TSESTree.Node): void; - CatchClause(node: TSESTree.Node): void; - Program(node: TSESTree.Node): void; - Identifier(node: TSESTree.Node): void; - UpdateExpression(node: TSESTree.Node): void; - MemberExpression(node: TSESTree.Node): void; - Property(node: TSESTree.Node): void; - MethodDefinition(node: TSESTree.Node): void; - BreakStatement(): void; - ContinueStatement(): void; - LabeledStatement(node: TSESTree.Node): void; - ForStatement(node: TSESTree.Node): void; - ClassExpression(node: TSESTree.Node): void; - ClassDeclaration(node: TSESTree.Node): void; - CallExpression(node: TSESTree.Node): void; - BlockStatement(node: TSESTree.Node): void; - ThisExpression(): void; - WithStatement(node: TSESTree.Node): void; - VariableDeclaration(node: TSESTree.Node): void; - SwitchStatement(node: TSESTree.Node): void; - FunctionDeclaration(node: TSESTree.Node): void; - FunctionExpression(node: TSESTree.Node): void; - ForOfStatement(node: TSESTree.Node): void; - ForInStatement(node: TSESTree.Node): void; - ArrowFunctionExpression(node: TSESTree.Node): void; - ImportDeclaration(node: TSESTree.Node): void; - visitExportDeclaration(node: TSESTree.Node): void; - ExportDeclaration(node: TSESTree.Node): void; - ExportNamedDeclaration(node: TSESTree.Node): void; - ExportSpecifier(node: TSESTree.Node): void; - MetaProperty(): void; - } -} - -declare module 'eslint-scope/lib/scope' { - 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'; - import { Definition } from 'eslint-scope/lib/definition'; - - export type ScopeType = - | 'block' - | 'catch' - | 'class' - | 'for' - | 'function' - | 'function-expression-name' - | 'global' - | 'module' - | 'switch' - | 'with' - | 'TDZ' - | 'enum' - | 'empty-function'; - - export class Scope { - type: ScopeType; - isStrict: boolean; - upper: Scope | null; - childScopes: Scope[]; - variableScope: Scope; - block: TSESTree.Node; - variables: Variable[]; - set: Map; - references: Reference[]; - through: Reference[]; - thisFound?: boolean; - functionExpressionScope: boolean; - - constructor( - scopeManager: ScopeManager, - type: ScopeType, - upperScope: Scope | null, - block: TSESTree.Node | null, - isMethodDefinition: boolean, - ); - - __shouldStaticallyClose(scopeManager: ScopeManager): boolean; - __shouldStaticallyCloseForGlobal(ref: any): boolean; - __staticCloseRef(ref: any): void; - __dynamicCloseRef(ref: any): void; - __globalCloseRef(ref: any): void; - __close(scopeManager: ScopeManager): Scope; - __isValidResolution(ref: any, variable: any): boolean; - __resolve(ref: any): boolean; - __delegateToUpperScope(ref: any): void; - __addDeclaredVariablesOfNode(variable: any, node: TSESTree.Node): void; - __defineGeneric( - name: any, - set: any, - variables: any, - node: any, - def: Definition, - ): void; - - __define(node: TSESTree.Node, def: Definition): void; - - __referencing( - node: TSESTree.Node, - assign: number, - writeExpr: TSESTree.Node, - maybeImplicitGlobal: any, - partial: any, - init: any, - ): void; - - __detectEval(): void; - __detectThis(): void; - __isClosed(): boolean; - /** - * returns resolved {Reference} - * @method Scope#resolve - * @param {Espree.Identifier} ident - identifier to be resolved. - * @returns {Reference} reference - */ - resolve(ident: TSESTree.Node): Reference; - - /** - * returns this scope is static - * @method Scope#isStatic - * @returns {boolean} static - */ - isStatic(): boolean; - - /** - * returns this scope has materialized arguments - * @method Scope#isArgumentsMaterialized - * @returns {boolean} arguemnts materialized - */ - isArgumentsMaterialized(): boolean; - - /** - * returns this scope has materialized `this` reference - * @method Scope#isThisMaterialized - * @returns {boolean} this materialized - */ - isThisMaterialized(): boolean; - - isUsedName(name: any): boolean; - } - - export class GlobalScope extends Scope { - constructor(scopeManager: ScopeManager, block: TSESTree.Node | null); - } - - export class ModuleScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class FunctionExpressionNameScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class CatchScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class WithScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class BlockScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class SwitchScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class FunctionScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - isMethodDefinition: boolean, - ); - } - - export class ForScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } - - export class ClassScope extends Scope { - constructor( - scopeManager: ScopeManager, - upperScope: Scope, - block: TSESTree.Node | null, - ); - } -} - -declare module 'eslint-scope/lib/reference' { - import { TSESTree } from '@typescript-eslint/experimental-utils'; - import { Scope } from 'eslint-scope/lib/scope'; - import Variable from 'eslint-scope/lib/variable'; - - export default class 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; - - static READ: 0x1; - static WRITE: 0x2; - static RW: 0x3; - } -} - -declare module 'eslint-scope/lib/scope-manager' { - import { TSESTree } from '@typescript-eslint/experimental-utils'; - import { Scope } from 'eslint-scope/lib/scope'; - import Variable from 'eslint-scope/lib/variable'; - - export interface ScopeManagerOptions { - directive?: boolean; - optimistic?: boolean; - ignoreEval?: boolean; - nodejsScope?: boolean; - sourceType?: 'module' | 'script'; - impliedStrict?: boolean; - ecmaVersion?: number; - } - - export default class ScopeManager { - __options: ScopeManagerOptions; - __currentScope: Scope; - scopes: Scope[]; - globalScope: Scope; - - constructor(options: ScopeManagerOptions); - - __useDirective(): boolean; - __isOptimistic(): boolean; - __ignoreEval(): boolean; - __isNodejsScope(): boolean; - isModule(): boolean; - isImpliedStrict(): boolean; - isStrictModeSupported(): boolean; - - // Returns appropriate scope for this node. - __get(node: TSESTree.Node): Scope; - getDeclaredVariables(node: TSESTree.Node): Variable[]; - acquire(node: TSESTree.Node, inner?: boolean): Scope | null; - acquireAll(node: TSESTree.Node): Scope | null; - release(node: TSESTree.Node, inner?: boolean): Scope | null; - attach(): void; - detach(): void; - - __nestScope(scope: Scope): Scope; - __nestGlobalScope(node: TSESTree.Node): Scope; - __nestBlockScope(node: TSESTree.Node): Scope; - __nestFunctionScope( - node: TSESTree.Node, - isMethodDefinition: boolean, - ): Scope; - __nestForScope(node: TSESTree.Node): Scope; - __nestCatchScope(node: TSESTree.Node): Scope; - __nestWithScope(node: TSESTree.Node): Scope; - __nestClassScope(node: TSESTree.Node): Scope; - __nestSwitchScope(node: TSESTree.Node): Scope; - __nestModuleScope(node: TSESTree.Node): Scope; - __nestFunctionExpressionNameScope(node: TSESTree.Node): Scope; - - __isES6(): boolean; - } -} - -declare module 'eslint-scope' { - import ScopeManager from 'eslint-scope/lib/scope-manager'; - import Reference from 'eslint-scope/lib/reference'; - import Scope from 'eslint-scope/lib/scope'; - import Variable from 'eslint-scope/lib/variable'; - - interface AnalysisOptions { - optimistic?: boolean; - directive?: boolean; - ignoreEval?: boolean; - nodejsScope?: boolean; - impliedStrict?: boolean; - fallback?: string | ((node: {}) => string[]); - sourceType?: 'script' | 'module'; - ecmaVersion?: number; - } - function analyze(ast: {}, options?: AnalysisOptions): ScopeManager; - - const version: string; - - export { - AnalysisOptions, - version, - Reference, - Variable, - Scope, - ScopeManager, - analyze, - }; -} - -declare module 'eslint/lib/util/traverser'; diff --git a/packages/parser/typings/eslint.d.ts b/packages/parser/typings/eslint.d.ts new file mode 100644 index 000000000000..15a965cd48d1 --- /dev/null +++ b/packages/parser/typings/eslint.d.ts @@ -0,0 +1,14 @@ +declare module 'eslint/lib/util/traverser' { + import { TSESTree } from '@typescript-eslint/experimental-utils'; + const traverser: { + traverse( + node: TSESTree.Node, + options: { + enter?: (node: TSESTree.Node, parent: TSESTree.Node) => void; + leave?: (node: TSESTree.Node, parent: TSESTree.Node) => void; + visitorKeys?: Record; + }, + ): void; + }; + export = traverser; +}