Skip to content

Commit

Permalink
feature(putout) add support of jscodeshift codemods
Browse files Browse the repository at this point in the history
  • Loading branch information
coderaiser committed Aug 7, 2019
1 parent b16c31a commit 1b9ef88
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 3 deletions.
4 changes: 4 additions & 0 deletions packages/putout/.putout.json
Expand Up @@ -4,5 +4,9 @@
},
"babelPlugins": [
"transform-inline-consecutive-adds"
],
"jscodeshiftPlugins": [
["async-await-codemod/async-await", "async-await should be used instead of Promises"],
["async-await-codemod/await-promise-chain", "async-await should be used instead of Promise chain"]
]
}
7 changes: 7 additions & 0 deletions packages/putout/lib/putout.js
Expand Up @@ -13,6 +13,7 @@ const getPlugins = require('./get-plugins');
const customParser = require('./custom-parser');
const runPlugins = require('./run-plugins');
const runBabelPlugins = require('./run-babel-plugins');
const runJSCodeshiftPlugins = require('./run-jscodeshift-plugins');
const print = require('./print');

const isUndefined = (a) => typeof a === 'undefined';
Expand Down Expand Up @@ -101,6 +102,7 @@ function transform(ast, source, opts) {
plugins: pluginNames,
cache,
babelPlugins = [],
jscodeshiftPlugins = [],
rules,
fix,
fixCount,
Expand Down Expand Up @@ -128,6 +130,11 @@ function transform(ast, source, opts) {
plugins,
parser,
}),
...runJSCodeshiftPlugins({
ast,
fix,
jscodeshiftPlugins,
}),
];

return places;
Expand Down
8 changes: 5 additions & 3 deletions packages/putout/lib/run-babel-plugins/index.js
Expand Up @@ -3,7 +3,7 @@
const {transformFromAstSync} = require('@babel/core');

const print = require('../print');
const getPositions = require('./get-positions');
const getPositions = require('../get-positions-by-diff');

const getMessage = (a) => a
.replace(/@babel\/plugin-|babel-plugin-/, '')
Expand All @@ -12,10 +12,10 @@ const getMessage = (a) => a
module.exports = ({fix, ast, babelPlugins}) => {
const places = [];

if (!babelPlugins)
if (!babelPlugins.length)
return places;

const oldCode = print(ast);
let oldCode = print(ast);

for (const plugin of babelPlugins) {
transform(ast, '', plugin);
Expand All @@ -28,6 +28,8 @@ module.exports = ({fix, ast, babelPlugins}) => {
const rule = `babel/${plugin}`;
const message = getMessage(plugin);

oldCode = newCode;

for (const position of positions)
places.push({
rule,
Expand Down
74 changes: 74 additions & 0 deletions packages/putout/lib/run-jscodeshift-plugins/index.js
@@ -0,0 +1,74 @@
'use strict';

const once = require('once');
const print = require('../print');
const getPositions = require('../get-positions-by-diff');

const {isArray} = Array;
const {assign} = Object;

const getMessage = (a) => a.replace('/', ': ');
const parsePlugin = (a) => {
if (!isArray(a))
return [
a,
getMessage(a),
];

const [name, message] = a;

return [
name,
getMessage(message),
];
};

const getJScodeshift = once(() => require('jscodeshift'));

const wrapCodeShift = () => {
const j = getJScodeshift();

const fixedJscodeshift = (a) => {
return assign(j(a), {
toSource() {
return print(this.__paths[0].value);
},
});
};

return assign(fixedJscodeshift, j);
};

module.exports = ({fix, ast, jscodeshiftPlugins}) => {
const places = [];

if (!jscodeshiftPlugins)
return places;

const jscodeshift = wrapCodeShift(ast);

let oldCode = print(ast);
for (const plugin of jscodeshiftPlugins) {
const [pluginName, message] = parsePlugin(plugin);
const fn = require(pluginName);

const newCode = fn({source: ast}, {jscodeshift});

if (!fix && newCode !== oldCode) {
const positions = getPositions(oldCode, newCode);
const rule = `jscodeshift/${pluginName}`;

oldCode = newCode;

for (const position of positions)
places.push({
rule,
message,
position,
});
}
}

return places;
};

2 changes: 2 additions & 0 deletions packages/putout/package.json
Expand Up @@ -93,6 +93,7 @@
"glob": "^7.1.3",
"ignore": "^5.0.4",
"is-relative": "^1.0.0",
"jscodeshift": "^0.6.4",
"once": "^1.4.0",
"recast": "https://github.com/coderaiser/recast/archive/v0.18.1-fix.tar.gz",
"try-catch": "^2.0.0",
Expand All @@ -109,6 +110,7 @@
"acorn": "^6.1.1",
"acorn-jsx": "^5.0.1",
"acorn-stage3": "^2.0.0",
"async-await-codemod": "https://github.com/sgilroy/async-await-codemod.git",
"babel-loader": "^8.0.6",
"babel-plugin-macros": "^2.6.1",
"codegen.macro": "^3.0.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/putout/test/fixture/jscodeshift-fix.js
@@ -0,0 +1,4 @@
async function promise() {
const helloResult = await hello();
return world(helloResult);
}
3 changes: 3 additions & 0 deletions packages/putout/test/fixture/jscodeshift.js
@@ -0,0 +1,3 @@
function promise() {
return hello().then(world);
}
35 changes: 35 additions & 0 deletions packages/putout/test/putout.js
Expand Up @@ -35,6 +35,8 @@ const fixture = readFixtures([
'not-jsx',
'babel-plugins',
'babel-plugins-fix',
'jscodeshift',
'jscodeshift-fix',
]);

test('putout: no vars', (t) => {
Expand Down Expand Up @@ -614,3 +616,36 @@ test('putout: plugin: find: push', (t) => {
t.deepEqual(places, expected, 'should equal');
t.end();
});

test('putout: jscodeshift', (t) => {
const {code} = putout(fixture.jscodeshift, {
jscodeshiftPlugins: [
'async-await-codemod/async-await',
],
});

t.deepEqual(code, fixture.jscodeshiftFix);
t.end();
});

test('putout: jscodeshift: messsage', (t) => {
const {places} = putout(fixture.jscodeshift, {
fix: false,
jscodeshiftPlugins: [
['async-await-codemod/async-await', 'async-await should be used instead of Promises'],
],
});

const expected = [{
message: 'async-await should be used instead of Promises',
position: {
column: 0,
line: 2,
},
rule: 'jscodeshift/async-await-codemod/async-await',
}];

t.deepEqual(places, expected);
t.end();
});

0 comments on commit 1b9ef88

Please sign in to comment.