Last active
November 15, 2022 04:28
-
-
Save hi-ogawa/aa33a19cd4e3b513ff2493a05f59e5c7 to your computer and use it in GitHub Desktop.
jscodeshift script for converting number values to string values within specified forms of variable declarations
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
/* eslint-disable no-console */ | |
// | |
// usage: | |
// npm i -D jscodeshift @types/jscodeshift recast | |
// npx jscodeshift --parser tsx --transform patch-transaction-editable.ts (...files) | |
// | |
/* | |
//// example input //// | |
const someVariable: TransactionEditable[] = [ | |
{ | |
vol: "0", | |
prc: -1, | |
fee: 1 * 2, | |
realized: SOME_CONSTANT, | |
} | |
] | |
//// example output //// | |
const someVariable: TransactionEditable[] = [ | |
{ | |
vol: "0", | |
prc: "-1", | |
fee: (1 * 2).toString(), | |
realized: SOME_CONSTANT.toString(), | |
} | |
] | |
*/ | |
import type { API, FileInfo } from "jscodeshift"; | |
import * as recast from "recast"; | |
const TYPES = ["TransactionEditable", "TransactionCreateRequest"]; | |
const NUMERIC_PROPERTY_NAMES = ["vol", "prc", "fee", "realized"]; | |
export default function transformer(file: FileInfo, api: API): string { | |
const j = api.jscodeshift; | |
const $j = j(file.source); | |
for (const path of $j.find(j.VariableDeclaration).paths()) { | |
for (const decl of path.value.declarations) { | |
if (decl.type !== "VariableDeclarator") continue; | |
if (decl.id.type !== "Identifier") continue; | |
if (decl.id.typeAnnotation?.type !== "TSTypeAnnotation") continue; | |
// match e.g. `TransactionEditable`, `TransactionEditable[]`, `TransactionCreateRequest`, etc... | |
if ( | |
j(decl.id.typeAnnotation) | |
.find(j.Identifier) | |
.filter(i => TYPES.includes(i.value.name)).length === 0 | |
) | |
continue; | |
if (!decl.init) continue; | |
for (const prop of j(path).find(j.ObjectProperty).paths()) { | |
if (prop.value.key.type !== "Identifier") continue; | |
if (!NUMERIC_PROPERTY_NAMES.includes(prop.value.key.name)) continue; | |
// skip if string | |
if (prop.value.value.type === "StringLiteral") continue; | |
// skip if `toString` | |
const code = recast.print(prop.value).code.trim(); | |
if (code.endsWith("toString()")) continue; | |
// debug log | |
console.error( | |
`${file.path}:${prop.value.loc?.start.line}:${prop.value.loc?.start.column} - ${code}` | |
); | |
// number literal to string literal | |
if (prop.value.value.type === "NumericLiteral") { | |
prop.replace( | |
j.objectProperty( | |
j.identifier(prop.value.key.name), | |
j.stringLiteral(prop.value.value.value.toString()) | |
) | |
); | |
continue; | |
} | |
// negated number literal to string literal | |
if ( | |
prop.value.value.type === "UnaryExpression" && | |
prop.value.value.operator === "-" && | |
prop.value.value.argument.type === "NumericLiteral" | |
) { | |
prop.replace( | |
j.objectProperty( | |
j.identifier(prop.value.key.name), | |
j.stringLiteral("-" + prop.value.value.argument.value.toString()) | |
) | |
); | |
continue; | |
} | |
// otherwise call `toString` at runtime | |
if (recast.types.namedTypes.Expression.check(prop.value.value)) { | |
prop.replace( | |
j.objectProperty( | |
j.identifier(prop.value.key.name), | |
j.callExpression( | |
// TODO: type assersion seems not working | |
j.memberExpression(prop.value.value as any, j.identifier("toString")), | |
[] | |
) | |
) | |
); | |
} | |
continue; | |
} | |
} | |
} | |
return $j.toSource(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment