Skip to main content
Glama
go.ts3.77 kB
/** * Go deep code analyzer using Go's native parser and AST */ import { spawn } from "child_process"; import * as path from "path"; import { CodeAnalyzer } from "../core/analyzer.js"; import { DeepAnalysis, FileAnalysis, AnalysisSummary } from "../core/types.js"; import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export class GoAnalyzer extends CodeAnalyzer { private goHelperPath: string; constructor(projectPath: string, files: string[]) { super(projectPath, files); // Use path relative to source directory this.goHelperPath = path.resolve( __dirname, "..", "..", "src", "analyzers", "helpers", "go_analyzer.go" ); } canAnalyze(filePath: string): boolean { const ext = path.extname(filePath).toLowerCase(); return ext === ".go"; } getLanguage(): string { return "go"; } async analyze(): Promise<DeepAnalysis> { const fileAnalyses: FileAnalysis[] = []; for (const file of this.files) { if (this.canAnalyze(file)) { const analysis = await this.analyzeFile(file); if (analysis) { fileAnalyses.push(analysis); } } } return { language: "go", files: fileAnalyses, summary: this.generateSummary(fileAnalyses), }; } async analyzeFile(filePath: string): Promise<FileAnalysis | null> { try { const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(this.projectPath, filePath); const result = await this.runGoAnalyzer(absolutePath); if (result.error) { console.error(`Error analyzing ${filePath}: ${result.error}`); return null; } return result as FileAnalysis; } catch (error) { console.error(`Error analyzing ${filePath}:`, error); return null; } } private runGoAnalyzer(filePath: string): Promise<any> { return new Promise((resolve, reject) => { const goRun = spawn("go", ["run", this.goHelperPath, filePath]); let stdout = ""; let stderr = ""; goRun.stdout.on("data", (data) => { stdout += data.toString(); }); goRun.stderr.on("data", (data) => { stderr += data.toString(); }); goRun.on("close", (code) => { if (code !== 0) { reject(new Error(`Go process exited with code ${code}: ${stderr}`)); return; } try { const result = JSON.parse(stdout); resolve(result); } catch (error) { reject(new Error(`Failed to parse Go analyzer output: ${error}`)); } }); goRun.on("error", (error) => { reject(new Error(`Failed to start Go process: ${error.message}`)); }); }); } private generateSummary(fileAnalyses: FileAnalysis[]): AnalysisSummary { const summary: AnalysisSummary = { totalFiles: fileAnalyses.length, totalClasses: 0, totalInterfaces: 0, totalFunctions: 0, totalEnums: 0, totalTypeAliases: 0, overallDocCoverage: 0, }; let totalSymbols = 0; let documentedSymbols = 0; fileAnalyses.forEach((file) => { summary.totalClasses += file.classes.length; summary.totalInterfaces += file.interfaces.length; summary.totalFunctions += file.functions.length; summary.totalEnums += file.enums.length; summary.totalTypeAliases += file.typeAliases.length; totalSymbols += file.documentation.totalSymbols; documentedSymbols += file.documentation.documentedSymbols; }); summary.overallDocCoverage = totalSymbols > 0 ? (documentedSymbols / totalSymbols) * 100 : 0; return summary; } }

Latest Blog Posts

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/LiL-Loco/documentation-mcp-server'

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