Skip to content

Commit

Permalink
Add transform to fix up misuse of arguments in arrow functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpojer committed May 23, 2015
1 parent 7502159 commit a20a5e1
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 0 deletions.
4 changes: 4 additions & 0 deletions test/__tests__/transform-tests.js
Expand Up @@ -56,4 +56,8 @@ describe('Transform Tests', () => {
test('insert-super', 'insert-super-test');
});

it('transforms the "arrow function arguments" tests correctly', () => {
test('arrow-function-arguments', 'arrow-function-arguments-test');
});

});
28 changes: 28 additions & 0 deletions test/arrow-function-arguments-test.js
@@ -0,0 +1,28 @@
'use strict';

var fn1 = () => console.log(arguments);

var fn2 = (a, b, c) => {
console.log(arguments);

return arguments;
};

var fn3 = (a, b, args) => {
console.log(args);

return arguments;
};

var fn4 = function(a, b, c) {
console.log(arguments);
var fn5 = () => arguments;
var fn6 = () => (function() { return arguments; });
class A {
constructor() {
console.log(arguments);
}
}
};

var fn5 = (a, ...b) => arguments;
28 changes: 28 additions & 0 deletions test/arrow-function-arguments-test.output.js
@@ -0,0 +1,28 @@
'use strict';

var fn1 = (...args) => console.log(args);

var fn2 = (a, b, c, ...args) => {
console.log([a, b, c, ...args]);

return [a, b, c, ...args];
};

var fn3 = (a, b, args) => {
console.log(args);

return arguments;
};

var fn4 = function(a, b, c) {
console.log(arguments);
var fn5 = (...args) => args;
var fn6 = () => (function() { return arguments; });
class A {
constructor() {
console.log(arguments);
}
}
};

var fn5 = (a, ...b) => [a, ...b];
84 changes: 84 additions & 0 deletions transforms/arrow-function-arguments.js
@@ -0,0 +1,84 @@
// -----------------------------------------------------------------------------
// Update arrow function arguments to args
function arrowFunctionArguments(file, api, options) {
const j = api.jscodeshift;

const printOptions = options.printOptions || {quote: 'single'};
const root = j(file.source);

const ARGUMENTS = 'arguments';
const ARGS = 'args';

const createArrowFunctionExpression = (fn, args) => {
const arrow = j.arrowFunctionExpression(
(fn.params || []).concat(
// https://github.com/benjamn/recast/pull/179
// j.spreadElementPattern(args)
),
fn.body,
fn.generator
);
arrow.rest = args;
return arrow;
};

const filterArrowFunctions = path => {
while (path.parent) {
switch (path.value.type) {
case 'ArrowFunctionExpression':
if (j(path).find(j.Identifier, {name: ARGS}).size()) {
console.error(
file.path + ': arrow function uses "' + ARGS + '" already. ' +
'Please rename this identifier first.'
);
return false;
}
return true;
case 'FunctionExpression':
case 'MethodDeclaration':
case 'Function':
case 'FunctionDeclaration':
return false;
default:
break;
}
path = path.parent;
}
return false;
};

const updateArgumentsCalls = path => {
var afPath = path;
while (afPath.parent) {
if (afPath.value.type == 'ArrowFunctionExpression') {
break;
}
afPath = afPath.parent;
}

const {value: fn} = afPath;
const {params} = fn;
const args = fn.rest || j.identifier(ARGS);
j(afPath).replaceWith(createArrowFunctionExpression(fn, args));

if (params.length) {
j(path).replaceWith(
j.arrayExpression(params.concat(
j.spreadElement(args)
))
);
} else {
j(path).replaceWith(args);
}
};

const didTransform = root
.find(j.Identifier, {name: ARGUMENTS})
.filter(filterArrowFunctions)
.forEach(updateArgumentsCalls)
.size() > 0;

return didTransform ? root.toSource(printOptions) + '\n' : null;
}

module.exports = arrowFunctionArguments;

0 comments on commit a20a5e1

Please sign in to comment.