Skip to content

Commit

Permalink
refactor: move to loadDescriptor catch clause
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed Jan 8, 2020
1 parent 67092ae commit 0c6af2b
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 41 deletions.
2 changes: 0 additions & 2 deletions packages/babel-core/src/config/config-descriptors.js
Expand Up @@ -15,7 +15,6 @@ import type {
PluginList,
PluginItem,
} from "./validation/options";
import { assertNoUnwrappedItemOptionPairs } from "./validation/options";

// Represents a config object and functions to lazily load the descriptors
// for the plugins and presets so we don't load the plugins/presets unless
Expand Down Expand Up @@ -230,7 +229,6 @@ function createDescriptors(
alias: string,
ownPass?: boolean,
): Array<UnloadedDescriptor> {
assertNoUnwrappedItemOptionPairs(items, type);
const descriptors = items.map((item, index) =>
createDescriptor(item, dirname, {
type,
Expand Down
67 changes: 51 additions & 16 deletions packages/babel-core/src/config/full.js
Expand Up @@ -13,7 +13,11 @@ import {
import type { UnloadedDescriptor } from "./config-descriptors";
import traverse from "@babel/traverse";
import { makeWeakCache, type CacheConfigurator } from "./caching";
import { validate, type CallerMetadata } from "./validation/options";
import {
validate,
type CallerMetadata,
assertNoUnwrappedItemOptionPairs,
} from "./validation/options";
import { validatePluginObject } from "./validation/plugins";
import makeAPI from "./helpers/config-api";

Expand Down Expand Up @@ -70,21 +74,52 @@ export default function loadFullConfig(
},
pass: Array<Plugin>,
) {
const plugins = config.plugins.reduce((acc, descriptor) => {
if (descriptor.options !== false) {
acc.push(loadPluginDescriptor(descriptor, context));
}
return acc;
}, []);
const presets = config.presets.reduce((acc, descriptor) => {
if (descriptor.options !== false) {
acc.push({
preset: loadPresetDescriptor(descriptor, context),
pass: descriptor.ownPass ? [] : pass,
});
}
return acc;
}, []);
const plugins = config.plugins.reduce(
(acc: Plugin[], descriptor: UnloadedDescriptor, i) => {
if (descriptor.options !== false) {
try {
acc.push(loadPluginDescriptor(descriptor, context));
} catch (e) {
// print special message for `plugins: ["@babel/foo", { foo: "option" }]`
if (i > 0) {
assertNoUnwrappedItemOptionPairs(
config.plugins[i - 1],
descriptor,
"plugin",
i,
);
}
throw e;
}
}
return acc;
},
[],
);
const presets = config.presets.reduce(
(acc, descriptor: UnloadedDescriptor, i) => {
if (descriptor.options !== false) {
try {
acc.push({
preset: loadPresetDescriptor(descriptor, context),
pass: descriptor.ownPass ? [] : pass,
});
} catch (e) {
if (i > 0) {
assertNoUnwrappedItemOptionPairs(
config.presets[i - 1],
descriptor,
"preset",
i,
);
}
throw e;
}
}
return acc;
},
[],
);

// resolve presets
if (presets.length > 0) {
Expand Down
33 changes: 16 additions & 17 deletions packages/babel-core/src/config/validation/options.js
Expand Up @@ -27,7 +27,7 @@ import {
type Validator,
type OptionPath,
} from "./option-assertions";
import { validatePluginObject } from "./plugins";
import type { UnloadedDescriptor } from "../config-descriptors";

const ROOT_VALIDATORS: ValidatorSet = {
cwd: (assertString: Validator<$PropertyType<ValidatedOptions, "cwd">>),
Expand Down Expand Up @@ -442,25 +442,24 @@ function assertOverridesList(loc: OptionPath, value: mixed): OverridesList {
}

export function assertNoUnwrappedItemOptionPairs(
items: PluginList,
lastItem: UnloadedDescriptor,
thisItem: UnloadedDescriptor,
type: "plugin" | "preset",
index: number,
): void {
if (
items.length === 2 &&
typeof items[0] === "string" &&
typeof items[1] === "object" &&
!Array.isArray(items[1])
lastItem.file &&
lastItem.options === undefined &&
typeof thisItem.value === "object"
) {
try {
type === "preset"
? validate(type, items[1])
: validatePluginObject(items[1]);
} catch (e) {
throw new Error(
`.${type}[1] is not a valid ${type}. Maybe you meant to use\n` +
`"${type}": [\n ["${items[0]}", ${JSON.stringify(items[1])}]\n]\n` +
`To be a valid ${type}, its name and options should be wrapped in a pair of brackets`,
);
}
throw new Error(
`.${type}[${index}] is not a valid ${type}. Maybe you meant to use\n` +
`"${type}": [\n ["${lastItem.file.request}", ${JSON.stringify(
thisItem.value,
undefined,
2,
)}]\n]\n` +
`To be a valid ${type}, its name and options should be wrapped in a pair of brackets`,
);
}
}
12 changes: 8 additions & 4 deletions packages/babel-core/test/__snapshots__/option-manager.js.snap
@@ -1,17 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`option-manager config plugin/preset flattening and overriding should throw when an option is provided as a plugin 1`] = `
".plugin[1] is not a valid plugin. Maybe you meant to use
"[BABEL] unknown: .plugin[1] is not a valid plugin. Maybe you meant to use
\\"plugin\\": [
[\\"@babel/transform-react-jsx\\", {\\"useSpread\\":true}]
[\\"./fixtures/option-manager/babel-plugin-foo\\", {
\\"useSpread\\": true
}]
]
To be a valid plugin, its name and options should be wrapped in a pair of brackets"
`;

exports[`option-manager config plugin/preset flattening and overriding should throw when an option is provided as a preset 1`] = `
".preset[1] is not a valid preset. Maybe you meant to use
"[BABEL] unknown: .preset[1] is not a valid preset. Maybe you meant to use
\\"preset\\": [
[\\"@babel/env\\", {\\"useBuiltIns\\":\\"entry\\"}]
[\\"./fixtures/option-manager/babel-preset-bar\\", {
\\"useBuiltIns\\": \\"entry\\"
}]
]
To be a valid preset, its name and options should be wrapped in a pair of brackets"
`;
@@ -0,0 +1 @@
module.exports = () => ({});
@@ -0,0 +1 @@
module.exports = () => ({});
10 changes: 8 additions & 2 deletions packages/babel-core/test/option-manager.js
Expand Up @@ -30,15 +30,21 @@ describe("option-manager", () => {
it("should throw when an option is provided as a preset", () => {
expect(() => {
loadOptions({
presets: ["@babel/env", { useBuiltIns: "entry" }],
presets: [
"./fixtures/option-manager/babel-preset-bar",
{ useBuiltIns: "entry" },
],
});
}).toThrowErrorMatchingSnapshot();
});

it("should throw when an option is provided as a plugin", () => {
expect(() => {
loadOptions({
plugins: ["@babel/transform-react-jsx", { useSpread: true }],
plugins: [
"./fixtures/option-manager/babel-plugin-foo",
{ useSpread: true },
],
});
}).toThrowErrorMatchingSnapshot();
});
Expand Down

0 comments on commit 0c6af2b

Please sign in to comment.