Created
July 26, 2022 13:18
-
-
Save martinschneider01/40e0f340cf2ed549a875e8de00475b97 to your computer and use it in GitHub Desktop.
This file contains 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
// Codemod to be used with jscodeshift | |
import { | |
API, | |
ASTPath, | |
CallExpression, | |
FileInfo, | |
Identifier, | |
JSCodeshift, | |
ObjectExpression, | |
ObjectProperty, | |
} from 'jscodeshift'; | |
const requiredPropertiesKeys = ['data', 'number', 'general', 'renderers'] as const; | |
// Filter function to ensure that we enter the mutation function only if needed | |
const filterOutSimpleUsages = (p: ASTPath<CallExpression>) => { | |
const args = p.value.arguments; | |
// If we only have the translation key, we don't need to refactor this usage | |
if (args.length === 1) { | |
return false; | |
} | |
// More than 2 arguments is an absolute sign of an old usage | |
// If second argument is not an object, we need to manually fix this case | |
if (args.length > 2 || args[1].type !== 'ObjectExpression') { | |
return true; | |
} | |
// If none of the above properties is found in second argument, we can say that this is an old usage | |
return requiredPropertiesKeys.every( | |
(requiredPropertyKey) => | |
!(args[1] as ObjectExpression).properties.find( | |
// I needed to do some TS trickery to avoid getting warnings everywhere, sorry for that | |
(property) => ((property as ObjectProperty).key as Identifier).name === requiredPropertyKey, | |
), | |
); | |
}; | |
// Mutation function, we apply our modification to the AST | |
const mutatePath = (j: JSCodeshift) => (p: ASTPath<CallExpression>) => { | |
const objectProperties = requiredPropertiesKeys.reduce((acc, propertyKey, index) => { | |
const argument = p.value.arguments[index + 1]; | |
if (!argument || argument.type === 'SpreadElement') { | |
return acc; | |
} | |
if ((argument as Identifier).name && (argument as Identifier).name === 'undefined') { | |
return acc; | |
} | |
return [...acc, j.objectProperty(j.identifier(propertyKey), argument)]; | |
}, [] as ObjectProperty[]); | |
p.value.arguments = [p.value.arguments[0], j.objectExpression(objectProperties)]; | |
return p; | |
}; | |
module.exports = function (file: FileInfo, api: API) { | |
const j = api.jscodeshift; | |
// If we don't find any "Translate" string inside our file, we can assume that it's safe to skip it | |
const regex = new RegExp('Translate[(]', 'i'); | |
if (!regex.test(file.source)) { | |
return null; | |
} | |
return j(file.source) | |
.find(j.CallExpression, { | |
callee: { | |
type: 'Identifier', | |
name: 't', | |
}, | |
}) | |
.filter(filterOutSimpleUsages) | |
.map(mutatePath(j)) | |
.toSource(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment