Last active
May 16, 2019 23:46
-
-
Save cletusw/86a5df2f0e9b61e419db14f249282fc6 to your computer and use it in GitHub Desktop.
Converts the given angular injected parameter into an explicit require statement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Converts the given angular injected parameter into an explicit require statement | |
* | |
* Run this with jscodeshift | |
* @example | |
* jscodeshift . --specifier='Auth' --source='application/Auth' | |
* | |
* Live demo: https://astexplorer.net/#/gist/5492d2b9850a451d8e8d532bc64f21ce/latest | |
* | |
* Converts: | |
* app.controller('myController', function ($scope, Auth, $q) { | |
* }); | |
* | |
* function test($scope, Auth, $q) { | |
* 'ngInject'; | |
* } | |
* | |
* app.component('myComponent', { | |
* controller: function ($scope, Auth, $q) { | |
* } | |
* }); | |
* | |
* app.directive('myDirective', function (Auth) { | |
* return { | |
* controller: function ($scope, Auth, $q) { | |
* } | |
* }; | |
* }); | |
* | |
* to: | |
* import Auth from 'application/Auth'; | |
* app.controller('myController', function ($scope, $q) { | |
* }); | |
* | |
* function test($scope, $q) { | |
* 'ngInject'; | |
* } | |
* | |
* app.component('myComponent', { | |
* controller: function ($scope, $q) { | |
* } | |
* }); | |
* | |
* app.directive('myDirective', function () { | |
* return { | |
* controller: function ($scope, $q) { | |
* } | |
* }; | |
* }); | |
*/ | |
const angularMethods = [ | |
'config', | |
'provider', | |
'factory', | |
'service', | |
'controller', | |
'filter', | |
'directive' | |
]; | |
function isNgInject(functionExpression) { | |
if (!functionExpression.body.body.length) { | |
return false; | |
} | |
let firstBodyNode = functionExpression.body.body[0]; | |
return ( | |
firstBodyNode.type === 'ExpressionStatement' && | |
firstBodyNode.expression.type === 'Literal' && | |
firstBodyNode.expression.value === 'ngInject' | |
); | |
} | |
function isControllerOnObject(path) { | |
return ( | |
path.name === 'value' && | |
path.parentPath.parentPath.name === 'properties' && | |
path.node.type === 'FunctionExpression' && | |
path.parentPath.node.type === 'Property' && | |
path.parentPath.parentPath.node.type === 'ObjectExpression' | |
); | |
} | |
function isParameterOfAngularMethod(path) { | |
return ( | |
path.node.type === 'FunctionExpression' && | |
path.parentPath.name === 'arguments' && | |
path.parentPath.parentPath.node.type === 'CallExpression' && | |
path.parentPath.parentPath.node.callee.type === 'MemberExpression' && | |
path.parentPath.parentPath.node.callee.property.type === 'Identifier' && | |
angularMethods.indexOf(path.parentPath.parentPath.node.callee.property.name) > -1 | |
); | |
} | |
function isUseStrict(node) { | |
return ( | |
node && | |
node.type === 'ExpressionStatement' && | |
node.expression.type === 'Literal' && | |
node.expression.value === 'use strict' | |
); | |
} | |
module.exports = function transformer(file, api, options) { | |
const j = api.jscodeshift; | |
const { | |
specifier = 'Auth', | |
source = 'application/Auth' | |
} = options; | |
let addedImport = false; | |
let output = j(file.source) | |
.find(j.Identifier) | |
.filter((path) => { | |
return ( | |
path.node.name === specifier && | |
path.parentPath.name === 'params' && ( | |
isNgInject(path.parentPath.node) || | |
isControllerOnObject(path.parentPath.parentPath) || | |
isParameterOfAngularMethod(path.parentPath.parentPath) | |
) | |
); | |
}) | |
.closest(j.Program) | |
.forEach((path) => { | |
let importDeclaration = j.importDeclaration([j.importDefaultSpecifier(j.identifier(specifier))], j.literal(source)); | |
if (isUseStrict(path.node.body[0])) { | |
path.node.body.splice(1, 0, importDeclaration); | |
} | |
else { | |
path.node.body.unshift(importDeclaration); | |
} | |
addedImport = true; | |
}) | |
.toSource({ | |
arrowParensAlways: true, | |
quote: 'single', | |
}); | |
if (addedImport) { | |
// Remove injections using regex to retain code style | |
output = output.replace(new RegExp(`\\h*${specifier}\\s*,\\s*`, 'g'), '') | |
.replace(new RegExp(`\\s*,\\s*${specifier}\\h*(?=[,\\n\\)])`, 'g'), '') | |
.replace(new RegExp(`\\(\\s*${specifier}\\s*\\)`, 'g'), '()'); | |
} | |
return output; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment