vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
243 lines (242 loc) • 9.79 kB
JavaScript
import { BaseLanguageHandler } from './base.js';
import { getNodeText } from '../astAnalyzer.js';
import logger from '../../../logger.js';
export class LuaHandler extends BaseLanguageHandler {
getFunctionQueryPatterns() {
return [
'function_declaration',
'function_definition',
'local_function',
'function',
'anonymous_function'
];
}
getClassQueryPatterns() {
return [
'table_constructor',
'assignment_statement',
'variable_declaration'
];
}
getImportQueryPatterns() {
return [
'function_call',
'variable_declaration'
];
}
extractFunctionName(node, sourceCode, _options) {
try {
if (node.type === 'function_declaration' ||
node.type === 'function_definition' ||
node.type === 'local_function' ||
node.type === 'function') {
const nameNode = node.childForFieldName('name');
if (nameNode) {
const name = getNodeText(nameNode, sourceCode);
if (name.includes(':')) {
const parts = name.split(':');
return `method_${parts[0]}_${parts[1]}`;
}
if (name.includes('.')) {
const parts = name.split('.');
return `${parts[0]}_${parts[parts.length - 1]}`;
}
if (name.startsWith('test')) {
return `test_${name.substring(4)}`;
}
if (name.includes('Callback') || name.includes('_callback')) {
return `callback_${name}`;
}
return name;
}
}
if (node.type === 'anonymous_function') {
if (node.parent?.type === 'assignment_statement') {
const variableNode = node.parent.childForFieldName('variables');
if (variableNode?.firstChild) {
return getNodeText(variableNode.firstChild, sourceCode);
}
}
if (node.parent?.type === 'field' &&
node.parent.parent?.type === 'table_constructor') {
const nameNode = node.parent.childForFieldName('name');
if (nameNode) {
return getNodeText(nameNode, sourceCode);
}
}
return 'anonymous_function';
}
return 'anonymous';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua function name');
return 'anonymous';
}
}
extractClassName(node, sourceCode) {
try {
if (node.type === 'table_constructor') {
if (node.parent?.type === 'assignment_statement') {
const variableNode = node.parent.childForFieldName('variables');
if (variableNode?.firstChild) {
return getNodeText(variableNode.firstChild, sourceCode);
}
}
if (node.parent?.type === 'return_statement') {
let current = node.parent.parent;
while (current) {
if (current.type === 'function_declaration' ||
current.type === 'function_definition' ||
current.type === 'local_function') {
const nameNode = current.childForFieldName('name');
if (nameNode) {
return `${getNodeText(nameNode, sourceCode)}_Class`;
}
}
current = current.parent;
}
}
}
else if (node.type === 'assignment_statement') {
const variableNode = node.childForFieldName('variables');
const valueNode = node.childForFieldName('values');
if (variableNode?.firstChild &&
valueNode?.firstChild?.type === 'table_constructor') {
return getNodeText(variableNode.firstChild, sourceCode);
}
}
else if (node.type === 'variable_declaration') {
const nameNode = node.childForFieldName('name');
const valueNode = node.childForFieldName('value');
if (nameNode && valueNode?.type === 'table_constructor') {
return getNodeText(nameNode, sourceCode);
}
}
return 'AnonymousClass';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua class name');
return 'AnonymousClass';
}
}
extractParentClass(node, sourceCode) {
try {
if (node.type === 'assignment_statement' || node.type === 'variable_declaration') {
let current = node.nextNamedSibling;
while (current) {
if (current.type === 'function_call' &&
current.childForFieldName('name')?.text === 'setmetatable') {
const argsNode = current.childForFieldName('arguments');
if (argsNode && argsNode.childCount && argsNode.childCount >= 2) {
const parentNode = argsNode.child(1);
if (parentNode) {
return getNodeText(parentNode, sourceCode);
}
}
}
current = current.nextNamedSibling;
}
}
return undefined;
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua parent class');
return undefined;
}
}
extractImportPath(node, sourceCode) {
try {
if (node.type === 'function_call' &&
node.childForFieldName('name')?.text === 'require') {
const argsNode = node.childForFieldName('arguments');
if (argsNode?.firstChild) {
return getNodeText(argsNode.firstChild, sourceCode);
}
}
else if (node.type === 'variable_declaration') {
const valueNode = node.childForFieldName('value');
if (valueNode?.type === 'function_call' &&
valueNode.childForFieldName('name')?.text === 'require') {
const argsNode = valueNode.childForFieldName('arguments');
if (argsNode?.firstChild) {
return getNodeText(argsNode.firstChild, sourceCode);
}
}
}
return 'unknown';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua import path');
return 'unknown';
}
}
extractFunctionComment(node, sourceCode) {
try {
const current = node;
let prev = current.previousNamedSibling;
while (prev && prev.type !== 'comment') {
prev = prev.previousNamedSibling;
}
if (prev && prev.type === 'comment') {
const commentText = getNodeText(prev, sourceCode);
return commentText
.replace(/^--\s*/mg, '')
.trim();
}
return undefined;
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua function comment');
return undefined;
}
}
extractClassComment(node, sourceCode) {
try {
const current = node;
let prev = current.previousNamedSibling;
while (prev && prev.type !== 'comment') {
prev = prev.previousNamedSibling;
}
if (prev && prev.type === 'comment') {
const commentText = getNodeText(prev, sourceCode);
return commentText
.replace(/^--\s*/mg, '')
.trim();
}
return undefined;
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Lua class comment');
return undefined;
}
}
detectFramework(sourceCode) {
try {
if (sourceCode.includes('love.') ||
sourceCode.includes('function love.') ||
sourceCode.includes('love.graphics')) {
return 'love2d';
}
if (sourceCode.includes('display.') ||
sourceCode.includes('physics.') ||
sourceCode.includes('transition.')) {
return 'corona';
}
if (sourceCode.includes('lapis.') ||
sourceCode.includes('require("lapis")') ||
sourceCode.includes('app:get')) {
return 'lapis';
}
if (sourceCode.includes('torch.') ||
sourceCode.includes('nn.') ||
sourceCode.includes('require("torch")')) {
return 'torch';
}
return null;
}
catch (error) {
logger.warn({ err: error }, 'Error detecting Lua framework');
return null;
}
}
}