Last active
June 1, 2020 13:08
TypeScript custom transformers with ts.createSolutionBuilderWithWatch
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
var ts = require('typescript'); | |
var diagReport = ts.createBuilderStatusReporter(ts.sys, ts.sys.writeOutputIsTTY && ts.sys.writeOutputIsTTY()); | |
var host = ts.createWatchCompilerHost( | |
[__filename], | |
{ allowJs: true, checkJs: true, outFile: __filename + '.out.js' }, | |
ts.sys, | |
createAndPatchProgram, | |
void 0, | |
reportWatch); | |
var buildStart = Date.now(); | |
ts.createWatchProgram(host); | |
function reportWatch(diag, newLine, options, errorCount) { | |
ts.sys.write(typeof errorCount === 'number' ? | |
'\x1b[90m ' + (((Date.now() - buildStart) / 1000) + 's ').slice(0, 10) + '\x1b[0m' : | |
'WATCH DIAG '); | |
diagReport(diag); | |
if (typeof errorCount !== 'number') buildStart = Date.now(); | |
} | |
var prog; | |
function createAndPatchProgram() { | |
prog = ts.createEmitAndSemanticDiagnosticsBuilderProgram.apply(ts, arguments); | |
prog.__oldEmit = prog.emit; | |
prog.emit = overrideEmit; | |
return prog; | |
} | |
function overrideEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { | |
return this.__oldEmit( | |
targetSourceFile, | |
writeFile, | |
cancellationToken, | |
emitOnlyDtsFiles, | |
{ after: [transformInjectStatementNumbers] } | |
); | |
} | |
var checker; | |
/** @param {import('typescript').TransformationContext} context */ | |
function transformInjectStatementNumbers(context) { | |
checker = prog.getProgram().getTypeChecker(); | |
return transformFile; | |
function transformFile(sourceFile) { | |
return ts.updateSourceFileNode( | |
sourceFile, | |
sourceFile.statements.map(decorateStatementWithComplexityAndType)); | |
} | |
} | |
function decorateStatementWithComplexityAndType(statement) { | |
var nodeCount = 0; | |
var type; | |
ts.forEachChild(statement, visitStatementChild); | |
return ts.addSyntheticLeadingComment( | |
statement, ts.SyntaxKind.SingleLineCommentTrivia, | |
' complexity: ' + nodeCount + | |
(!type ? '' : ' = ' + checker.typeToString(type))); | |
function visitStatementChild(child) { | |
nodeCount++; | |
if (!type) type = checker.getTypeAtLocation(child); | |
if (type.getFlags() === ts.TypeFlags.Any) type = null; | |
ts.forEachChild(child, visitStatementChild); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment