Skip to content

Instantly share code, notes, and snippets.

@dsherret
Last active November 27, 2018 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsherret/499c61da33570f9ba8efda924e49ec64 to your computer and use it in GitHub Desktop.
Save dsherret/499c61da33570f9ba8efda924e49ec64 to your computer and use it in GitHub Desktop.
import { Project, ts, Node, SyntaxKind } from "ts-simple-ast";
for (const nodeName of getCompilerNodeNames().sort()) {
const result = doForNodeName(nodeName);
if (result === true)
console.log(`${nodeName}: No any.`);
else
console.log(`${nodeName}: ${result} classes.`);
}
function doForNodeName(compilerNodeName: string) {
const fileText = `import * as ts from "typescript";
type WrappedNodeType = CompilerNodeToWrappedType<ts.${compilerNodeName}>;
type CompilerNodeToWrappedType<T extends ts.Node> = T extends ts.${compilerNodeName} ? ${compilerNodeName} : Node<T>;
class Node<NodeType extends ts.Node = ts.Node> {
compilerNode!: NodeType;
}
class ${compilerNodeName} extends Node<ts.${compilerNodeName}> {}
`;
const project = new Project();
const sourceFile = project.createSourceFile("Node.ts", fileText);
const wrappedNode = sourceFile.getTypeAliasOrThrow("WrappedNodeType");
const compilerNodeToWrappedType = sourceFile.getTypeAliasOrThrow("CompilerNodeToWrappedType");
const nodeNames = getCompilerNodeNames();
nodeNames.splice(nodeNames.indexOf(compilerNodeName), 1);
for (const nodeName of nodeNames) {
sourceFile.addStatements(`class ${nodeName} extends Node<ts.${nodeName}> {}`);
// conditional type nodes are not implemented yet in ts-simple-ast, so falling back (messy)
let currentTypeNode = compilerNodeToWrappedType.getTypeNodeOrThrow() as Node<ts.ConditionalTypeNode>;
while (currentTypeNode.getKind() === SyntaxKind.ConditionalType)
currentTypeNode = currentTypeNode.getNodeProperty("falseType");
currentTypeNode = currentTypeNode.getParent();
currentTypeNode.replaceWithText(writer => writer.writeLine(`T extends ts.${nodeName} ? ${nodeName} :`).write(currentTypeNode.getText()));
const wrappedTypeText = wrappedNode.getType().getText(wrappedNode);
if (wrappedTypeText === "any") {
//ensureNoCompileErrors();
return sourceFile.getClasses().length;
}
if (wrappedTypeText !== compilerNodeName)
throw new Error(wrappedTypeText + ":" + compilerNodeName);
}
//ensureNoCompileErrors();
return true;
function ensureNoCompileErrors() {
const diagnostics = project.getPreEmitDiagnostics();
if (diagnostics.length > 0)
console.log(project.formatDiagnosticsWithColorAndContext(diagnostics));
}
}
function getCompilerNodeNames() {
return [ "ArrayBindingPattern", "BindingElement", "ObjectBindingPattern", "ClassDeclaration", "ClassExpression", "ConstructorDeclaration",
"GetAccessorDeclaration", "MethodDeclaration", "PropertyDeclaration", "SetAccessorDeclaration", "ComputedPropertyName", "Identifier", "QualifiedName",
"SyntaxList", "Decorator", "JSDoc", "JSDocAugmentsTag", "JSDocClassTag", "JSDocParameterTag", "JSDocPropertyTag", "JSDocReturnTag", "JSDocTypedefTag", "JSDocTypeTag",
"JSDocUnknownTag", "EnumDeclaration", "EnumMember", "AsExpression", "AwaitExpression", "CallExpression", "CommaListExpression", "ConditionalExpression",
"DeleteExpression", "ImportExpression", "MetaProperty", "NewExpression", "NonNullExpression", "OmittedExpression", "ParenthesizedExpression", "PartiallyEmittedExpression",
"PostfixUnaryExpression", "PrefixUnaryExpression", "SpreadElement", "SuperElementAccessExpression", "SuperExpression", "SuperPropertyAccessExpression",
"ThisExpression", "TypeAssertion", "TypeOfExpression", "VoidExpression", "YieldExpression", "ArrowFunction", "FunctionDeclaration", "FunctionExpression",
"ParameterDeclaration", "HeritageClause", "CallSignatureDeclaration", "ConstructSignatureDeclaration", "IndexSignatureDeclaration", "InterfaceDeclaration",
"MethodSignature", "PropertySignature", "TypeElement", "JsxAttribute", "JsxClosingElement", "JsxClosingFragment", "JsxElement", "JsxFragment", "JsxOpeningElement",
"JsxOpeningFragment", "JsxSelfClosingElement", "JsxSpreadAttribute", "JsxText", "BooleanLiteral", "NullLiteral", "NumericLiteral", "RegularExpressionLiteral",
"StringLiteral", "ExportAssignment", "ExportDeclaration", "ExportSpecifier", "ExternalModuleReference", "ImportClause", "ImportDeclaration", "ImportEqualsDeclaration",
"ImportSpecifier", "ModuleBlock", "NamedExports", "NamedImports", "NamespaceDeclaration", "NamespaceImport", "SourceFile", "Block", "BreakStatement",
"CaseBlock", "CaseClause", "CatchClause", "ContinueStatement", "DebuggerStatement", "DefaultClause", "DoStatement", "EmptyStatement", "ExpressionStatement", "ForInStatement",
"ForOfStatement", "ForStatement", "IfStatement", "LabeledStatement", "NotEmittedStatement", "ReturnStatement", "SwitchStatement", "ThrowStatement", "TryStatement",
"VariableStatement", "WhileStatement", "IterationStatement", "WithStatement", "ArrayTypeNode", "ConstructorTypeNode", "ExpressionWithTypeArguments", "FunctionTypeNode",
"ImportTypeNode", "IntersectionTypeNode", "LiteralTypeNode", "ParenthesizedTypeNode", "TupleTypeNode", "TypeAliasDeclaration", "Statement", "TypeLiteralNode",
"TypeParameterDeclaration", "TypeReferenceNode", "UnionTypeNode", "TypeNode", "VariableDeclaration", "VariableDeclarationList", "ArrayDestructuringAssignment",
"ArrayLiteralExpression", "ObjectDestructuringAssignment", "BinaryExpression", "ObjectLiteralExpression", "PropertyAssignment", "ShorthandPropertyAssignment",
"SpreadAssignment", "NoSubstitutionTemplateLiteral", "LiteralExpression", "TaggedTemplateExpression", "TemplateExpression", "PrimaryExpression", "MemberExpression",
"LeftHandSideExpression", "UpdateExpression", "UnaryExpression", "TemplateHead", "TemplateMiddle", "TemplateSpan", "TemplateTail", "JsxExpression"
];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment