vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
169 lines (168 loc) • 6.72 kB
JavaScript
import { BaseLanguageHandler } from './base.js';
import { getNodeText } from '../astAnalyzer.js';
import logger from '../../../logger.js';
export class DefaultLanguageHandler extends BaseLanguageHandler {
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'
];
}
getClassQueryPatterns() {
return [
'class_declaration',
'class_definition',
'class',
'class_item',
'struct_declaration',
'struct_definition',
'struct',
'interface_declaration',
'interface_definition',
'interface'
];
}
getImportQueryPatterns() {
return [
'import_declaration',
'import_statement',
'import',
'include_statement',
'include',
'require',
'using_declaration',
'using_directive',
'using'
];
}
extractFunctionName(node, sourceCode, _options) {
try {
const nameNode = node.childForFieldName('name');
if (nameNode) {
return getNodeText(nameNode, sourceCode);
}
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);
}
}
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);
}
}
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);
if (['map', 'filter', 'reduce', 'forEach', 'find', 'findIndex', 'some', 'every'].includes(funcName)) {
return `${funcName}_callback`;
}
if (['describe', 'it', 'test', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll'].includes(funcName)) {
const args = callExprNode.childForFieldName('arguments');
if (args && args.firstChild &&
(args.firstChild.type === 'string' || args.firstChild.type === 'string_literal')) {
const testDesc = getNodeText(args.firstChild, sourceCode);
const cleanDesc = testDesc.replace(/^["']|["']$/g, '').substring(0, 30);
return `${funcName}_${cleanDesc}`;
}
return `${funcName}_handler`;
}
}
}
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`;
}
}
return 'anonymous';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting function name');
return 'anonymous';
}
}
extractClassName(node, sourceCode) {
try {
const nameNode = node.childForFieldName('name');
if (nameNode) {
return getNodeText(nameNode, sourceCode);
}
return 'AnonymousClass';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting class name');
return 'AnonymousClass';
}
}
extractImportPath(node, sourceCode) {
try {
const sourceNode = node.childForFieldName('source');
if (sourceNode) {
return getNodeText(sourceNode, sourceCode).replace(/^["']|["']$/g, '');
}
const pathNode = node.childForFieldName('path');
if (pathNode) {
return getNodeText(pathNode, sourceCode).replace(/^["']|["']$/g, '');
}
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, '');
}
}
return 'unknown';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting import path');
return 'unknown';
}
}
extractFunctionComment(node, sourceCode) {
try {
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;
}
}
}