public static LineOfCode Parse(Codebase owner, string line) { line = line.Trim(); var result = new LineOfCode(); result.Owner = owner; result.ID = line; result.CalledFrom = new List <LineOfCode>(); result.CallsTo = new List <LineOfCode>(); result.Leaks = new List <Backtrace>(); var match = Regex.Match(line, "(?<moduleName>.*)\\!(?<symbolName>.*)\\+(?<rest>(.*))?$|(?<moduleName>.*)$"); var moduleName = match.Groups["moduleName"].Value; var symbolName = match.Groups["symbolName"].Value; if (String.IsNullOrEmpty(symbolName)) { symbolName = moduleName; } var rest = match.Groups["rest"].Success ? match.Groups["rest"].Value : ""; result.Module = owner.Modules.FirstOrDefault(x => x.Name == moduleName); result.Scope = owner.GetScope(symbolName); result.Function = owner.GetFunction(symbolName); result.Scope.Lines.Add(result); // Add line to scope result.Function.Lines.AddOrGet(result); // Add line to function result.Module.Scopes.AddOrGet(result.Scope); // Add scope to module result.Module.Functions.AddOrGet(result.Function); // Add function to module result.Module.Lines.AddOrGet(result); // Add line to module match = Regex.Match(rest, ".* \\((?<fileName>.*), (?<lineNum>\\d*)\\)"); if (match.Success) // Is file,line present? { var filename = match.Groups["fileName"].Value; var lineNum = Convert.ToInt32(match.Groups["lineNum"].Value); result.LineNumber = lineNum; result.SourceFile = owner.GetFile(filename, result.Module); result.SourceFile.Lines.AddOrGet(result); // Add line to file result.Module.Files.AddOrGet(result.SourceFile); // Add file to module result.GeneratePreview(filename, lineNum); } return(result); }
// Get line if it already exists inside the codebase, // or add new if not found public LineOfCode GetLine(string line) { line = line.Trim(); var existingLine = Lines.FirstOrDefault(x => x.ID == line); if (existingLine != null) { return(existingLine); } else { var newLine = LineOfCode.Parse(this, line); Lines.Add(newLine); return(newLine); } }
public static Backtrace FromLines(Codebase owner, List <string> lines, int startLine, int endLine) { var header = lines[0]; var subHeader = lines[1]; var headerNumbers = Regex.Matches(header, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))") // first number must capture negative sign if exists. .Cast <Match>() .Select(x => x.Groups["number"].Value.Replace(" ", "")) .Select(x => Convert.ToInt32(x)) .ToList(); var subHeaderNumberMatches = Regex.Matches(subHeader, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))"); //var subHeaderNumbers = Regex.Matches(subHeader, "(?<number>^-\\s*\\d+)|(?<number>\\d+)( |\\))") // first number must capture negative sign if exists. var subHeaderNumbers = subHeaderNumberMatches .Cast <Match>() .Select(x => x.Groups["number"].Value.Replace(" ", "")) .Select(x => Convert.ToInt32(x)) .ToList(); var bytesDelta = headerNumbers[0]; var newBytes = headerNumbers[1]; var oldBytes = headerNumbers[2]; var countDelta = subHeaderNumbers[0]; var newCount = subHeaderNumbers[1]; var oldCount = subHeaderNumbers[2]; var result = new Backtrace { TotalLeak = bytesDelta, Count = countDelta, Owner = owner, Lines = new List <LineOfCode>(), StartLine = startLine, EndLine = endLine }; var justLines = lines.Skip(2).Where(x => x.Trim() != string.Empty).ToList(); LineOfCode prevLine = null; foreach (var lineStr in justLines) { var line = owner.GetLine(lineStr); line.Leaks.AddOrGet(result); // Add leak to line's leaks line.Function.Leaks.AddOrGet(result); // Add leak to line's function's leak line.Scope.Leaks.AddOrGet(result); // Add leak to line's scope's leak if (line.SourceFile != null) { line.SourceFile.Leaks.AddOrGet(result); // Add leak to line's file's leaks } line.Module.Leaks.AddOrGet(result); // Add leak to line's module's leaks result.Lines.Add(line); // Add line to leak // Connect and update calls to and called from if (prevLine != null) { line.CallsTo.AddOrGet(prevLine); // Line calls prevLine line.Function.CallsTo.AddOrGet(prevLine.Function); // Line's function calls prevLine's function line.Module.CallsTo.AddOrGet(prevLine.Module); // Line's module calls prevLine's module if (line.SourceFile != null && prevLine.SourceFile != null) { line.SourceFile.CallsTo.AddOrGet(prevLine.SourceFile); // Line's file calls prevLine's file prevLine.SourceFile.CalledFrom.AddOrGet(line.SourceFile); // PrevLine's file is called from line's file } prevLine.CalledFrom.AddOrGet(line); // PrevLine is called from line prevLine.Function.CalledFrom.AddOrGet(line.Function); // PrevLine's function is called from line's function prevLine.Module.CalledFrom.AddOrGet(line.Module); // PrevLine's module is called from line's module } prevLine = line; } return(result); }