Skip to main content
Glama
default.js8.61 kB
/** * Default language handler for the Code-Map Generator tool. * This file contains the default language handler that provides basic function detection * for languages without specific handlers. */ import { getNodeText } from '../astAnalyzer.js'; import logger from '../../../logger.js'; import { ContextTracker } from '../context/contextTracker.js'; /** * Default language handler that provides basic function detection for languages without specific handlers. */ export class DefaultLanguageHandler { /** * Context tracker for nested function analysis. */ contextTracker = new ContextTracker(); /** * Gets the query patterns for function detection. */ getFunctionQueryPatterns() { return [ 'function_declaration', 'function_definition', 'method_declaration', 'method_definition', 'function', 'arrow_function', 'lambda', 'lambda_expression', 'function_item', 'method', 'subroutine', 'procedure_declaration', 'procedure', 'sub', 'def' ]; } /** * Gets the query patterns for class detection. */ getClassQueryPatterns() { return [ 'class_declaration', 'class_definition', 'class', 'class_item', 'struct_declaration', 'struct_definition', 'struct', 'interface_declaration', 'interface_definition', 'interface' ]; } /** * Gets the query patterns for import detection. */ getImportQueryPatterns() { return [ 'import_declaration', 'import_statement', 'import', 'include_statement', 'include', 'require', 'using_declaration', 'using_directive', 'using' ]; } /** * Extracts the function name from an AST node. */ extractFunctionName(node, sourceCode, options) { try { // Try to get name from 'name' field const nameNode = node.childForFieldName('name'); if (nameNode) { return getNodeText(nameNode, sourceCode); } // Try to get name from parent if it's a variable declaration if (node.parent?.type === 'variable_declarator' || node.parent?.type === 'variable_declaration' || node.parent?.type === 'assignment_expression') { const parentNameNode = node.parent.childForFieldName('name') || node.parent.childForFieldName('left'); if (parentNameNode) { return getNodeText(parentNameNode, sourceCode); } } // Try to get name from parent if it's a property if (node.parent?.type === 'pair' || node.parent?.type === 'property_definition' || node.parent?.type === 'property') { const keyNode = node.parent.childForFieldName('key') || node.parent.childForFieldName('name'); if (keyNode) { return getNodeText(keyNode, sourceCode); } } // Try to get name from parent if it's a function call argument if (node.parent?.type === 'arguments' && node.parent.parent?.type === 'call_expression') { const callExprNode = node.parent.parent; const funcNameNode = callExprNode.childForFieldName('function'); if (funcNameNode) { const funcName = getNodeText(funcNameNode, sourceCode); // Common callback patterns if (['map', 'filter', 'reduce', 'forEach', 'find', 'findIndex', 'some', 'every'].includes(funcName)) { return `${funcName}_callback`; } // Common test framework patterns if (['describe', 'it', 'test', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll'].includes(funcName)) { // Try to get the test description from the first argument const args = callExprNode.childForFieldName('arguments'); if (args && args.firstChild && (args.firstChild.type === 'string' || args.firstChild.type === 'string_literal')) { const testDesc = getNodeText(args.firstChild, sourceCode); // Remove quotes and truncate if too long const cleanDesc = testDesc.replace(/^["']|["']$/g, '').substring(0, 30); return `${funcName}_${cleanDesc}`; } return `${funcName}_handler`; } } } // Use context information if available const context = this.contextTracker.getCurrentContext(); if (context && context.parent) { if (context.parent.type === 'class' && context.parent.name) { return `${context.parent.name}_method`; } else if (context.parent.type === 'function' && context.parent.name) { return `${context.parent.name}_inner`; } } // If all else fails, return 'anonymous' return 'anonymous'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting function name'); return 'anonymous'; } } /** * Extracts the class name from an AST node. */ extractClassName(node, sourceCode) { try { // Try to get name from 'name' field const nameNode = node.childForFieldName('name'); if (nameNode) { return getNodeText(nameNode, sourceCode); } // If all else fails, return 'AnonymousClass' return 'AnonymousClass'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting class name'); return 'AnonymousClass'; } } /** * Extracts the import path from an AST node. */ extractImportPath(node, sourceCode) { try { // Try to get path from 'source' field const sourceNode = node.childForFieldName('source'); if (sourceNode) { return getNodeText(sourceNode, sourceCode).replace(/^["']|["']$/g, ''); } // Try to get path from 'path' field const pathNode = node.childForFieldName('path'); if (pathNode) { return getNodeText(pathNode, sourceCode).replace(/^["']|["']$/g, ''); } // Try to get path from string literal child for (let i = 0; i < node.childCount; i++) { const child = node.child(i); if (child && (child.type === 'string' || child.type === 'string_literal')) { return getNodeText(child, sourceCode).replace(/^["']|["']$/g, ''); } } // If all else fails, return 'unknown' return 'unknown'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting import path'); return 'unknown'; } } /** * Extracts the function comment from an AST node. */ extractFunctionComment(node, sourceCode) { try { // Look for a comment node before the function const startPosition = node.startPosition; const startIndex = startPosition.row > 0 ? sourceCode.lastIndexOf('\n', sourceCode.indexOf('\n', 0) + startPosition.row) : 0; if (startIndex >= 0) { const textBeforeNode = sourceCode.substring(0, startIndex); const commentMatch = textBeforeNode.match(/\/\*\*([\s\S]*?)\*\/\s*$/) || textBeforeNode.match(/\/\/(.*)\s*$/); if (commentMatch) { return commentMatch[1].trim(); } } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting function comment'); return undefined; } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/freshtechbro/vibe-coder-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server