2023-09-01 16:21:45 +00:00
|
|
|
import ts from 'typescript'
|
2023-09-01 15:52:44 +00:00
|
|
|
|
|
|
|
const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
|
|
|
|
// TODO: get a reference to the program instance that the plugin is running in instead of creating a new program?
|
|
|
|
const program = ts.createProgram([], {})
|
|
|
|
const checker = program.getTypeChecker()
|
|
|
|
|
|
|
|
return sourceFile => {
|
|
|
|
const visitor = (node: ts.Node): ts.Node => {
|
|
|
|
// @ts-ignore
|
|
|
|
if (ts.isStringLiteral(node) && node.text === '__infer__') {
|
2023-09-01 16:36:50 +00:00
|
|
|
console.log('PLUGIN: FOUND AN OCCURRENCE OF __infer__')
|
2023-09-01 15:52:44 +00:00
|
|
|
|
2023-09-01 16:36:50 +00:00
|
|
|
// we're looking for a function call like typed('name', '__infer__', deps => ...)
|
2023-09-01 15:52:44 +00:00
|
|
|
const parentNode = node.parent
|
2023-09-01 16:36:50 +00:00
|
|
|
if (ts.isCallExpression(parentNode) && ts.isIdentifier(parentNode.expression) && parentNode.expression.escapedText === 'typed') {
|
|
|
|
// console.log('PARENT')
|
|
|
|
// console.log(parentNode)
|
|
|
|
|
|
|
|
// TODO: validate that argNode is an ArrowFunction
|
|
|
|
// @ts-ignore
|
|
|
|
const argNode = parentNode.arguments[2]
|
|
|
|
// @ts-ignore
|
|
|
|
const returnType = argNode.type.getText(sourceFile)
|
|
|
|
console.log('PLUGIN: RETURN TYPE')
|
|
|
|
console.log(returnType)
|
|
|
|
// (a: number) => number
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
const paramNode = argNode.parameters[0]
|
|
|
|
const paramTypeSrc = paramNode.type.getText(sourceFile)
|
|
|
|
console.log('PLUGIN: PARAM TYPE SRC', paramTypeSrc)
|
|
|
|
// {
|
|
|
|
// multiply: (a: number, b: number) => number,
|
|
|
|
// unaryMinus: (x: number) => number, // just for the experiment
|
|
|
|
// }
|
|
|
|
|
|
|
|
const type = checker.getTypeAtLocation(paramNode)
|
|
|
|
const paramType = checker.typeToString(type, paramNode, ts.TypeFormatFlags.InTypeAlias)
|
|
|
|
console.log('PLUGIN: PARAM TYPE STRING', paramType)
|
|
|
|
// { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; }
|
|
|
|
|
|
|
|
const depsAndReturnType = `{ deps: ${paramType}; return: ${returnType} }`
|
|
|
|
|
|
|
|
return ts.factory.createStringLiteral(depsAndReturnType)
|
|
|
|
}
|
2023-09-01 15:52:44 +00:00
|
|
|
}
|
|
|
|
|
2023-09-01 16:21:45 +00:00
|
|
|
return ts.visitEachChild(node, visitor, context)
|
|
|
|
}
|
2023-09-01 15:52:44 +00:00
|
|
|
|
2023-09-01 16:21:45 +00:00
|
|
|
return ts.visitNode(sourceFile, visitor)
|
|
|
|
}
|
|
|
|
}
|
2023-09-01 15:52:44 +00:00
|
|
|
|
2023-09-01 16:21:45 +00:00
|
|
|
export default transformer
|