diff --git a/src/babel/babelAstTypes.ts b/src/babel/babelAstTypes.ts index 3a30f53..17d4d44 100644 --- a/src/babel/babelAstTypes.ts +++ b/src/babel/babelAstTypes.ts @@ -5,7 +5,6 @@ import * as defaultTypes from '@babel/types' import { memoize, omit, mapValues } from 'lodash' import fork from 'ast-types/fork' import { Fork } from 'ast-types/types' -import nodePathPlugin from 'ast-types/lib/node-path' const babelAstTypes: (t?: typeof defaultTypes) => ReturnType = memoize((t: typeof defaultTypes = defaultTypes): ReturnType => { @@ -14,8 +13,6 @@ const babelAstTypes: (t?: typeof defaultTypes) => ReturnType = const { builtInTypes, Type } = types const { def, or } = Type - fork.use(nodePathPlugin) - def('Node').field('type', builtInTypes.string) def('Comment') .field('type', builtInTypes.string) @@ -118,6 +115,7 @@ const babelAstTypes: (t?: typeof defaultTypes) => ReturnType = ) } } + def('Identifier').bases('Pattern') } return fork([babel]) diff --git a/test/astx/bugs_scope.ts b/test/astx/bugs_scope.ts new file mode 100644 index 0000000..d0bc6c5 --- /dev/null +++ b/test/astx/bugs_scope.ts @@ -0,0 +1,17 @@ +import { TransformOptions } from '../../src' +import { astxTestcase } from '../astxTestcase' +import { NodePath as AstTypesNodePath } from 'ast-types/lib/node-path' +import dedent from 'dedent-js' + +astxTestcase({ + file: __filename, + input: dedent` + const foo = 1; + `, + parsers: ['babel', 'babel/tsx'], + astx: ({ astx, report }: TransformOptions): void => { + const path = astx.find`const foo = 1;`.paths[0] + report((path as AstTypesNodePath).scope !== null) + }, + expectedReports: [true], +}) diff --git a/test/astx/scope-testcase.ts b/test/astx/scope-testcase.ts new file mode 100644 index 0000000..f6c8c6d --- /dev/null +++ b/test/astx/scope-testcase.ts @@ -0,0 +1,51 @@ +import { NodePath as AstTypesNodePath } from 'ast-types/lib/node-path' +import { Astx } from '../../src' +import { astxTestcase } from '../astxTestcase' +import dedent from 'dedent-js' + +astxTestcase({ + file: __filename, + input: dedent` + const x = 1, y = 2; + function foo() { + const y = 3; + const target = x + y; + } + `, + expected: dedent` + const x = 1, y = 2; + function foo() { + const y = 3; + const target = 1 + 3; + } + `, + parsers: ['babel', 'babel/tsx'], + astx: ({ astx }) => { + for (const { $a, $b } of astx.find`const target = $a + $b`) { + inlineNaively($a) + inlineNaively($b) + } + }, +}) + +/** kludge to gain access to scope */ +type AstxWithScope = Astx & { + path: AstTypesNodePath +} + +// inspired by jscodeshift +function getDeclarator(a: AstxWithScope) { + const name = a.path.value.name + const bindings = new Astx( + a.context, + a.path.scope?.lookup(name)?.getBindings()[name] + ) + return bindings + .closest((astx) => astx.node.type === 'VariableDeclarator') + .at(0) +} + +function inlineNaively(a: Astx) { + const val = getDeclarator(a as AstxWithScope).path.get('init').value + a.replace(val) +}