diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index edc5d12bf67..11a68518d73 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -1,12 +1,12 @@ +import { TSESLint } from '@typescript-eslint/experimental-utils'; import { AST_NODE_TYPES, parseAndGenerateServices, - TSESTreeOptions, ParserServices, + TSESTreeOptions, } 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 { simpleTraverse } from './simple-traverse'; import { visitorKeys } from './visitor-keys'; type ParserOptions = TSESLint.ParserOptions; @@ -87,7 +87,7 @@ export function parseForESLint( const { ast, services } = parseAndGenerateServices(code, parserOptions); ast.sourceType = options.sourceType; - traverser.traverse(ast, { + simpleTraverse(ast, { enter(node) { switch (node.type) { // Function#body cannot be null in ESTree spec. diff --git a/packages/parser/src/simple-traverse.ts b/packages/parser/src/simple-traverse.ts new file mode 100644 index 00000000000..8cc007058ad --- /dev/null +++ b/packages/parser/src/simple-traverse.ts @@ -0,0 +1,58 @@ +import { TSESTree } from '@typescript-eslint/typescript-estree'; +import { visitorKeys } from './visitor-keys'; + +function isValidNode(x: any): x is TSESTree.Node { + return x !== null && typeof x === 'object' && typeof x.type === 'string'; +} + +function getVisitorKeysForNode( + allVisitorKeys: typeof visitorKeys, + node: TSESTree.Node, +): readonly string[] { + const keys = allVisitorKeys[node.type]; + return keys || []; +} + +interface SimpleTraverseOptions { + enter: (node: TSESTree.Node, parent: TSESTree.Node | undefined) => void; +} + +class SimpleTraverser { + private allVisitorKeys = visitorKeys; + private enter: SimpleTraverseOptions['enter']; + + constructor({ enter }: SimpleTraverseOptions) { + this.enter = enter; + } + + traverse(node: unknown, parent: TSESTree.Node | undefined) { + if (!isValidNode(node)) { + return; + } + this.enter(node, parent); + + const keys = getVisitorKeysForNode(this.allVisitorKeys, node); + if (keys.length < 1) { + return; + } + + for (const key of keys) { + const childOrChildren = node[key as keyof typeof node]; + + if (Array.isArray(childOrChildren)) { + for (const child of childOrChildren) { + this.traverse(child, node); + } + } else { + this.traverse(childOrChildren, node); + } + } + } +} + +export function simpleTraverse( + startingNode: TSESTree.Node, + options: SimpleTraverseOptions, +) { + new SimpleTraverser(options).traverse(startingNode, undefined); +} diff --git a/packages/parser/tsconfig.build.json b/packages/parser/tsconfig.build.json index 578d8230840..a94802fb081 100644 --- a/packages/parser/tsconfig.build.json +++ b/packages/parser/tsconfig.build.json @@ -4,5 +4,5 @@ "declaration": true, "outDir": "./dist" }, - "include": ["src", "typings"] + "include": ["src"] } diff --git a/packages/parser/tsconfig.json b/packages/parser/tsconfig.json index 58599d3d3ed..6f763b588b5 100644 --- a/packages/parser/tsconfig.json +++ b/packages/parser/tsconfig.json @@ -1,5 +1,5 @@ { "extends": "./tsconfig.build.json", - "include": ["src", "typings", "tests", "tools"], + "include": ["src", "tests", "tools"], "exclude": ["tests/fixtures"] } diff --git a/packages/parser/typings/eslint.d.ts b/packages/parser/typings/eslint.d.ts deleted file mode 100644 index 15a965cd48d..00000000000 --- a/packages/parser/typings/eslint.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -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; -}