Last active
July 12, 2024 12:37
-
-
Save sheepla/b0a0bfc8e8d42bcd3d8e40efaeb3731d to your computer and use it in GitHub Desktop.
Parse TypeScript AST in Deno
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
import * as ts from "https://esm.sh/typescript"; | |
interface BaseNode { | |
pos: number; | |
end: number; | |
kind: number; | |
id: number; | |
flags: number; | |
modifierFlagsCache: number; | |
transformFlags: number; | |
} | |
interface IdentifierNode extends BaseNode { | |
kind: 80; | |
escapedText: string; | |
} | |
interface ParameterNode extends BaseNode { | |
kind: 169; | |
name: IdentifierNode; | |
} | |
interface ArgumentNode extends BaseNode { | |
expression: ExpressionNode; | |
} | |
interface ExpressionNode extends BaseNode { | |
expression: IdentifierNode | BinaryExpressionNode; | |
arguments?: ArgumentNode[]; | |
} | |
interface BinaryExpressionNode extends BaseNode { | |
left: StringLiteralNode; | |
operatorToken: TokenNode; | |
right: IdentifierNode; | |
} | |
interface StringLiteralNode extends BaseNode { | |
kind: 11; | |
text: string; | |
hasExtendedUnicodeEscape: boolean; | |
} | |
interface TokenNode extends BaseNode { | |
kind: number; | |
} | |
interface StatementNode extends BaseNode { | |
name: IdentifierNode; | |
parameters: ParameterNode[]; | |
body: BlockNode; | |
} | |
interface BlockNode extends BaseNode { | |
statements: ExpressionStatementNode[]; | |
multiLine: boolean; | |
} | |
interface ExpressionStatementNode extends BaseNode { | |
expression: ExpressionNode; | |
} | |
interface Ast extends BaseNode { | |
statements: StatementNode[]; | |
endOfFileToken: TokenNode; | |
text: string; | |
fileName: string; | |
path: string; | |
resolvedPath: string; | |
originalFileName: string; | |
languageVersion: number; | |
languageVariant: number; | |
scriptKind: number; | |
isDeclarationFile: boolean; | |
hasNoDefaultLib: boolean; | |
nodeCount: number; | |
identifierCount: number; | |
symbolCount: number; | |
parseDiagnostics: any[]; | |
bindDiagnostics: any[]; | |
pragmas: any; | |
referencedFiles: any[]; | |
typeReferenceDirectives: any[]; | |
libReferenceDirectives: any[]; | |
amdDependencies: any[]; | |
identifiers: any; | |
jsDocParsingMode: number; | |
} | |
async function parseSourceCode(sourceCode: string): Promise<Ast> { | |
const srcFile = ts.createSourceFile( | |
"example.ts", | |
sourceCode, | |
ts.ScriptTarget.Latest, | |
true, | |
ts.ScriptKind.TS | |
); | |
const serializer = () => { | |
const seen = new WeakSet(); | |
return (_: any, value: any) => { | |
if (typeof value === "object" && value !== null) { | |
const containsCicularRef = seen.has(value) | |
if (containsCicularRef) { | |
return; | |
} | |
seen.add(value); | |
} | |
return value; | |
}; | |
}; | |
return JSON.parse(JSON.stringify(srcFile, serializer())); | |
} | |
async function parseSourceFile(path: string): Promise<Ast> { | |
const text = await Deno.readTextFile(path); | |
return parseSourceCode(text); | |
} | |
const ast = await parseSourceFile(Deno.args[0]) | |
console.log(ast); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Run
Result: