From 20d9a101862bceb374b046e14725f4f44b5022cf Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Mon, 16 Mar 2020 16:52:33 -0500 Subject: [PATCH] Add estree parsing support for `export * as A` (#11254) --- eslint/babel-eslint-parser/test/index.js | 35 ++++++-- packages/babel-parser/src/plugins/estree.js | 24 ++++++ .../fixtures/estree/export/batch/input.js | 1 + .../fixtures/estree/export/batch/output.json | 67 +++++++++++++++ .../fixtures/estree/export/ns-from/input.js | 1 + .../estree/export/ns-from/output.json | 83 +++++++++++++++++++ .../test/fixtures/estree/export/options.json | 4 + 7 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/estree/export/batch/input.js create mode 100644 packages/babel-parser/test/fixtures/estree/export/batch/output.json create mode 100644 packages/babel-parser/test/fixtures/estree/export/ns-from/input.js create mode 100644 packages/babel-parser/test/fixtures/estree/export/ns-from/output.json create mode 100644 packages/babel-parser/test/fixtures/estree/export/options.json diff --git a/eslint/babel-eslint-parser/test/index.js b/eslint/babel-eslint-parser/test/index.js index 16204fbb9a..6fd61c8414 100644 --- a/eslint/babel-eslint-parser/test/index.js +++ b/eslint/babel-eslint-parser/test/index.js @@ -9,28 +9,38 @@ const BABEL_OPTIONS = { "@babel/eslint-shared-fixtures/config/babel.config.js", ), }; -const ALLOWED_PROPERTIES = [ +const PROPS_TO_REMOVE = [ "importKind", "exportKind", "variance", "typeArguments", ]; +// We can remove needing to drop "exported" if null once this lands: +// https://github.com/acornjs/acorn/pull/889 +const PROPS_TO_REMOVE_IF_NULL = ["exported"]; -function deeplyRemoveProperties(obj, props) { +function deeplyRemoveProperties(obj, props, propsIfNull) { for (const [k, v] of Object.entries(obj)) { if (typeof v === "object") { if (Array.isArray(v)) { for (const el of v) { - if (el != null) deeplyRemoveProperties(el, props); + if (el != null) { + deeplyRemoveProperties(el, props, propsIfNull); + } } } - if (props.includes(k)) delete obj[k]; - else if (v != null) deeplyRemoveProperties(v, props); + if (props.includes(k) || (propsIfNull.includes(k) && v === null)) { + delete obj[k]; + } else if (v != null) { + deeplyRemoveProperties(v, props, propsIfNull); + } continue; } - if (props.includes(k)) delete obj[k]; + if (props.includes(k) || (propsIfNull.includes(k) && v === null)) { + delete obj[k]; + } } } @@ -62,7 +72,7 @@ describe("Babel and Espree", () => { eslintScopeManager: true, babelOptions: BABEL_OPTIONS, }).ast; - deeplyRemoveProperties(babelAST, ALLOWED_PROPERTIES); + deeplyRemoveProperties(babelAST, PROPS_TO_REMOVE, PROPS_TO_REMOVE_IF_NULL); expect(babelAST).toEqual(espreeAST); } @@ -266,6 +276,17 @@ describe("Babel and Espree", () => { parseAndAssertSame('export * from "foo";'); }); + // Espree doesn't support `export * as ns` yet + it("export * as ns", () => { + const code = 'export * as Foo from "foo";'; + const babylonAST = parseForESLint(code, { + eslintVisitorKeys: true, + eslintScopeManager: true, + babelOptions: BABEL_OPTIONS, + }).ast; + expect(babylonAST.tokens[1].type).toEqual("Punctuator"); + }); + it("export named", () => { parseAndAssertSame("var foo = 1;export { foo };"); }); diff --git a/packages/babel-parser/src/plugins/estree.js b/packages/babel-parser/src/plugins/estree.js index 659bdd2c0d..1f04b03e30 100644 --- a/packages/babel-parser/src/plugins/estree.js +++ b/packages/babel-parser/src/plugins/estree.js @@ -407,4 +407,28 @@ export default (superClass: Class): Class => super.toReferencedListDeep(exprList, isParenthesizedExpr); } + + parseExport(node: N.Node) { + super.parseExport(node); + + switch (node.type) { + case "ExportAllDeclaration": + node.exported = null; + break; + + case "ExportNamedDeclaration": + if ( + node.specifiers.length === 1 && + node.specifiers[0].type === "ExportNamespaceSpecifier" + ) { + node.type = "ExportAllDeclaration"; + node.exported = node.specifiers[0].exported; + delete node.specifiers; + } + + break; + } + + return node; + } }; diff --git a/packages/babel-parser/test/fixtures/estree/export/batch/input.js b/packages/babel-parser/test/fixtures/estree/export/batch/input.js new file mode 100644 index 0000000000..9ec8f63ab2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/export/batch/input.js @@ -0,0 +1 @@ +export * from "foo"; diff --git a/packages/babel-parser/test/fixtures/estree/export/batch/output.json b/packages/babel-parser/test/fixtures/estree/export/batch/output.json new file mode 100644 index 0000000000..13118b1f2b --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/export/batch/output.json @@ -0,0 +1,67 @@ +{ + "type": "File", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportAllDeclaration", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "source": { + "type": "Literal", + "start": 14, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "value": "foo", + "raw": "\"foo\"" + }, + "exported": null + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/export/ns-from/input.js b/packages/babel-parser/test/fixtures/estree/export/ns-from/input.js new file mode 100644 index 0000000000..27357f4758 --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/export/ns-from/input.js @@ -0,0 +1 @@ +export * as A from 'test'; diff --git a/packages/babel-parser/test/fixtures/estree/export/ns-from/output.json b/packages/babel-parser/test/fixtures/estree/export/ns-from/output.json new file mode 100644 index 0000000000..5b60865a3e --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/export/ns-from/output.json @@ -0,0 +1,83 @@ +{ + "type": "File", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportAllDeclaration", + "start": 0, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "source": { + "type": "Literal", + "start": 19, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 25 + } + }, + "value": "test", + "raw": "'test'" + }, + "exported": { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + }, + "identifierName": "A" + }, + "name": "A" + } + } + ] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/estree/export/options.json b/packages/babel-parser/test/fixtures/estree/export/options.json new file mode 100644 index 0000000000..9cb285f13a --- /dev/null +++ b/packages/babel-parser/test/fixtures/estree/export/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["estree"], + "sourceType": "module" +}