Use Object Spread Syntax (#7777)

* Use Object Spread Syntax

* Nits
This commit is contained in:
Justin Ridgewell 2018-04-23 21:44:27 -04:00 committed by GitHub
parent 037fee8ffb
commit 2afe9404fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 263 additions and 70 deletions

View File

@ -0,0 +1,3 @@
src
test
*.log

View File

@ -0,0 +1,57 @@
# @babel/plugin-codemod-object-assign-to-object-spread
Transforms old code that uses `Object.assign` with an Object Literal as
the first param to use Object Spread syntax.
## Examples
```js
const obj = Object.assign({
test1: 1,
}, other, {
test2: 2,
}, other2);
```
Is transformed to:
```js
const obj = {
test1: 1,
...other,
test2: 2,
...other2,
};
```
## Installation
```sh
npm install --save-dev @babel/plugin-codemod-object-assign-to-object-spread
```
## Usage
### Via `.babelrc` (Recommended)
**.babelrc**
```json
{
"plugins": ["@babel/plugin-codemod-object-assign-to-object-spread"]
}
```
### Via CLI
```sh
babel --plugins @babel/plugin-codemod-object-assign-to-object-spread script.js
```
### Via Node API
```javascript
require("@babel/core").transform("code", {
plugins: ["@babel/plugin-codemod-object-assign-to-object-spread"]
});
```

View File

@ -0,0 +1,22 @@
{
"name": "@babel/plugin-codemod-object-assign-to-object-spread",
"version": "7.0.0-beta.44",
"description": "Transforms Object.assign into object spread syntax",
"repository": "https://github.com/babel/babel/tree/master/codemods/babel-plugin-codemod-object-assign-to-object-spread",
"license": "MIT",
"main": "lib/index.js",
"keywords": [
"@babel/codemod",
"@babel/plugin"
],
"dependencies": {
"@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.44"
},
"peerDependencies": {
"@babel/core": "7.0.0-beta.44"
},
"devDependencies": {
"@babel/core": "7.0.0-beta.44",
"@babel/helper-plugin-test-runner": "7.0.0-beta.44"
}
}

View File

@ -0,0 +1,35 @@
import syntaxObjectRestSpread from "@babel/plugin-syntax-object-rest-spread";
export default function({ types: t }) {
return {
inherits: syntaxObjectRestSpread,
visitor: {
CallExpression(path) {
if (!path.get("callee").matchesPattern("Object.assign")) return;
const args = path.get("arguments");
if (args.length === 0) return;
const [objPath] = args;
if (!objPath.isObjectExpression()) return;
const obj = objPath.node;
const { properties } = obj;
for (let i = 1; i < args.length; i++) {
const arg = args[i];
const { node } = arg;
if (arg.isObjectExpression()) {
properties.push(...node.properties);
} else {
properties.push(t.spreadElement(node));
}
}
path.replaceWith(obj);
},
},
};
}

View File

@ -0,0 +1 @@
Object.assign({test: 1}, test2, {test: 2}, test3);

View File

@ -0,0 +1,3 @@
{
"plugins": ["../../../../lib"]
}

View File

@ -0,0 +1,6 @@
({
test: 1,
...test2,
test: 2,
...test3
});

View File

@ -0,0 +1,3 @@
{
"plugins": ["../../../../lib"]
}

View File

@ -0,0 +1,3 @@
import runner from "@babel/helper-plugin-test-runner";
runner(__dirname);

View File

@ -2,10 +2,11 @@
"name": "@babel/plugin-codemod-optional-catch-binding", "name": "@babel/plugin-codemod-optional-catch-binding",
"version": "7.0.0-beta.46", "version": "7.0.0-beta.46",
"description": "Remove unused catch bindings", "description": "Remove unused catch bindings",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-remove-unused-catch-binding", "repository": "https://github.com/babel/babel/tree/master/codemods/babel-plugin-codemod-remove-unused-catch-binding",
"license": "MIT", "license": "MIT",
"main": "lib/index.js", "main": "lib/index.js",
"keywords": [ "keywords": [
"@babel/codemod",
"@babel/plugin" "@babel/plugin"
], ],
"dependencies": { "dependencies": {

View File

@ -1,7 +1,6 @@
import syntaxOptionalCatchBinding from "@babel/plugin-syntax-optional-catch-binding"; import syntaxOptionalCatchBinding from "@babel/plugin-syntax-optional-catch-binding";
import { types as t } from "@babel/core";
export default function() { export default function({ types: t }) {
return { return {
inherits: syntaxOptionalCatchBinding, inherits: syntaxOptionalCatchBinding,

View File

@ -51,9 +51,10 @@ export function log(msg, force) {
} }
export function transform(filename, code, opts, callback) { export function transform(filename, code, opts, callback) {
opts = Object.assign({}, opts, { opts = {
...opts,
filename, filename,
}); };
babel.transform(code, opts, callback); babel.transform(code, opts, callback);
} }

View File

@ -38,12 +38,15 @@ function getMarkerLines(
source: Array<string>, source: Array<string>,
opts: Object, opts: Object,
): { start: number, end: number, markerLines: Object } { ): { start: number, end: number, markerLines: Object } {
const startLoc: Location = Object.assign( const startLoc: Location = {
{}, column: 0,
{ column: 0, line: -1 }, line: -1,
loc.start, ...loc.start,
); };
const endLoc: Location = Object.assign({}, startLoc, loc.end); const endLoc: Location = {
...startLoc,
...loc.end,
};
const { linesAbove = 2, linesBelow = 3 } = opts || {}; const { linesAbove = 2, linesBelow = 3 } = opts || {};
const startLine = startLoc.line; const startLine = startLoc.line;
const startColumn = startLoc.column; const startColumn = startLoc.column;

View File

@ -480,7 +480,9 @@ function emptyChain(): ConfigChain {
} }
function normalizeOptions(opts: ValidatedOptions): ValidatedOptions { function normalizeOptions(opts: ValidatedOptions): ValidatedOptions {
const options = Object.assign({}, opts); const options = {
...opts,
};
delete options.extends; delete options.extends;
delete options.env; delete options.env;
delete options.plugins; delete options.plugins;

View File

@ -174,7 +174,10 @@ const loadDescriptor = makeWeakCache(
let item = value; let item = value;
if (typeof value === "function") { if (typeof value === "function") {
const api = Object.assign({}, context, makeAPI(cache)); const api = {
...context,
...makeAPI(cache),
};
try { try {
item = value(api, options, dirname); item = value(api, options, dirname);
} catch (e) { } catch (e) {
@ -229,9 +232,13 @@ const instantiatePlugin = makeWeakCache(
): Plugin => { ): Plugin => {
const pluginObj = validatePluginObject(value); const pluginObj = validatePluginObject(value);
const plugin = Object.assign({}, pluginObj); const plugin = {
...pluginObj,
};
if (plugin.visitor) { if (plugin.visitor) {
plugin.visitor = traverse.explode(Object.assign({}, plugin.visitor)); plugin.visitor = traverse.explode({
...plugin.visitor,
});
} }
if (plugin.inherits) { if (plugin.inherits) {

View File

@ -12,7 +12,10 @@ export default function transformFileSync(
if (opts == null) { if (opts == null) {
options = { filename }; options = { filename };
} else if (opts && typeof opts === "object") { } else if (opts && typeof opts === "object") {
options = Object.assign({}, opts, { filename }); options = {
...opts,
filename,
};
} }
const config = loadConfig(options); const config = loadConfig(options);

View File

@ -19,7 +19,10 @@ export default ((function transformFile(filename, opts, callback) {
if (opts == null) { if (opts == null) {
options = { filename }; options = { filename };
} else if (opts && typeof opts === "object") { } else if (opts && typeof opts === "object") {
options = Object.assign({}, opts, { filename }); options = {
...opts,
filename,
};
} }
process.nextTick(() => { process.nextTick(() => {

View File

@ -22,36 +22,38 @@ export default function normalizeOptions(config: ResolvedConfig): {} {
const opts = config.options; const opts = config.options;
const options = Object.assign({}, opts, { const options = {
parserOpts: Object.assign( ...opts,
{
sourceType:
path.extname(filenameRelative) === ".mjs" ? "module" : sourceType,
sourceFileName: filename,
plugins: [],
},
opts.parserOpts,
),
generatorOpts: Object.assign(
{
// General generator flags.
filename,
auxiliaryCommentBefore: opts.auxiliaryCommentBefore,
auxiliaryCommentAfter: opts.auxiliaryCommentAfter,
retainLines: opts.retainLines,
comments,
shouldPrintComment: opts.shouldPrintComment,
compact,
minified: opts.minified,
// Source-map generation flags. parserOpts: {
sourceMaps, sourceType:
sourceRoot, path.extname(filenameRelative) === ".mjs" ? "module" : sourceType,
sourceFileName,
}, sourceFileName: filename,
opts.generatorOpts, plugins: [],
), ...opts.parserOpts,
}); },
generatorOpts: {
// General generator flags.
filename,
auxiliaryCommentBefore: opts.auxiliaryCommentBefore,
auxiliaryCommentAfter: opts.auxiliaryCommentAfter,
retainLines: opts.retainLines,
comments,
shouldPrintComment: opts.shouldPrintComment,
compact,
minified: opts.minified,
// Source-map generation flags.
sourceMaps,
sourceRoot,
sourceFileName,
...opts.generatorOpts,
},
};
for (const plugins of config.passes) { for (const plugins of config.passes) {
for (const plugin of plugins) { for (const plugin of plugins) {

View File

@ -82,5 +82,8 @@ const handle = {
// Optionally, a memoize method may be defined on the state, which will be // Optionally, a memoize method may be defined on the state, which will be
// called when the member is a self-referential update. // called when the member is a self-referential update.
export default function memberExpressionToFunctions(path, visitor, state) { export default function memberExpressionToFunctions(path, visitor, state) {
path.traverse(visitor, Object.assign({}, state, handle)); path.traverse(visitor, {
...state,
...handle,
});
} }

View File

@ -170,7 +170,9 @@ export default class ImportInjector {
optsList.push(importedSource); optsList.push(importedSource);
} }
const newOpts = Object.assign({}, this._defaultOpts); const newOpts = {
...this._defaultOpts,
};
for (const opts of optsList) { for (const opts of optsList) {
if (!opts) continue; if (!opts) continue;
Object.keys(newOpts).forEach(key => { Object.keys(newOpts).forEach(key => {

View File

@ -34,7 +34,10 @@ function copyApiObject(api) {
} }
} }
return Object.assign({}, proto, api); return {
...proto,
...api,
};
} }
function has(obj, key) { function has(obj, key) {

View File

@ -95,7 +95,9 @@ export const isPluginRequired = (
}; };
const getBuiltInTargets = targets => { const getBuiltInTargets = targets => {
const builtInTargets = Object.assign({}, targets); const builtInTargets = {
...targets,
};
if (builtInTargets.uglify != null) { if (builtInTargets.uglify != null) {
delete builtInTargets.uglify; delete builtInTargets.uglify;
} }

View File

@ -177,7 +177,9 @@ export default function normalizeOptions(opts: Options) {
false, false,
), ),
spec: validateBoolOption("loose", opts.spec, false), spec: validateBoolOption("loose", opts.spec, false),
targets: Object.assign({}, opts.targets), targets: {
...opts.targets,
},
useBuiltIns: validateUseBuiltInsOption(opts.useBuiltIns), useBuiltIns: validateUseBuiltInsOption(opts.useBuiltIns),
}; };
} }

View File

@ -39,11 +39,12 @@ function mtime(filename) {
function compile(code, filename) { function compile(code, filename) {
// merge in base options and resolve all the plugins and presets relative to this file // merge in base options and resolve all the plugins and presets relative to this file
const opts = new OptionManager().init( const opts = new OptionManager().init(
Object.assign( // sourceRoot can be overwritten
{ sourceRoot: path.dirname(filename) }, // sourceRoot can be overwritten {
deepClone(transformOpts), sourceRoot: path.dirname(filename),
{ filename }, ...deepClone(transformOpts),
), filename,
},
); );
// Bail out ASAP if the file has been ignored. // Bail out ASAP if the file has been ignored.
@ -109,7 +110,9 @@ register({
export default function register(opts?: Object = {}) { export default function register(opts?: Object = {}) {
// Clone to avoid mutating the arguments object with the 'delete's below. // Clone to avoid mutating the arguments object with the 'delete's below.
opts = Object.assign({}, opts); opts = {
...opts,
};
if (opts.extensions) hookExtensions(opts.extensions); if (opts.extensions) hookExtensions(opts.extensions);
if (opts.cache === false && cache) { if (opts.cache === false && cache) {
@ -123,7 +126,9 @@ export default function register(opts?: Object = {}) {
delete opts.extensions; delete opts.extensions;
delete opts.cache; delete opts.cache;
transformOpts = Object.assign({}, opts); transformOpts = {
...opts,
};
let { cwd = "." } = transformOpts; let { cwd = "." } = transformOpts;

View File

@ -44,7 +44,10 @@ export function merge(a: TemplateOpts, b: TemplateOpts): TemplateOpts {
} = b; } = b;
return { return {
parser: Object.assign({}, a.parser, b.parser), parser: {
...a.parser,
...b.parser,
},
placeholderWhitelist, placeholderWhitelist,
placeholderPattern, placeholderPattern,
preserveComments, preserveComments,

View File

@ -134,14 +134,12 @@ type MetadataState = {
}; };
function parseWithCodeFrame(code: string, parserOpts: {}): BabelNodeFile { function parseWithCodeFrame(code: string, parserOpts: {}): BabelNodeFile {
parserOpts = Object.assign( parserOpts = {
{ allowReturnOutsideFunction: true,
allowReturnOutsideFunction: true, allowSuperOutsideMethod: true,
allowSuperOutsideMethod: true, sourceType: "module",
sourceType: "module", ...parserOpts,
}, };
parserOpts,
);
try { try {
return parse(code, parserOpts); return parse(code, parserOpts);

View File

@ -62,7 +62,9 @@ export default function cloneNode<T: Object>(node: T, deep: boolean = true): T {
newNode.trailingComments = node.trailingComments; newNode.trailingComments = node.trailingComments;
} }
if (has(node, "extra")) { if (has(node, "extra")) {
newNode.extra = Object.assign({}, node.extra); newNode.extra = {
...node.extra,
};
} }
return newNode; return newNode;

View File

@ -19,7 +19,9 @@ plugins.typescript = typescriptPlugin;
export function parse(input: string, options?: Options): File { export function parse(input: string, options?: Options): File {
if (options && options.sourceType === "unambiguous") { if (options && options.sourceType === "unambiguous") {
options = Object.assign({}, options); options = {
...options,
};
try { try {
options.sourceType = "module"; options.sourceType = "module";
const parser = getParser(options, input); const parser = getParser(options, input);

View File

@ -20,7 +20,7 @@ if [ -n "$TEST_GREP" ]; then
fi fi
if [ -n "$TEST_ONLY" ]; then if [ -n "$TEST_ONLY" ]; then
jestArgs+=("packages/.*$TEST_ONLY.*/test") jestArgs+=("(packages|codemods)/.*$TEST_ONLY.*/test")
fi fi
$node node_modules/.bin/jest "${jestArgs[@]}" $node node_modules/.bin/jest "${jestArgs[@]}"