-
-
Save sadasant/af004683137185aec6fb06bdbc217039 to your computer and use it in GitHub Desktop.
magic typescript function that returns its arguments' AST
This file contains hidden or 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
// This uses my modified version of typescript from my branch github.com/willmtemple/typescript#fucking-parser | |
import * as ts from "typescript/built/local/typescript"; | |
import * as fs from "fs"; | |
import * as os from "os"; | |
import { promisify } from "util"; | |
const readFile = promisify(fs.readFile); | |
interface CallSite { | |
fileName: string; | |
lineNumber: number; | |
columnNumber: number; | |
} | |
/** | |
* Gets the filename of the calling function | |
*/ | |
function getCaller(): CallSite { | |
const stack = new Error().stack.split("\n").slice(1); | |
let relevantStackEntry = stack.filter( | |
(s) => !s.includes(__filename) && s.includes(".ts") | |
)[0]; | |
if (relevantStackEntry.includes("(")) { | |
relevantStackEntry = relevantStackEntry.split("(")[1].split(")")[0]; | |
} else { | |
relevantStackEntry = relevantStackEntry.split(" ").slice(-1)[0]; | |
} | |
const site = relevantStackEntry.split(":"); | |
return { | |
fileName: site[0], | |
lineNumber: parseInt(site[1]), | |
columnNumber: parseInt(site[2]), | |
}; | |
} | |
async function readFragmentToString(callSite: CallSite): Promise<string> { | |
const content = (await readFile(callSite.fileName)).toString("utf-8"); | |
const relevantLines = content.split(os.EOL).slice(callSite.lineNumber - 1); | |
relevantLines[0] = relevantLines[0].substring(callSite.columnNumber - 1); | |
return relevantLines.join(os.EOL); | |
} | |
export async function getAsts(..._: any[]): Promise<Array<ts.Expression>> { | |
const callSite = getCaller(); | |
const text = await readFragmentToString(callSite); | |
console.log(text); | |
ts.Parser.initializeState( | |
"", | |
text, | |
ts.ScriptTarget.ESNext, | |
undefined, | |
ts.ScriptKind.TS | |
); | |
// Prime the scanner with a new token | |
ts.Parser.nextToken(); | |
const expr = ts.Parser.parseExpression(); | |
console.log(expr); | |
// Top level AST points to the call, so we know it will be a call expression | |
// and have arguments. | |
return (expr as any).arguments; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment