import { sys, getDefaultCompilerOptions, createProgram, createCompilerHost } from "./typescript-internal"; import { loadSourceFiles } from "./types"; import { discover, DiscoveryResult } from "./discovery"; import { combinePaths } from "./utilities"; main(); function main() { if (sys.args.length < 3) { sys.write("Usage:" + sys.newLine) sys.write("\tnode processTypes.js " + sys.newLine); return; } const typesTsFileName = sys.resolvePath(sys.args[0]); const factoryTsFileName = sys.resolvePath(sys.args[1]); const utilitiesTsFileName = sys.resolvePath(sys.args[2]); loadSourceFiles([ /*typesTsFileName*/ sys.resolvePath(sys.args[0]), /*factoryTsFileName*/ sys.resolvePath(sys.args[1]), /*utilitiesTsFileName*/ sys.resolvePath(sys.args[2]) ]); // Discover syntax nodes const discovery = discover(); // Emit the generated factory output file const factoryDirectory = sys.resolvePath(combinePaths(factoryTsFileName, "..")); const factoryOutputFile = combinePaths(factoryDirectory, "factory.generated.ts"); const factoryOutput = generateFactory(discovery); sys.writeFile(factoryOutputFile, factoryOutput); } export function generateFactory(discovery: DiscoveryResult) { return ` // /// namespace ts {${each(discovery.createableNodes, syntaxNode => ` export function ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => `${member.parameterName}?: ${member.parameterTypeName}, `)}location?: TextRange, flags?: NodeFlags): ${syntaxNode.typeName} { let node = createNode<${syntaxNode.typeName}>(SyntaxKind.${syntaxNode.kindName}, location, flags); ${each(syntaxNode.createParameters, member => ` if (${member.parameterName}) ${ member.isModifiersArray ? `setModifiers(node, ${member.parameterName});` : member.isNodeArray ? `node.${member.propertyName} = createNodeArray(${member.parameterName});` : `node.${member.propertyName} = ${member.parameterName};` }`)} return node; }`)}${each(discovery.updateableNodes, syntaxNode => ` export function ${syntaxNode.updateFunctionName}(node: ${syntaxNode.typeName}${each(syntaxNode.updateParameters, member => `, ${member.parameterName}: ${member.parameterTypeName}`)}): ${syntaxNode.typeName} { if (${each(syntaxNode.updateParameters, member => `${member.parameterName} !== node.${member.propertyName}`, ` || `)}) { let newNode = ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => member.isFactoryParameter ? `node.${member.propertyName}` : member.parameterName, `, `)}); return updateFrom(node, newNode); } return node; }`)}${each(discovery.testableNodes, syntaxNode => ` export function ${syntaxNode.testFunctionName}(node: Node): node is ${syntaxNode.typeName} { return node && node.kind === SyntaxKind.${syntaxNode.kindName}; }`)}${each(discovery.testableTypes, syntaxType => ` export function ${syntaxType.testFunctionName}(node: Node): node is ${syntaxType.typeName} { if (node) { switch (node.kind) {${each(syntaxType.syntaxNodes, syntaxNode => ` case SyntaxKind.${syntaxNode.kindName}:`)} return true; } } return false; }`)} export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node { if (node) { switch (node.kind) {${each(discovery.updateableNodes, syntaxNode => ` case SyntaxKind.${syntaxNode.kindName}: return ${syntaxNode.updateFunctionName}(<${syntaxNode.typeName}>node${each(syntaxNode.updateParameters, member => member.visitorFunctionName && member.testFunctionName ? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor, ${member.testFunctionName})` : member.visitorFunctionName ? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor)` : `, (<${syntaxNode.typeName}>node).${member.propertyName}` )});`)} } } return node; } }`; function each(items: T[], callbackfn: (item: T) => string, separator = ``) { return items.map(callbackfn).join(separator); } }