From 73b138eeb8429aed1ecdbc29838fc4353ccc46b7 Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Thu, 2 May 2019 12:10:05 -0500 Subject: [PATCH] fix #201 --- .../babel-plugin-flow-runtime/package.json | 2 +- .../functionObjectPatternWithAnnotation.js | 35 +++++++++++++++++ .../functionWithComplexPattern.js | 38 +++++++++++++++++++ .../src/__tests__/fixtures.js | 1 + .../src/__tests__/testTransform.js | 12 ++++-- .../src/__tests__/transform.test.js | 10 ++--- .../src/preTransformVisitors.js | 21 ++++++++++ .../src/transformVisitors.js | 8 +--- yarn.lock | 12 ++++++ 9 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionObjectPatternWithAnnotation.js create mode 100644 packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionWithComplexPattern.js diff --git a/packages/babel-plugin-flow-runtime/package.json b/packages/babel-plugin-flow-runtime/package.json index 4026a0f..6f8c3c0 100644 --- a/packages/babel-plugin-flow-runtime/package.json +++ b/packages/babel-plugin-flow-runtime/package.json @@ -2,7 +2,7 @@ "name": "babel-plugin-flow-runtime", "homepage": "https://codemix.github.io/flow-runtime", "repository": "https://github.com/codemix/flow-runtime.git", - "version": "0.18.0", + "version": "0.19.0", "description": "Transforms flow type annotations into flow-runtime types, optionally adds runtime type validation to annotated code.", "main": "babel-plugin-flow-runtime.js", "scripts": { diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionObjectPatternWithAnnotation.js b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionObjectPatternWithAnnotation.js new file mode 100644 index 0000000..772ddfe --- /dev/null +++ b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionObjectPatternWithAnnotation.js @@ -0,0 +1,35 @@ +export const integration = { + presets: [ + ["@babel/preset-env", {"targets": {"node": "current"}}], + '@babel/preset-flow', + ], + plugins: [ + 'babel-plugin-flow-runtime', + ], +}; + +export const input = ` + class Model { + static init({foo}: {foo: string}) { + + } + } +`; + +export const expected = ` +"use strict"; + var _flowRuntime = _interopRequireDefault(require("flow-runtime")); + function _interopRequireDefault(obj) { +return obj && obj.__esModule ? obj : { +default: obj +}; + +} @_flowRuntime.default.annotate(_flowRuntime.default.class("Model", _flowRuntime.default.staticMethod("init", _flowRuntime.default.param("_arg", _flowRuntime.default.object(_flowRuntime.default.property("foo", _flowRuntime.default.string())))))) class Model { +static init(_arg) { +let { +foo +} = _arg; + +} +} +`; diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionWithComplexPattern.js b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionWithComplexPattern.js new file mode 100644 index 0000000..5196b4a --- /dev/null +++ b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/patternMatching/functionWithComplexPattern.js @@ -0,0 +1,38 @@ +export const integration = { + presets: [ + ["@babel/preset-env", {"targets": {"node": "current"}}], + '@babel/preset-flow', + ], + plugins: [ + 'babel-plugin-flow-runtime', + ], +}; + +export const input = ` + class Model { + static init({a: [b, {d, e}], f: {g: [h, ...k], i}, ...j}: {a: [number, {d: string, e: number}], f: {g: [string], i: number}}) { + + } + } +`; + +export const expected = ` +"use strict"; + var _flowRuntime = _interopRequireDefault(require("flow-runtime")); + function _interopRequireDefault(obj) { +return obj && obj.__esModule ? obj : { +default: obj +}; + +} @_flowRuntime.default.annotate(_flowRuntime.default.class("Model", _flowRuntime.default.staticMethod("init", _flowRuntime.default.param("_arg", _flowRuntime.default.object(_flowRuntime.default.property("a", _flowRuntime.default.tuple(_flowRuntime.default.number(), _flowRuntime.default.object(_flowRuntime.default.property("d", _flowRuntime.default.string()), _flowRuntime.default.property("e", _flowRuntime.default.number())))), _flowRuntime.default.property("f", _flowRuntime.default.object(_flowRuntime.default.property("g", _flowRuntime.default.tuple(_flowRuntime.default.string())), _flowRuntime.default.property("i", _flowRuntime.default.number())))))))) class Model { +static init(_arg) { +let { +a: [b, { +d, e +}], f: { +g: [h, ...k], i +}, ...j +} = _arg; +} +} +`; diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/fixtures.js b/packages/babel-plugin-flow-runtime/src/__tests__/fixtures.js index b72aa90..8e65d91 100644 --- a/packages/babel-plugin-flow-runtime/src/__tests__/fixtures.js +++ b/packages/babel-plugin-flow-runtime/src/__tests__/fixtures.js @@ -43,6 +43,7 @@ export type Fixture = { annotated?: string; combined?: string; customRuntime?: string; + integration?: boolean; }; const fixtures: Map = new Map(files.filter(filterIncluded).map(filename => { diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/testTransform.js b/packages/babel-plugin-flow-runtime/src/__tests__/testTransform.js index 538f6b1..0c26a8f 100644 --- a/packages/babel-plugin-flow-runtime/src/__tests__/testTransform.js +++ b/packages/babel-plugin-flow-runtime/src/__tests__/testTransform.js @@ -3,6 +3,7 @@ import {equal} from 'assert'; import transform from '../transform'; +import * as babel from '@babel/core'; import * as babylon from '@babel/parser'; import generate from '@babel/generator'; @@ -67,9 +68,14 @@ function normalize (input: string): string { ; } -export default function testTransform(input: string, options: Options, expected: string) { +export default function testTransform(input: string, options: Options, expected: string, integration?: Object) { const parsed = parse(input); - const transformed = stripFlowTypes(transform(parsed, options)); - const generated = generate(transformed).code; + let generated; + if (integration) { + generated = babel.transform(input, integration).code; + } else { + const transformed = stripFlowTypes(transform(parsed, options)); + generated = generate(transformed).code; + } equal(normalize(generated), normalize(expected)); } diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/transform.test.js b/packages/babel-plugin-flow-runtime/src/__tests__/transform.test.js index c709245..7a8ae75 100644 --- a/packages/babel-plugin-flow-runtime/src/__tests__/transform.test.js +++ b/packages/babel-plugin-flow-runtime/src/__tests__/transform.test.js @@ -5,23 +5,23 @@ import fixtures from './fixtures'; import testTransform from './testTransform'; describe('transform', () => { - for (const [name, {input, expected, annotated, combined, customRuntime}] of fixtures) { + for (const [name, {input, expected, annotated, combined, customRuntime, integration}] of fixtures) { it(`should transform ${name}`, () => { - testTransform(input, {assert: true, annotate: false}, expected); + testTransform(input, {assert: true, annotate: false}, expected, integration); }); if (annotated) { it(`should transform ${name} with decorations`, () => { - testTransform(input, {assert: false, annotate: true}, annotated); + testTransform(input, {assert: false, annotate: true, integration}, annotated, integration); }); } if (combined) { it(`should transform ${name} with decorations and assertions`, () => { - testTransform(input, {assert: true, annotate: true}, combined); + testTransform(input, {assert: true, annotate: true, integration}, combined, integration); }); } if (customRuntime) { it(`should transform ${name} with custom runtime path`, () => { - testTransform(input, {libraryName: './custom-flow-runtime'}, customRuntime); + testTransform(input, {libraryName: './custom-flow-runtime'}, customRuntime, integration); }); } } diff --git a/packages/babel-plugin-flow-runtime/src/preTransformVisitors.js b/packages/babel-plugin-flow-runtime/src/preTransformVisitors.js index 407bad7..50c8c03 100644 --- a/packages/babel-plugin-flow-runtime/src/preTransformVisitors.js +++ b/packages/babel-plugin-flow-runtime/src/preTransformVisitors.js @@ -15,6 +15,26 @@ export default function preTransformVisitors (context: ConversionContext): Objec }; } +function removePatternBindings(path: NodePath) { + if (path.isIdentifier()) { + path.scope.removeBinding(path.node.name); + } else if (path.isRestElement()) { + removePatternBindings(path.get('argument')); + } else if (path.isObjectProperty()) { + removePatternBindings(path.get('value')); + } else if (path.isObjectPattern()) { + const properties = path.get('properties'); + for (let i = 0; i < properties.length; i++) { + removePatternBindings(properties[i]); + } + } else if (path.isArrayPattern()) { + const elements = path.get('elements'); + for (let i = 0; i < elements.length; i++) { + removePatternBindings(elements[i]); + } + } +} + function foldComplexParamsIntoBody (path: NodePath) { let body = path.get('body'); const params = path.get('params'); @@ -39,6 +59,7 @@ function foldComplexParamsIntoBody (path: NodePath) { body = path.get('body'); path.node.expression = false; } + removePatternBindings(param); const cloned = t.cloneDeep(param.node); const uid = body.scope.generateUidIdentifier(`arg${params[i].key}`); uid.__flowRuntime__wasParam = true; diff --git a/packages/babel-plugin-flow-runtime/src/transformVisitors.js b/packages/babel-plugin-flow-runtime/src/transformVisitors.js index 67b00c4..0ac485b 100644 --- a/packages/babel-plugin-flow-runtime/src/transformVisitors.js +++ b/packages/babel-plugin-flow-runtime/src/transformVisitors.js @@ -264,14 +264,12 @@ export default function transformVisitors (context: ConversionContext): Object { path.get('init').node ); + path.scope.removeOwnBinding(name); context.replacePath(path, t.variableDeclarator( t.identifier(name), wrapped )); } - else { - context.replacePath(id, t.identifier(name)); - } } else if (shouldCheck) { const wrapped = context.assert( @@ -279,16 +277,12 @@ export default function transformVisitors (context: ConversionContext): Object { path.get('init').node ); - // vjpr: We remove the scope. path.scope.removeOwnBinding(name); context.replacePath(path, t.variableDeclarator( t.identifier(name), wrapped )); } - else { - context.replacePath(id, t.identifier(name)); - } }, AssignmentExpression (path: NodePath) { if (context.shouldSuppressPath(path)) { diff --git a/yarn.lock b/yarn.lock index 9390618..6f75f5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1611,6 +1611,18 @@ babel-plugin-external-helpers@^6.18.0: dependencies: babel-runtime "^6.22.0" +babel-plugin-flow-runtime@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/babel-plugin-flow-runtime/-/babel-plugin-flow-runtime-0.17.0.tgz#51d7b2e6a526edc48fad8d8eed45bf7cc32ffc08" + integrity sha512-6u9abuyr26AFzJJ7tENieAHvK37RvO5atKbZ/oIdXHABE2dHkurgdgYTDQRznmNUx+ppx2ORkwy5GBKXTake3g== + dependencies: + babel-generator "^6.21.0" + babel-traverse "^6.20.0" + babel-types "^6.16.0" + babylon "^6.16.1" + camelcase "^3.0.0" + flow-config-parser "^0.3.0" + babel-plugin-istanbul@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-2.0.3.tgz#266b304b9109607d60748474394676982f660df4"