typocomath/src/plugins/myFirstPlugin.ts

59 lines
2.0 KiB
TypeScript

import * as ts from 'typescript';
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 => {
// For the experiment we only want to influence a single file
if (!sourceFile.fileName.endsWith('arithmeticInfer4.ts')) {
return sourceFile
}
const visitor = (node: ts.Node): ts.Node => {
// @ts-ignore
if (ts.isStringLiteral(node) && node.text === '__infer__') {
console.log('STRING LITERAL', node.text)
console.log(node)
const parentNode = node.parent
console.log('PARENT')
console.log(parentNode)
// TODO: validate that the parent is indeed a mathjs typed function with deps
// @ts-ignore
const argNode = parentNode.arguments[1]
const returnType = argNode.type.getText(sourceFile)
console.log('RETURN TYPE')
console.log(returnType)
// (a: number) => number
const paramNode = argNode.parameters[0]
const paramTypeSrc = paramNode.type.getText(sourceFile)
console.log('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('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)
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(sourceFile, visitor);
};
};
export default transformer;