Skip to content

Instantly share code, notes, and snippets.

@sadan4
Created September 25, 2024 00:07
Show Gist options
  • Select an option

  • Save sadan4/752113ac158732d64a2e3ad60cbd247c to your computer and use it in GitHub Desktop.

Select an option

Save sadan4/752113ac158732d64a2e3ad60cbd247c to your computer and use it in GitHub Desktop.
horrorcode v2
import { collectVariableUsage, isSyntaxList, VariableInfo, VariableUse } from "tsutils";
import { FunctionExpression, Identifier, isBinaryExpression, isCallExpression, isExpressionStatement, isFunctionExpression, isIdentifier, isNumericLiteral, isPropertyAccessExpression, isReturnStatement, isVariableDeclaration, Node, ObjectLiteralExpression, PropertyAccessExpression, PropertyAssignment, SourceFile, VariableDeclaration } from "typescript";
import * as vscode from "vscode";
import { window } from "vscode";
import { getNumberAndColumnFromPos } from "./lineUtil";
export const zeroRange = new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0));
export function findParrent<T extends Node | undefined = Node>(node: Node, func: (node: Node) => boolean): T | undefined {
while (!func(node)) {
if (!node.parent) return undefined;
node = node.parent;
}
return node as T;
}
type NodeFunc = (node: Node) => boolean;
/**
* @param node the node to start from
* @param func a function to check if the parrent matches
*/
export function lastParrent<T extends Node = Node>(node: Node, func: NodeFunc): T | undefined {
if (!node.parent) return undefined;
while (func(node.parent)) {
if (!node.parent) return node as T;
node = node.parent;
}
return node as T;
}
export function lastChild<T extends Node = Node>(node: Node | undefined, func: NodeFunc): T | undefined {
if (!node) return undefined;
const c = node.getChildren();
if (c.length === 0) {
if (func(node)) return node as T;
return undefined;
}
if (c.length === 1) {
if (func(c[0])) return lastChild(c[0], func);
if (func(node)) return node as T;
return undefined;
}
const x = one(c, func);
if (x) {
return lastChild(x, func);
}
if (func(node)) return node as T;
return undefined;
}
function one<T>(arr: Array<T>, func: (t: T) => boolean): T | undefined {
const filter = arr.filter(func);
return (filter.length === 1 || undefined) && filter[0];
}
export function getLeadingIdentifier(node: Node | undefined): [Identifier | undefined, Identifier | undefined] {
if (!node) return [node, undefined];
const { expression: module, name: wpExport } = lastChild<PropertyAccessExpression>(lastParrent(node, isPropertyAccessExpression), isPropertyAccessExpression) ?? {};
if (!module || !isIdentifier(module)) return [undefined, undefined];
return [module, wpExport ? isIdentifier(wpExport) ? wpExport : undefined : undefined];
}
/**
* @param node finds a webpack arg from the source tree
* @param paramIndex the index of the param 0, 1, 2 etc...
* @returns the indenfiier of the param if found or undef
*/
export function findWebpackArg(node: Node, paramIndex = 2): Identifier | undefined {
for (const n of node.getChildren()) {
if (isSyntaxList(n) ||
isExpressionStatement(n) ||
isBinaryExpression(n))
return findWebpackArg(n);
if (isFunctionExpression(n)) {
if (n.parameters.length !== 3) return;
const p = n.parameters[paramIndex].name;
if (!p) return;
if (!isIdentifier(p)) return;
return p;
}
}
}
export function getModuleId(dec: VariableInfo | undefined, wpExport: Identifier | undefined): undefined | number {
if (!dec) return undefined;
if (dec.declarations.length !== 1) return undefined;
const init = findParrent<VariableDeclaration>(dec.declarations[0], isVariableDeclaration)?.initializer;
if (!init || !isCallExpression(init)) return undefined;
if (init.arguments.length !== 1 || !isNumericLiteral(init.arguments[0])) return undefined;
const num = +init.arguments[0].text;
// window.showInformationMessage(`${num}\n${wpExport?.text || "No export found"}`);
return num;
}
export type Definitions = vscode.ProviderResult<vscode.Definition | vscode.DefinitionLink[]>;
export function findExportLocation(exportFile: SourceFile, wpExportName: string): vscode.Range | undefined {
const vars = collectVariableUsage(exportFile);
const wreq = findWebpackArg(exportFile);
if (!wreq) {
console.error(new Error("could not find wreq"));
return;
}
console.log(vars.get(wreq));
return;
}
export function findWreq_d(use: VariableUse): boolean {
if (getLeadingIdentifier(use.location)[1]?.text === "d") return true
return false;
}
export function findObjectLiteralByKey(object: ObjectLiteralExpression, prop: string) {
return object.properties.find(x => x.name?.getText() === prop)
} export function findReturnIdentifier(func: FunctionExpression): Identifier | undefined {
const lastStatment = func.body.statements.at(-1);
if (!lastStatment || !isReturnStatement(lastStatment)
|| !lastStatment.expression || !isIdentifier(lastStatment.expression)
) return undefined;
return lastStatment.expression
}
export function makeRange(node: Node, text: string): vscode.Range {
return new vscode.Range(makeLocation(node.pos, text), makeLocation(node.end, text))
}
export function makeLocation(pos: number, text: string): vscode.Position {
const loc = getNumberAndColumnFromPos(text, pos);
return new vscode.Position(loc.lineNumber, loc.column);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment