vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
190 lines (189 loc) • 6.75 kB
JavaScript
import { BaseLanguageHandler } from './base.js';
import { getNodeText } from '../astAnalyzer.js';
import logger from '../../../logger.js';
export class BashHandler extends BaseLanguageHandler {
options;
getFunctionQueryPatterns() {
return [
'function_definition',
'declaration_command'
];
}
getClassQueryPatterns() {
return [
'program'
];
}
getImportQueryPatterns() {
return [
'source_command',
'command'
];
}
extractFunctionName(node, sourceCode, _options) {
try {
if (node.type === 'function_definition') {
const nameNode = node.childForFieldName('name');
if (nameNode) {
const name = getNodeText(nameNode, sourceCode);
if (name.startsWith('test_')) {
return name;
}
if (this.isHookFunction(name)) {
return `hook_${name}`;
}
return name;
}
}
if (node.type === 'declaration_command') {
const commandNode = node.childForFieldName('command');
if (commandNode?.text === 'function') {
const nameNode = node.childForFieldName('name');
if (nameNode) {
const name = getNodeText(nameNode, sourceCode);
if (name.startsWith('test_')) {
return name;
}
if (this.isHookFunction(name)) {
return `hook_${name}`;
}
return name;
}
}
}
return 'anonymous';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Bash/Shell function name');
return 'anonymous';
}
}
isHookFunction(name) {
const hookFunctions = [
'pre_install',
'post_install',
'pre_upgrade',
'post_upgrade',
'pre_remove',
'post_remove',
'setup',
'teardown',
'before_script',
'after_script'
];
return hookFunctions.includes(name);
}
extractClassName(node, _sourceCode) {
try {
if (node.type === 'program' && this.options?.filePath) {
const filename = this.options.filePath.split('/').pop() || 'script';
return filename.replace(/\.[^.]+$/, '');
}
return 'Script';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Bash/Shell class name');
return 'Script';
}
}
extractImportPath(node, sourceCode) {
try {
if (node.type === 'source_command') {
const pathNode = node.childForFieldName('path');
if (pathNode) {
return getNodeText(pathNode, sourceCode);
}
}
else if (node.type === 'command') {
const nameNode = node.childForFieldName('name');
if (nameNode && (nameNode.text === 'source' || nameNode.text === '.')) {
const argumentNode = node.childForFieldName('argument');
if (argumentNode) {
return getNodeText(argumentNode, sourceCode);
}
}
}
return 'unknown';
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Bash/Shell 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 Bash/Shell function comment');
return undefined;
}
}
extractClassComment(node, sourceCode) {
try {
if (node.type === 'program') {
const firstChild = node.firstChild;
if (firstChild?.type === 'shebang') {
return `Shell: ${getNodeText(firstChild, sourceCode)}`;
}
let commentBlock = '';
let current = node.firstChild;
if (current?.type === 'shebang') {
current = current.nextNamedSibling;
}
while (current && current.type === 'comment') {
commentBlock += getNodeText(current, sourceCode).replace(/^#\s*/mg, '') + '\n';
current = current.nextNamedSibling;
}
if (commentBlock) {
return commentBlock.trim();
}
}
return undefined;
}
catch (error) {
logger.warn({ err: error, nodeType: node.type }, 'Error extracting Bash/Shell class comment');
return undefined;
}
}
detectFramework(sourceCode) {
try {
if (sourceCode.includes('docker ') ||
sourceCode.includes('Dockerfile') ||
sourceCode.includes('docker-compose')) {
return 'docker';
}
if (sourceCode.includes('ansible-playbook') ||
sourceCode.includes('ansible-galaxy') ||
sourceCode.includes('ansible ')) {
return 'ansible';
}
if (sourceCode.includes('kubectl ') ||
sourceCode.includes('kubelet') ||
sourceCode.includes('kubernetes')) {
return 'kubernetes';
}
if (sourceCode.includes('aws ') ||
sourceCode.includes('AWS_') ||
sourceCode.includes('aws-cli')) {
return 'aws';
}
return null;
}
catch (error) {
logger.warn({ err: error }, 'Error detecting Bash/Shell framework');
return null;
}
}
}