Skip to content

Instantly share code, notes, and snippets.

@calebdre
Created June 14, 2024 20:55
Show Gist options
  • Save calebdre/4e1519d6762e4ed3d26777f3e8994181 to your computer and use it in GitHub Desktop.
Save calebdre/4e1519d6762e4ed3d26777f3e8994181 to your computer and use it in GitHub Desktop.
export function extractFunctions(fileContents: string): ExtractFunctionResponse[] {
const functions: ExtractFunctionResponse[] = [];
try {
const ast = parser.parse(fileContents, {
sourceType: 'module',
plugins: ['typescript', 'jsx'],
allowImportExportEverywhere: true,
allowAwaitOutsideFunction: true,
allowReturnOutsideFunction: true,
allowSuperOutsideMethod: true,
allowUndeclaredExports: true,
errorRecovery: true,
});
traverse(ast, {
FunctionDeclaration(path) {
const node = path.node;
functions.push({
function: fileContents.slice(node.start, node.end),
functionName: node.id.name,
});
},
VariableDeclarator(path) {
const node = path.node;
if (node.init && types.isArrowFunctionExpression(node.init)) {
functions.push({
function: fileContents.slice(node.start, node.end),
functionName: node.id.name,
});
}
},
ExportNamedDeclaration(path) {
const node = path.node;
if (node.declaration) {
if (types.isVariableDeclaration(node.declaration)) {
node.declaration.declarations.forEach((declarator) => {
if (
declarator.init &&
types.isArrowFunctionExpression(declarator.init)
) {
functions.push({
function: fileContents.slice(declarator.start, declarator.end),
functionName: declarator.id.name,
});
}
});
} else if (types.isFunctionDeclaration(node.declaration)) {
functions.push({
function: fileContents.slice(
node.declaration.start,
node.declaration.end
),
functionName: node.declaration.id.name,
});
}
} else if (node.specifiers && node.specifiers.length > 0) {
node.specifiers.forEach((specifier) => {
if (types.isExportSpecifier(specifier)) {
const exportedName = specifier.exported.name;
const binding = path.scope.getBinding(exportedName);
if (binding && binding.path.isVariableDeclarator()) {
const declaratorNode = binding.path.node;
if (
declaratorNode.init &&
types.isArrowFunctionExpression(declaratorNode.init)
) {
functions.push({
function: fileContents.slice(
declaratorNode.start,
declaratorNode.end
),
functionName: exportedName,
});
}
}
}
});
}
},
});
} catch (error) {
console.error('Error parsing file:', error);
}
// remove duplicates with the same function name
return functions.filter((func, index, self) =>
index === self.findIndex((f) => f.functionName === func.functionName)
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment