using CodeBase.Models; using CodeBase.Orchestrators; using CodeBase.Services; using Google.Protobuf; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace CodeBase.Parsers { public class ScipParser(ScipOrchestrator scipOrchestrator) { public async Task> ParseProjectAsync(string projectRootPath, string language, string name) { var scipFilePath = Path.Combine(projectRootPath, "index.scip"); if (!File.Exists(scipFilePath)) { await scipOrchestrator.GenerateScipAsync(projectRootPath, language); } var filter = new UniversalFileFilter(); using var stream = File.OpenRead(scipFilePath); var scipIndex = Scip.Index.Parser.ParseFrom(stream); var extractedChunks = new List(); foreach (var document in scipIndex.Documents) { if (!filter.IsValidCodeFile(document.RelativePath)) continue; var absoluteFilePath = Path.Combine(projectRootPath, document.RelativePath); if (!File.Exists(absoluteFilePath)) continue; var fileLines = await File.ReadAllLinesAsync(absoluteFilePath); var declarations = document.Occurrences.Where(o => (o.SymbolRoles & 1) == 1); foreach (var occ in declarations) { int startLine = occ.Range[0]; int endLine = occ.Range.Count == 3 ? occ.Range[0] : occ.Range[2]; if (startLine < 0 || endLine >= fileLines.Length) continue; var codeSnippet = string.Join( Environment.NewLine, fileLines.Skip(startLine).Take(endLine - startLine + 1) ); // Возвращаем чанки пока БЕЗ векторов extractedChunks.Add(new CodeChunk { Id = occ.Symbol, EntityName = ExtractSimpleName(occ.Symbol), FilePath = document.RelativePath, Content = codeSnippet, Language = document.Language, ProjectName = name }); } } return extractedChunks; } private string ExtractSimpleName(string scipSymbol) { if (string.IsNullOrEmpty(scipSymbol)) return "Unknown"; var parts = scipSymbol.Split(new[] { '#', '.', '(', ')' }, StringSplitOptions.RemoveEmptyEntries); return parts.LastOrDefault() ?? scipSymbol; } } }