From 00f58b9bfa0abc66cbc4d875ca65c715401935d6 Mon Sep 17 00:00:00 2001 From: Sven SAULEAU Date: Mon, 24 Apr 2017 21:15:15 +0200 Subject: [PATCH] feat: optional chaing --- .../.npmignore | 3 + .../README.md | 1 + .../package.json | 20 ++++++ .../src/index.js | 64 +++++++++++++++++++ .../fixtures/general/member-access/actual.js | 1 + .../general/member-access/expected.js | 1 + .../general/nested-member-access/actual.js | 1 + .../general/nested-member-access/expected.js | 1 + .../test/fixtures/general/options.json | 3 + .../test/index.js | 3 + 10 files changed, 98 insertions(+) create mode 100644 packages/babel-plugin-transform-optional-chaining/.npmignore create mode 100644 packages/babel-plugin-transform-optional-chaining/README.md create mode 100644 packages/babel-plugin-transform-optional-chaining/package.json create mode 100644 packages/babel-plugin-transform-optional-chaining/src/index.js create mode 100644 packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/actual.js create mode 100644 packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/expected.js create mode 100644 packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/actual.js create mode 100644 packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/expected.js create mode 100644 packages/babel-plugin-transform-optional-chaining/test/fixtures/general/options.json create mode 100644 packages/babel-plugin-transform-optional-chaining/test/index.js diff --git a/packages/babel-plugin-transform-optional-chaining/.npmignore b/packages/babel-plugin-transform-optional-chaining/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-transform-optional-chaining/README.md b/packages/babel-plugin-transform-optional-chaining/README.md new file mode 100644 index 0000000000..41fdea4a70 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/README.md @@ -0,0 +1 @@ +# babel-plugin-transform-optional-chaining diff --git a/packages/babel-plugin-transform-optional-chaining/package.json b/packages/babel-plugin-transform-optional-chaining/package.json new file mode 100644 index 0000000000..1f6fc11699 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/package.json @@ -0,0 +1,20 @@ +{ + "name": "babel-plugin-transform-optional-chaining", + "version": "7.0.0-alpha.7", + "description": "", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-optional-chaining", + "license": "MIT", + "main": "lib/index.js", + "dependencies": { + "babel-traverse": "7.0.0-alpha.7", + "babel-types": "7.0.0-alpha.7", + "babel-template": "7.0.0-alpha.7", + "lodash": "^4.2.0" + }, + "keywords": [ + "babel-plugin" + ], + "devDependencies": { + "babel-helper-plugin-test-runner": "7.0.0-alpha.7" + } +} diff --git a/packages/babel-plugin-transform-optional-chaining/src/index.js b/packages/babel-plugin-transform-optional-chaining/src/index.js new file mode 100644 index 0000000000..6e29dde42a --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/src/index.js @@ -0,0 +1,64 @@ +import createTemplate from "babel-template"; +import traverse from "babel-traverse"; + +const nullOrUndefinedCheck = createTemplate(` + typeof CHECK !== "undefined" && CHECK !== null + ? NEXT + : null +`); + +function isOptional(path) { + return path.node.optional === true; +} + +const nullOrUndefinedCheckVisitor = { + noScope: true, + + Identifier(path, replacements) { + if (path.node.name in replacements) { + path.replaceInline(replacements[path.node.name]); + } + }, +}; + +function createCheck(node, object) { + + const template = nullOrUndefinedCheck(); + + traverse(template, nullOrUndefinedCheckVisitor, null, { + CHECK: object, + NEXT: node, + }); + + return template; +} + +export default function ({ types: t }) { + + return { + visitor: { + MemberExpression(path) { + + if (isOptional(path)) { + let { object } = path.node; + + while ( + t.isMemberExpression(object) + && isOptional({ node: object }) + ) { + object = createCheck( + object, + object.object + ); + } + + path.replaceWith( + createCheck(path.node, object) + ); + + path.stop(); + } + }, + }, + }; +} diff --git a/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/actual.js b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/actual.js new file mode 100644 index 0000000000..6ed5c83b93 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/actual.js @@ -0,0 +1 @@ +foo?.bar diff --git a/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/expected.js b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/expected.js new file mode 100644 index 0000000000..473cdedb0f --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/expected.js @@ -0,0 +1 @@ +typeof foo !== "undefined" && foo !== null ? foo.bar : null; \ No newline at end of file diff --git a/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/actual.js b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/actual.js new file mode 100644 index 0000000000..fc0ce9aea6 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/actual.js @@ -0,0 +1 @@ +foo?.bar?.vroum diff --git a/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/expected.js b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/expected.js new file mode 100644 index 0000000000..3c37951fcf --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/nested-member-access/expected.js @@ -0,0 +1 @@ +typeof (typeof foo !== "undefined" && foo !== null ? foo.bar : null) !== "undefined" && (typeof foo !== "undefined" && foo !== null ? foo.bar : null) !== null ? foo.bar.vroum : null; \ No newline at end of file diff --git a/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/options.json b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/options.json new file mode 100644 index 0000000000..846cf98412 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/fixtures/general/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-optional-chaining"] +} diff --git a/packages/babel-plugin-transform-optional-chaining/test/index.js b/packages/babel-plugin-transform-optional-chaining/test/index.js new file mode 100644 index 0000000000..09cfbc31f5 --- /dev/null +++ b/packages/babel-plugin-transform-optional-chaining/test/index.js @@ -0,0 +1,3 @@ +import runner from "babel-helper-plugin-test-runner"; + +runner(__dirname);