diff --git a/src/babel/messages.js b/src/babel/messages.js index 8b8fd7d0d4..a12341245f 100644 --- a/src/babel/messages.js +++ b/src/babel/messages.js @@ -37,7 +37,17 @@ export const MESSAGES = { pluginNotTransformer: "The plugin $1 didn't export a Plugin instance", pluginUnknown: "Unknown plugin $1", - pluginNotFile: "Plugin $1 is resolving to a different Babel version than what is performing the transformation." + pluginNotFile: "Plugin $1 is resolving to a different Babel version than what is performing the transformation.", + + pluginInvalidProperty: "Plugin $1 provided an invalid property of $2.", + pluginInvalidPropertyVisitor: `Define your visitor methods inside a \`visitor\` property like so: + + new Plugin("foobar", { + visitor: { + // define your visitor methods here! + } + }); +` }; export function get(key: String, ...args) { diff --git a/src/babel/transformation/plugin.js b/src/babel/transformation/plugin.js index d2c620df49..2a5ac25957 100644 --- a/src/babel/transformation/plugin.js +++ b/src/babel/transformation/plugin.js @@ -1,13 +1,30 @@ import PluginPass from "./plugin-pass"; import * as messages from "../messages"; -import isFunction from "lodash/lang/isFunction"; import traverse from "../traversal"; import assign from "lodash/object/assign"; import clone from "lodash/lang/clone"; import File from "./file"; +import * as t from "../types"; + +const VALID_PLUGIN_PROPERTIES = [ + "visitor", "metadata", + "manipulateOptions", + "post", "pre" +]; + +const VALID_METADATA_PROPERTES = [ + "dependencies", + "optional", + "stage", + "group", + "experimental", + "secondPass" +]; export default class Plugin { constructor(key: string, plugin: Object) { + Plugin.validate(key, plugin); + plugin = assign({}, plugin); var take = function (key) { @@ -34,13 +51,25 @@ export default class Plugin { this.key = key; } - normalize(visitor: Object): Object { - if (isFunction(visitor)) { - visitor = { ast: visitor }; + static validate(name, plugin) { + for (let key in plugin) { + if (key[0] === "_") continue; + if (VALID_PLUGIN_PROPERTIES.indexOf(key) >= 0) continue; + + var msgType = "pluginInvalidProperty"; + if (t.TYPES.indexOf(key) >= 0) msgType = "pluginInvalidPropertyVisitor"; + throw new Error(messages.get(msgType, name, key)); } - traverse.explode(visitor); + for (let key in plugin.metadata) { + if (VALID_METADATA_PROPERTES.indexOf(key) >= 0) continue; + throw new Error(messages.get("pluginInvalidProperty", name, `metadata.${key}`)); + } + } + + normalize(visitor: Object): Object { + traverse.explode(visitor); return visitor; } diff --git a/src/babel/traversal/path/index.js b/src/babel/traversal/path/index.js index fc4ae53277..28b53814da 100644 --- a/src/babel/traversal/path/index.js +++ b/src/babel/traversal/path/index.js @@ -123,17 +123,19 @@ assign(NodePath.prototype, require("./modification")); assign(NodePath.prototype, require("./family")); assign(NodePath.prototype, require("./comments")); -for (let type in virtualTypes) { - if (type[0] === "_") continue; - - NodePath.prototype[`is${type}`] = function (opts) { - return virtualTypes[type].checkPath(this, opts); - }; -} - for (let type of (t.TYPES: Array)) { let typeKey = `is${type}`; NodePath.prototype[typeKey] = function (opts) { return t[typeKey](this.node, opts); }; } + +for (let type in virtualTypes) { + if (type[0] === "_") continue; + + t.TYPES.push(type); + + NodePath.prototype[`is${type}`] = function (opts) { + return virtualTypes[type].checkPath(this, opts); + }; +} diff --git a/src/babel/traversal/visitors.js b/src/babel/traversal/visitors.js index b51df8b642..e934d8c3f0 100644 --- a/src/babel/traversal/visitors.js +++ b/src/babel/traversal/visitors.js @@ -106,7 +106,7 @@ export function verify(visitor) { for (var nodeType in visitor) { if (shouldIgnoreKey(nodeType)) continue; - if (t.TYPES.indexOf(nodeType) < 0 && !virtualTypes[nodeType]) { + if (t.TYPES.indexOf(nodeType) < 0) { throw new Error(messages.get("traverseVerifyNodeType", nodeType)); }