190 lines
5.2 KiB
C#
Executable File
190 lines
5.2 KiB
C#
Executable File
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace MarketAlly.AIPlugin.Analysis.Plugins
|
|
{
|
|
public class CompilationManager
|
|
{
|
|
public CompilationManager()
|
|
{
|
|
}
|
|
|
|
public async Task<CompilationResult> ValidateCompilationAsync(string solutionPath)
|
|
{
|
|
var result = new CompilationResult
|
|
{
|
|
StartTime = DateTime.UtcNow,
|
|
SolutionPath = solutionPath
|
|
};
|
|
|
|
try
|
|
{
|
|
// Use dotnet build to validate compilation
|
|
var processInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "dotnet",
|
|
Arguments = $"build \"{solutionPath}\" --verbosity quiet --nologo",
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
};
|
|
|
|
using var process = Process.Start(processInfo);
|
|
if (process == null)
|
|
{
|
|
throw new InvalidOperationException("Failed to start dotnet build process");
|
|
}
|
|
|
|
var output = await process.StandardOutput.ReadToEndAsync();
|
|
var error = await process.StandardError.ReadToEndAsync();
|
|
await process.WaitForExitAsync();
|
|
|
|
result.ExitCode = process.ExitCode;
|
|
result.BuildOutput = output;
|
|
result.BuildErrors = error;
|
|
|
|
// Parse compilation results
|
|
result.Status = process.ExitCode == 0 ? CompilationStatus.Success : CompilationStatus.Failed;
|
|
|
|
// Use existing parsing logic from WarningsAnalysisPlugin
|
|
result.Warnings = ParseWarningsFromBuildOutput(output + error);
|
|
result.Errors = ParseErrorsFromBuildOutput(output + error);
|
|
|
|
result.ErrorCount = result.Errors.Count;
|
|
result.WarningCount = result.Warnings.Count;
|
|
|
|
// Adjust status based on warnings
|
|
if (result.Status == CompilationStatus.Success && result.WarningCount > 0)
|
|
{
|
|
result.Status = CompilationStatus.Warning;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result.Status = CompilationStatus.Failed;
|
|
result.ErrorMessage = ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
result.EndTime = DateTime.UtcNow;
|
|
result.Duration = result.EndTime - result.StartTime;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private List<CompilationDiagnostic> ParseWarningsFromBuildOutput(string buildOutput)
|
|
{
|
|
var warnings = new List<CompilationDiagnostic>();
|
|
var lines = buildOutput.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
if (line.Contains("warning", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var warning = TryParseDiagnosticLine(line.Trim(), "warning");
|
|
if (warning != null)
|
|
{
|
|
warnings.Add(warning);
|
|
}
|
|
}
|
|
}
|
|
|
|
return warnings;
|
|
}
|
|
|
|
private List<CompilationDiagnostic> ParseErrorsFromBuildOutput(string buildOutput)
|
|
{
|
|
var errors = new List<CompilationDiagnostic>();
|
|
var lines = buildOutput.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
if (line.Contains("error", StringComparison.OrdinalIgnoreCase) &&
|
|
!line.Contains("warning", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
var error = TryParseDiagnosticLine(line.Trim(), "error");
|
|
if (error != null)
|
|
{
|
|
errors.Add(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
private CompilationDiagnostic? TryParseDiagnosticLine(string line, string type)
|
|
{
|
|
var patterns = new[]
|
|
{
|
|
@"(.+?)\((\d+),(\d+)\):\s*warning\s+([A-Z]+\d+):\s*(.+)",
|
|
@"warning\s+([A-Z]+\d+):\s*(.+)\s*\[(.+?)\]"
|
|
};
|
|
|
|
foreach (var pattern in patterns)
|
|
{
|
|
var match = System.Text.RegularExpressions.Regex.Match(line, pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
|
if (match.Success)
|
|
{
|
|
if (match.Groups.Count >= 5 && !string.IsNullOrEmpty(match.Groups[1].Value))
|
|
{
|
|
return new CompilationDiagnostic
|
|
{
|
|
File = Path.GetFileName(match.Groups[1].Value),
|
|
Line = int.TryParse(match.Groups[2].Value, out var parsedLine) ? parsedLine : 0,
|
|
Column = int.TryParse(match.Groups[3].Value, out var parsedCol) ? parsedCol : 0,
|
|
Code = match.Groups[4].Value,
|
|
Message = match.Groups[5].Value.Trim(),
|
|
Type = "warning"
|
|
};
|
|
}
|
|
else if (match.Groups.Count >= 3)
|
|
{
|
|
return new CompilationDiagnostic
|
|
{
|
|
Code = match.Groups[1].Value,
|
|
Message = match.Groups[2].Value.Trim(),
|
|
File = match.Groups.Count > 3 ? Path.GetFileName(match.Groups[3].Value) : "Unknown",
|
|
Type = "warning"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class CompilationResult
|
|
{
|
|
public DateTime StartTime { get; set; }
|
|
public DateTime EndTime { get; set; }
|
|
public TimeSpan Duration { get; set; }
|
|
public string SolutionPath { get; set; } = string.Empty;
|
|
public CompilationStatus Status { get; set; }
|
|
public int ExitCode { get; set; }
|
|
public int ErrorCount { get; set; }
|
|
public int WarningCount { get; set; }
|
|
public int? PreviousErrorCount { get; set; }
|
|
public string BuildOutput { get; set; } = string.Empty;
|
|
public string BuildErrors { get; set; } = string.Empty;
|
|
public string ErrorMessage { get; set; } = string.Empty;
|
|
public List<CompilationDiagnostic> Errors { get; set; } = new();
|
|
public List<CompilationDiagnostic> Warnings { get; set; } = new();
|
|
}
|
|
|
|
public enum CompilationStatus
|
|
{
|
|
Success,
|
|
Warning,
|
|
Failed
|
|
}
|
|
}
|