Add an option to Babylon to have decorators before export (#7869)
* Add support for plugin options in Babylon
They work similarly to how they work in Babel. e.g.
babylon.parse({
options: [
"plugin1",
["plugin2", { option: true }]
]
});
The inernal api to get an option is
this.getPluginOption("pluginName", "option")
If the plugin isn't defined, it returns undefined.
* Add Babylon option decorators.secoratorsBeforeExport
* Nit
This commit is contained in:
parent
a955efa3e3
commit
e45d5c3b65
@ -67,39 +67,39 @@ function getParserClass(
|
||||
pluginsFromOptions: $ReadOnlyArray<string>,
|
||||
): Class<Parser> {
|
||||
if (
|
||||
pluginsFromOptions.indexOf("decorators-legacy") >= 0 &&
|
||||
pluginsFromOptions.indexOf("decorators") >= 0
|
||||
hasPlugin(pluginsFromOptions, "decorators") &&
|
||||
hasPlugin(pluginsFromOptions, "decorators-legacy")
|
||||
) {
|
||||
throw new Error("Cannot use decorators and decorators2 plugin together");
|
||||
throw new Error(
|
||||
"Cannot use the decorators and decorators-legacy plugin together",
|
||||
);
|
||||
}
|
||||
|
||||
// Filter out just the plugins that have an actual mixin associated with them.
|
||||
let pluginList = pluginsFromOptions.filter(
|
||||
p => p === "estree" || p === "flow" || p === "jsx" || p === "typescript",
|
||||
);
|
||||
let pluginList = pluginsFromOptions.filter(plugin => {
|
||||
const p = getPluginName(plugin);
|
||||
return p === "estree" || p === "flow" || p === "jsx" || p === "typescript";
|
||||
});
|
||||
|
||||
if (pluginList.indexOf("flow") >= 0) {
|
||||
if (hasPlugin(pluginList, "flow")) {
|
||||
// ensure flow plugin loads last
|
||||
pluginList = pluginList.filter(plugin => plugin !== "flow");
|
||||
pluginList = pluginList.filter(p => getPluginName(p) !== "flow");
|
||||
pluginList.push("flow");
|
||||
}
|
||||
|
||||
if (
|
||||
pluginList.indexOf("flow") >= 0 &&
|
||||
pluginList.indexOf("typescript") >= 0
|
||||
) {
|
||||
if (hasPlugin(pluginList, "flow") && hasPlugin(pluginList, "typescript")) {
|
||||
throw new Error("Cannot combine flow and typescript plugins.");
|
||||
}
|
||||
|
||||
if (pluginList.indexOf("typescript") >= 0) {
|
||||
if (hasPlugin(pluginList, "typescript")) {
|
||||
// ensure typescript plugin loads last
|
||||
pluginList = pluginList.filter(plugin => plugin !== "typescript");
|
||||
pluginList = pluginList.filter(p => getPluginName(p) !== "typescript");
|
||||
pluginList.push("typescript");
|
||||
}
|
||||
|
||||
if (pluginList.indexOf("estree") >= 0) {
|
||||
if (hasPlugin(pluginList, "estree")) {
|
||||
// ensure estree plugin loads first
|
||||
pluginList = pluginList.filter(plugin => plugin !== "estree");
|
||||
pluginList = pluginList.filter(p => getPluginName(p) !== "estree");
|
||||
pluginList.unshift("estree");
|
||||
}
|
||||
|
||||
@ -114,3 +114,11 @@ function getParserClass(
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
function getPluginName(plugin) {
|
||||
return Array.isArray(plugin) ? plugin[0] : plugin;
|
||||
}
|
||||
|
||||
function hasPlugin(pluginsList, name) {
|
||||
return pluginsList.some(plugin => getPluginName(plugin) === name);
|
||||
}
|
||||
|
||||
@ -26,6 +26,10 @@ export default class BaseParser {
|
||||
}
|
||||
|
||||
hasPlugin(name: string): boolean {
|
||||
return !!this.plugins[name];
|
||||
return Object.hasOwnProperty.call(this.plugins, name);
|
||||
}
|
||||
|
||||
getPluginOption(plugin: string, name: string) {
|
||||
if (this.hasPlugin(plugin)) return this.plugins[plugin][name];
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,9 +41,10 @@ export default class Parser extends StatementParser {
|
||||
function pluginsMap(
|
||||
pluginList: $ReadOnlyArray<string>,
|
||||
): { [key: string]: boolean } {
|
||||
const pluginMap = {};
|
||||
for (const name of pluginList) {
|
||||
pluginMap[name] = true;
|
||||
const pluginMap = Object.create(null);
|
||||
for (const plugin of pluginList) {
|
||||
const [name, options = {}] = Array.isArray(plugin) ? plugin : [plugin];
|
||||
pluginMap[name] = options;
|
||||
}
|
||||
return pluginMap;
|
||||
}
|
||||
|
||||
@ -230,7 +230,10 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
parseDecorators(allowExport?: boolean): void {
|
||||
if (this.hasPlugin("decorators")) {
|
||||
if (
|
||||
this.hasPlugin("decorators") &&
|
||||
!this.getPluginOption("decorators", "decoratorsBeforeExport")
|
||||
) {
|
||||
allowExport = false;
|
||||
}
|
||||
|
||||
@ -1422,6 +1425,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
} else if (this.match(tt._class)) {
|
||||
return this.parseClass(expr, true, true);
|
||||
} else if (this.match(tt.at)) {
|
||||
if (
|
||||
this.hasPlugin("decorators") &&
|
||||
this.getPluginOption("decorators", "decoratorsBeforeExport")
|
||||
) {
|
||||
this.unexpected();
|
||||
}
|
||||
this.parseDecorators(false);
|
||||
return this.parseClass(expr, true, true);
|
||||
} else if (
|
||||
@ -1518,14 +1527,24 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
shouldParseExportDeclaration(): boolean {
|
||||
if (this.match(tt.at)) {
|
||||
this.expectOnePlugin(["decorators", "decorators-legacy"]);
|
||||
if (this.hasPlugin("decorators")) {
|
||||
if (this.getPluginOption("decorators", "decoratorsBeforeExport")) {
|
||||
this.unexpected();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
this.state.type.keyword === "var" ||
|
||||
this.state.type.keyword === "const" ||
|
||||
this.state.type.keyword === "let" ||
|
||||
this.state.type.keyword === "function" ||
|
||||
this.state.type.keyword === "class" ||
|
||||
this.isContextual("async") ||
|
||||
(this.match(tt.at) && this.expectPlugin("decorators"))
|
||||
this.isContextual("async")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export default (@decorator class Foo {})
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": true }]
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 40,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 40
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 40,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 40
|
||||
}
|
||||
},
|
||||
"sourceType": "module",
|
||||
"body": [
|
||||
{
|
||||
"type": "ExportDefaultDeclaration",
|
||||
"start": 0,
|
||||
"end": 40,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 40
|
||||
}
|
||||
},
|
||||
"declaration": {
|
||||
"type": "ClassExpression",
|
||||
"start": 16,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 16
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 39
|
||||
}
|
||||
},
|
||||
"decorators": [
|
||||
{
|
||||
"type": "Decorator",
|
||||
"start": 16,
|
||||
"end": 26,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 16
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
}
|
||||
},
|
||||
"callee": {
|
||||
"type": "Identifier",
|
||||
"start": 17,
|
||||
"end": 26,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"identifierName": "decorator"
|
||||
},
|
||||
"name": "decorator"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 33,
|
||||
"end": 36,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 33
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 36
|
||||
},
|
||||
"identifierName": "Foo"
|
||||
},
|
||||
"name": "Foo"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start": 37,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 37
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 39
|
||||
}
|
||||
},
|
||||
"body": []
|
||||
},
|
||||
"extra": {
|
||||
"parenthesized": true,
|
||||
"parenStart": 15
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export default @decorator class Foo {}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": true }]
|
||||
],
|
||||
"throws": "Unexpected token (1:15)"
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
@decorator
|
||||
export default class Foo {}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": true }]
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 38,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 38,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"sourceType": "module",
|
||||
"body": [
|
||||
{
|
||||
"type": "ExportDefaultDeclaration",
|
||||
"start": 11,
|
||||
"end": 38,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"declaration": {
|
||||
"type": "ClassDeclaration",
|
||||
"start": 0,
|
||||
"end": 38,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"decorators": [
|
||||
{
|
||||
"type": "Decorator",
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"callee": {
|
||||
"type": "Identifier",
|
||||
"start": 1,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
},
|
||||
"identifierName": "decorator"
|
||||
},
|
||||
"name": "decorator"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 32,
|
||||
"end": 35,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 24
|
||||
},
|
||||
"identifierName": "Foo"
|
||||
},
|
||||
"name": "Foo"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start": 36,
|
||||
"end": 38,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 25
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 27
|
||||
}
|
||||
},
|
||||
"body": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
@decorator
|
||||
export class Foo {}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": true }]
|
||||
]
|
||||
}
|
||||
134
packages/babylon/test/fixtures/experimental/decorators-2/decoratorsBeforeExport-export/output.json
vendored
Normal file
134
packages/babylon/test/fixtures/experimental/decorators-2/decoratorsBeforeExport-export/output.json
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 30,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 30,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"sourceType": "module",
|
||||
"body": [
|
||||
{
|
||||
"type": "ExportNamedDeclaration",
|
||||
"start": 11,
|
||||
"end": 30,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"specifiers": [],
|
||||
"source": null,
|
||||
"declaration": {
|
||||
"type": "ClassDeclaration",
|
||||
"start": 0,
|
||||
"end": 30,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"decorators": [
|
||||
{
|
||||
"type": "Decorator",
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"callee": {
|
||||
"type": "Identifier",
|
||||
"start": 1,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
},
|
||||
"identifierName": "decorator"
|
||||
},
|
||||
"name": "decorator"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 24,
|
||||
"end": 27,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 13
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 16
|
||||
},
|
||||
"identifierName": "Foo"
|
||||
},
|
||||
"name": "Foo"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start": 28,
|
||||
"end": 30,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 19
|
||||
}
|
||||
},
|
||||
"body": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"throws": "This experimental syntax requires enabling the parser plugin: 'decorators' (1:7)",
|
||||
"throws": "This experimental syntax requires enabling one of the following parser plugin(s): 'decorators, decorators-legacy' (1:7)",
|
||||
"plugins": null
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"plugins": ["decorators-legacy", "decorators"],
|
||||
"throws": "Cannot use decorators and decorators2 plugin together"
|
||||
"throws": "Cannot use the decorators and decorators-legacy plugin together"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user