Skip to content

Instantly share code, notes, and snippets.

@sadasant
Forked from willmtemple/index.ts
Created June 26, 2020 19:06
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 sadasant/af004683137185aec6fb06bdbc217039 to your computer and use it in GitHub Desktop.
Save sadasant/af004683137185aec6fb06bdbc217039 to your computer and use it in GitHub Desktop.
magic typescript function that returns its arguments' AST
// 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