1062 lines
32 KiB
C#
Executable File
1062 lines
32 KiB
C#
Executable File
using global::MarketAlly.AIPlugin;
|
|
using global::MarketAlly.AIPlugin.Refactoring.Plugins;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using System.Text.Json;
|
|
|
|
namespace MarketAlly.AIPlugin.Refactoring.TestConsole;
|
|
|
|
public class EnhancedRefactoringTestService
|
|
{
|
|
private readonly AIPluginRegistry _pluginRegistry;
|
|
private readonly ILogger<EnhancedRefactoringTestService> _logger;
|
|
|
|
public EnhancedRefactoringTestService(AIPluginRegistry pluginRegistry, ILogger<EnhancedRefactoringTestService> logger)
|
|
{
|
|
_pluginRegistry = pluginRegistry;
|
|
_logger = logger;
|
|
SetupPlugins();
|
|
}
|
|
|
|
private void SetupPlugins()
|
|
{
|
|
_pluginRegistry.RegisterPlugin(new CodeAnalysisPlugin());
|
|
_pluginRegistry.RegisterPlugin(new EnhancedDocumentationGeneratorPlugin());
|
|
_pluginRegistry.RegisterPlugin(new CodeFormatterPlugin());
|
|
_pluginRegistry.RegisterPlugin(new NamingConventionPlugin());
|
|
_pluginRegistry.RegisterPlugin(new BatchRefactorPlugin());
|
|
_pluginRegistry.RegisterPlugin(new CodeRefactoringPlugin());
|
|
_pluginRegistry.RegisterPlugin(new ReadmeGeneratorPlugin());
|
|
_pluginRegistry.RegisterPlugin(new AIReadmeGeneratorPlugin());
|
|
|
|
_logger.LogInformation("Registered {Count} refactoring plugins including README generators",
|
|
_pluginRegistry.GetAllPlugins().Count);
|
|
}
|
|
|
|
public async Task CreateAdvancedSampleFiles()
|
|
{
|
|
Console.WriteLine("[INFO] Creating advanced sample files with refactoring opportunities...");
|
|
|
|
var sampleDirectory = Path.Combine(Directory.GetCurrentDirectory(), "advanced_samples");
|
|
Directory.CreateDirectory(sampleDirectory);
|
|
|
|
await CreateComplexClassForExtraction(sampleDirectory);
|
|
await CreateGodClassForSplitting(sampleDirectory);
|
|
await CreateDuplicateCodeSample(sampleDirectory);
|
|
await CreateLongParameterListSample(sampleDirectory);
|
|
|
|
Console.WriteLine($"[SUCCESS] Created advanced sample files in: {sampleDirectory}");
|
|
Console.WriteLine("Advanced sample files for refactoring:");
|
|
Console.WriteLine(" - ComplexCalculator.cs (needs method extraction)");
|
|
Console.WriteLine(" - UserManagementSystem.cs (god class needing splitting)");
|
|
Console.WriteLine(" - DuplicateLogic.cs (contains duplicate code blocks)");
|
|
Console.WriteLine(" - ParameterHeavyService.cs (needs parameter objects)");
|
|
}
|
|
|
|
private async Task CreateComplexCalculator(string directory)
|
|
{
|
|
var content = @"using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace AdvancedSamples
|
|
{
|
|
public class ComplexCalculator
|
|
{
|
|
// This method is too long and complex - perfect for method extraction
|
|
public double CalculateComplexFormula(double x, double y, double z, bool useAdvanced, string mode)
|
|
{
|
|
double result = 0;
|
|
|
|
// Step 1: Basic validation and preprocessing
|
|
if (x <= 0 || y <= 0 || z <= 0)
|
|
{
|
|
throw new ArgumentException(""All values must be positive"");
|
|
}
|
|
|
|
double normalizedX = x / 100.0;
|
|
double normalizedY = y / 100.0;
|
|
double normalizedZ = z / 100.0;
|
|
|
|
if (normalizedX > 1.0) normalizedX = 1.0;
|
|
if (normalizedY > 1.0) normalizedY = 1.0;
|
|
if (normalizedZ > 1.0) normalizedZ = 1.0;
|
|
|
|
// Step 2: Complex mathematical operations
|
|
double baseCalculation = 0;
|
|
if (mode == ""linear"")
|
|
{
|
|
baseCalculation = normalizedX * 2.5 + normalizedY * 1.8 + normalizedZ * 3.2;
|
|
baseCalculation = Math.Pow(baseCalculation, 1.2);
|
|
baseCalculation = baseCalculation * Math.PI / 4.0;
|
|
}
|
|
else if (mode == ""exponential"")
|
|
{
|
|
baseCalculation = Math.Exp(normalizedX * 0.1) + Math.Exp(normalizedY * 0.15) + Math.Exp(normalizedZ * 0.12);
|
|
baseCalculation = baseCalculation * Math.Log(x + y + z + 1);
|
|
baseCalculation = Math.Sqrt(baseCalculation);
|
|
}
|
|
else if (mode == ""trigonometric"")
|
|
{
|
|
baseCalculation = Math.Sin(normalizedX * Math.PI) * Math.Cos(normalizedY * Math.PI) * Math.Tan(normalizedZ * Math.PI / 4);
|
|
baseCalculation = Math.Abs(baseCalculation);
|
|
baseCalculation = baseCalculation * 100;
|
|
}
|
|
|
|
// Step 3: Advanced processing if enabled
|
|
if (useAdvanced)
|
|
{
|
|
double advancedFactor = 1.0;
|
|
|
|
// Complex conditional logic
|
|
if (baseCalculation > 50)
|
|
{
|
|
if (x > y && y > z)
|
|
{
|
|
advancedFactor = 1.25;
|
|
}
|
|
else if (x < y && y < z)
|
|
{
|
|
advancedFactor = 1.15;
|
|
}
|
|
else
|
|
{
|
|
advancedFactor = 1.05;
|
|
}
|
|
}
|
|
else if (baseCalculation > 25)
|
|
{
|
|
advancedFactor = 0.95;
|
|
}
|
|
else
|
|
{
|
|
advancedFactor = 0.85;
|
|
}
|
|
|
|
baseCalculation *= advancedFactor;
|
|
|
|
// Additional transformations
|
|
if (mode.Contains(""linear""))
|
|
{
|
|
baseCalculation += Math.Sqrt(x) + Math.Sqrt(y) + Math.Sqrt(z);
|
|
}
|
|
|
|
baseCalculation = Math.Round(baseCalculation, 4);
|
|
}
|
|
|
|
// Step 4: Final result processing
|
|
result = baseCalculation;
|
|
|
|
if (result < 0) result = 0;
|
|
if (result > 1000) result = 1000;
|
|
|
|
// Log the calculation for debugging
|
|
Console.WriteLine($""Calculated result: {result} for inputs ({x}, {y}, {z}) with mode '{mode}' and advanced={useAdvanced}"");
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool ValidateInputRange(double value, double min, double max, string paramName)
|
|
{
|
|
if (value < min)
|
|
{
|
|
Console.WriteLine($""Warning: {paramName} value {value} is below minimum {min}"");
|
|
return false;
|
|
}
|
|
|
|
if (value > max)
|
|
{
|
|
Console.WriteLine($""Warning: {paramName} value {value} is above maximum {max}"");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}";
|
|
|
|
await File.WriteAllTextAsync(Path.Combine(directory, "ComplexCalculator.cs"), content);
|
|
}
|
|
|
|
private async Task CreateGodClassForSplitting(string directory)
|
|
{
|
|
var content = @"using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace AdvancedSamples
|
|
{
|
|
// This is a ""God Class"" that does too many things - needs splitting
|
|
public class UserManagementSystem
|
|
{
|
|
private List<User> _users = new List<User>();
|
|
private readonly HttpClient _httpClient = new HttpClient();
|
|
private readonly string _logFile = ""user_operations.log"";
|
|
|
|
// User CRUD Operations (should be in UserRepository)
|
|
public void CreateUser(string name, string email, int age)
|
|
{
|
|
var user = new User { Id = Guid.NewGuid(), Name = name, Email = email, Age = age };
|
|
_users.Add(user);
|
|
LogOperation($""User created: {user.Id}"");
|
|
}
|
|
|
|
public User GetUser(Guid id)
|
|
{
|
|
var user = _users.Find(u => u.Id == id);
|
|
LogOperation($""User retrieved: {id}"");
|
|
return user;
|
|
}
|
|
|
|
public void UpdateUser(Guid id, string name, string email, int age)
|
|
{
|
|
var user = _users.Find(u => u.Id == id);
|
|
if (user != null)
|
|
{
|
|
user.Name = name;
|
|
user.Email = email;
|
|
user.Age = age;
|
|
LogOperation($""User updated: {id}"");
|
|
}
|
|
}
|
|
|
|
public void DeleteUser(Guid id)
|
|
{
|
|
var user = _users.Find(u => u.Id == id);
|
|
if (user != null)
|
|
{
|
|
_users.Remove(user);
|
|
LogOperation($""User deleted: {id}"");
|
|
}
|
|
}
|
|
|
|
// Email Operations (should be in EmailService)
|
|
public async Task SendWelcomeEmail(Guid userId)
|
|
{
|
|
var user = GetUser(userId);
|
|
if (user != null)
|
|
{
|
|
var emailContent = $""Welcome {user.Name}! Your account has been created."";
|
|
await SendEmail(user.Email, ""Welcome"", emailContent);
|
|
LogOperation($""Welcome email sent to: {user.Email}"");
|
|
}
|
|
}
|
|
|
|
public async Task SendPasswordResetEmail(Guid userId)
|
|
{
|
|
var user = GetUser(userId);
|
|
if (user != null)
|
|
{
|
|
var resetToken = GenerateResetToken();
|
|
var emailContent = $""Click here to reset your password: /reset?token={resetToken}"";
|
|
await SendEmail(user.Email, ""Password Reset"", emailContent);
|
|
LogOperation($""Password reset email sent to: {user.Email}"");
|
|
}
|
|
}
|
|
|
|
private async Task SendEmail(string to, string subject, string body)
|
|
{
|
|
// Simulate email sending
|
|
await Task.Delay(100);
|
|
Console.WriteLine($""EMAIL: To={to}, Subject={subject}, Body={body}"");
|
|
}
|
|
|
|
// Logging Operations (should be in LoggingService)
|
|
public void LogOperation(string message)
|
|
{
|
|
var logEntry = $""[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}"";
|
|
File.AppendAllText(_logFile, logEntry + Environment.NewLine);
|
|
}
|
|
|
|
public string[] GetRecentLogs(int count)
|
|
{
|
|
if (!File.Exists(_logFile)) return new string[0];
|
|
|
|
var lines = File.ReadAllLines(_logFile);
|
|
if (lines.Length <= count)
|
|
return lines;
|
|
|
|
var recentLines = new string[count];
|
|
Array.Copy(lines, lines.Length - count, recentLines, 0, count);
|
|
return recentLines;
|
|
}
|
|
|
|
public void ClearLogs()
|
|
{
|
|
if (File.Exists(_logFile))
|
|
{
|
|
File.Delete(_logFile);
|
|
}
|
|
}
|
|
|
|
// Validation Operations (should be in ValidationService)
|
|
public bool ValidateEmail(string email)
|
|
{
|
|
if (string.IsNullOrEmpty(email)) return false;
|
|
if (!email.Contains(""@"")) return false;
|
|
if (!email.Contains(""."")) return false;
|
|
return true;
|
|
}
|
|
|
|
public bool ValidateAge(int age)
|
|
{
|
|
return age >= 13 && age <= 120;
|
|
}
|
|
|
|
public bool ValidateName(string name)
|
|
{
|
|
if (string.IsNullOrEmpty(name)) return false;
|
|
if (name.Length < 2) return false;
|
|
if (name.Length > 50) return false;
|
|
return true;
|
|
}
|
|
|
|
// Utility Operations (should be in separate utility classes)
|
|
private string GenerateResetToken()
|
|
{
|
|
return Guid.NewGuid().ToString(""N"").Substring(0, 16);
|
|
}
|
|
|
|
public void ExportUsersToFile(string fileName)
|
|
{
|
|
var lines = new List<string>();
|
|
lines.Add(""Id,Name,Email,Age"");
|
|
|
|
foreach (var user in _users)
|
|
{
|
|
lines.Add($""{user.Id},{user.Name},{user.Email},{user.Age}"");
|
|
}
|
|
|
|
File.WriteAllLines(fileName, lines);
|
|
LogOperation($""Users exported to: {fileName}"");
|
|
}
|
|
|
|
public void ImportUsersFromFile(string fileName)
|
|
{
|
|
if (!File.Exists(fileName)) return;
|
|
|
|
var lines = File.ReadAllLines(fileName);
|
|
for (int i = 1; i < lines.Length; i++) // Skip header
|
|
{
|
|
var parts = lines[i].Split(',');
|
|
if (parts.Length == 4)
|
|
{
|
|
var user = new User
|
|
{
|
|
Id = Guid.Parse(parts[0]),
|
|
Name = parts[1],
|
|
Email = parts[2],
|
|
Age = int.Parse(parts[3])
|
|
};
|
|
_users.Add(user);
|
|
}
|
|
}
|
|
LogOperation($""Users imported from: {fileName}"");
|
|
}
|
|
}
|
|
|
|
public class User
|
|
{
|
|
public Guid Id { get; set; }
|
|
public string Name { get; set; }
|
|
public string Email { get; set; }
|
|
public int Age { get; set; }
|
|
}
|
|
}";
|
|
|
|
await File.WriteAllTextAsync(Path.Combine(directory, "UserManagementSystem.cs"), content);
|
|
}
|
|
|
|
private async Task CreateDuplicateCodeSample(string directory)
|
|
{
|
|
var content = @"using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace AdvancedSamples
|
|
{
|
|
public class DuplicateLogic
|
|
{
|
|
private const string ERROR_LOG_FILE = ""errors.log"";
|
|
private const string INFO_LOG_FILE = ""info.log"";
|
|
private const string DEBUG_LOG_FILE = ""debug.log"";
|
|
|
|
// These methods have duplicate logging logic
|
|
public void LogError(string message)
|
|
{
|
|
var timestamp = DateTime.Now.ToString(""yyyy-MM-dd HH:mm:ss"");
|
|
var logEntry = $""[{timestamp}] ERROR: {message}"";
|
|
|
|
try
|
|
{
|
|
if (!File.Exists(ERROR_LOG_FILE))
|
|
{
|
|
File.Create(ERROR_LOG_FILE).Close();
|
|
}
|
|
|
|
File.AppendAllText(ERROR_LOG_FILE, logEntry + Environment.NewLine);
|
|
Console.WriteLine($""Logged error: {message}"");
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
Console.WriteLine($""Failed to log error: {ex.Message}"");
|
|
}
|
|
}
|
|
|
|
public void LogInfo(string message)
|
|
{
|
|
var timestamp = DateTime.Now.ToString(""yyyy-MM-dd HH:mm:ss"");
|
|
var logEntry = $""[{timestamp}] INFO: {message}"";
|
|
|
|
try
|
|
{
|
|
if (!File.Exists(INFO_LOG_FILE))
|
|
{
|
|
File.Create(INFO_LOG_FILE).Close();
|
|
}
|
|
|
|
File.AppendAllText(INFO_LOG_FILE, logEntry + Environment.NewLine);
|
|
Console.WriteLine($""Logged info: {message}"");
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
Console.WriteLine($""Failed to log info: {ex.Message}"");
|
|
}
|
|
}
|
|
|
|
public void LogDebug(string message)
|
|
{
|
|
var timestamp = DateTime.Now.ToString(""yyyy-MM-dd HH:mm:ss"");
|
|
var logEntry = $""[{timestamp}] DEBUG: {message}"";
|
|
|
|
try
|
|
{
|
|
if (!File.Exists(DEBUG_LOG_FILE))
|
|
{
|
|
File.Create(DEBUG_LOG_FILE).Close();
|
|
}
|
|
|
|
File.AppendAllText(DEBUG_LOG_FILE, logEntry + Environment.NewLine);
|
|
Console.WriteLine($""Logged debug: {message}"");
|
|
}
|
|
catch (IOException ex)
|
|
{
|
|
Console.WriteLine($""Failed to log debug: {ex.Message}"");
|
|
}
|
|
}
|
|
|
|
// These methods have duplicate validation logic
|
|
public bool ValidateUserInput(string name, string email, int age)
|
|
{
|
|
if (string.IsNullOrEmpty(name))
|
|
{
|
|
LogError(""Name cannot be empty"");
|
|
return false;
|
|
}
|
|
|
|
if (name.Length < 2)
|
|
{
|
|
LogError(""Name must be at least 2 characters"");
|
|
return false;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(email))
|
|
{
|
|
LogError(""Email cannot be empty"");
|
|
return false;
|
|
}
|
|
|
|
if (!email.Contains(""@""))
|
|
{
|
|
LogError(""Email must contain @ symbol"");
|
|
return false;
|
|
}
|
|
|
|
if (age < 0 || age > 150)
|
|
{
|
|
LogError(""Age must be between 0 and 150"");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool ValidateProductInput(string productName, string description, decimal price)
|
|
{
|
|
if (string.IsNullOrEmpty(productName))
|
|
{
|
|
LogError(""Product name cannot be empty"");
|
|
return false;
|
|
}
|
|
|
|
if (productName.Length < 2)
|
|
{
|
|
LogError(""Product name must be at least 2 characters"");
|
|
return false;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(description))
|
|
{
|
|
LogError(""Description cannot be empty"");
|
|
return false;
|
|
}
|
|
|
|
if (description.Length < 10)
|
|
{
|
|
LogError(""Description must be at least 10 characters"");
|
|
return false;
|
|
}
|
|
|
|
if (price < 0)
|
|
{
|
|
LogError(""Price cannot be negative"");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Duplicate string processing logic
|
|
public string FormatUserDisplayName(string firstName, string lastName)
|
|
{
|
|
if (string.IsNullOrEmpty(firstName)) firstName = ""Unknown"";
|
|
if (string.IsNullOrEmpty(lastName)) lastName = ""User"";
|
|
|
|
firstName = firstName.Trim();
|
|
lastName = lastName.Trim();
|
|
|
|
firstName = char.ToUpper(firstName[0]) + firstName.Substring(1).ToLower();
|
|
lastName = char.ToUpper(lastName[0]) + lastName.Substring(1).ToLower();
|
|
|
|
return $""{firstName} {lastName}"";
|
|
}
|
|
|
|
public string FormatProductDisplayName(string productName, string category)
|
|
{
|
|
if (string.IsNullOrEmpty(productName)) productName = ""Unknown"";
|
|
if (string.IsNullOrEmpty(category)) category = ""Product"";
|
|
|
|
productName = productName.Trim();
|
|
category = category.Trim();
|
|
|
|
productName = char.ToUpper(productName[0]) + productName.Substring(1).ToLower();
|
|
category = char.ToUpper(category[0]) + category.Substring(1).ToLower();
|
|
|
|
return $""{productName} ({category})"";
|
|
}
|
|
}
|
|
}";
|
|
|
|
await File.WriteAllTextAsync(Path.Combine(directory, "DuplicateLogic.cs"), content);
|
|
}
|
|
|
|
private async Task CreateLongParameterListSample(string directory)
|
|
{
|
|
var content = @"using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AdvancedSamples
|
|
{
|
|
public class ParameterHeavyService
|
|
{
|
|
// This method has too many parameters - needs parameter object
|
|
public void CreateOrder(
|
|
string customerName,
|
|
string customerEmail,
|
|
string customerPhone,
|
|
string customerAddress,
|
|
string customerCity,
|
|
string customerState,
|
|
string customerZip,
|
|
string productName,
|
|
string productSku,
|
|
decimal productPrice,
|
|
int quantity,
|
|
decimal discountPercentage,
|
|
string shippingMethod,
|
|
string shippingAddress,
|
|
string shippingCity,
|
|
string shippingState,
|
|
string shippingZip,
|
|
bool expeditedShipping,
|
|
string paymentMethod,
|
|
string creditCardNumber,
|
|
string creditCardExpiry,
|
|
string creditCardCvv,
|
|
string specialInstructions)
|
|
{
|
|
// Order creation logic...
|
|
Console.WriteLine(""Creating order with many parameters..."");
|
|
}
|
|
|
|
// Another method with too many parameters
|
|
public void ProcessPayment(
|
|
decimal amount,
|
|
string currency,
|
|
string paymentMethod,
|
|
string cardNumber,
|
|
string cardExpiry,
|
|
string cardCvv,
|
|
string cardHolderName,
|
|
string billingAddress,
|
|
string billingCity,
|
|
string billingState,
|
|
string billingZip,
|
|
string billingCountry,
|
|
bool saveCard,
|
|
string merchantId,
|
|
string transactionId,
|
|
string description)
|
|
{
|
|
// Payment processing logic...
|
|
Console.WriteLine(""Processing payment with many parameters..."");
|
|
}
|
|
|
|
// Configuration method with many boolean flags
|
|
public void ConfigureSystem(
|
|
bool enableLogging,
|
|
bool enableCaching,
|
|
bool enableCompression,
|
|
bool enableSsl,
|
|
bool enableAuthentication,
|
|
bool enableAuthorization,
|
|
bool enableRateLimiting,
|
|
bool enableMonitoring,
|
|
bool enableBackups,
|
|
bool enableEncryption,
|
|
string logLevel,
|
|
int cacheTimeout,
|
|
int connectionTimeout,
|
|
int maxRetries,
|
|
string encryptionKey)
|
|
{
|
|
// System configuration logic...
|
|
Console.WriteLine(""Configuring system with many parameters..."");
|
|
}
|
|
|
|
// Report generation with many filter parameters
|
|
public void GenerateReport(
|
|
DateTime startDate,
|
|
DateTime endDate,
|
|
string reportType,
|
|
string customerId,
|
|
string productCategory,
|
|
string region,
|
|
decimal minAmount,
|
|
decimal maxAmount,
|
|
string status,
|
|
bool includeDetails,
|
|
bool includeCharts,
|
|
bool includeStatistics,
|
|
string outputFormat,
|
|
string emailTo,
|
|
bool scheduleRecurring,
|
|
int recurringInterval)
|
|
{
|
|
// Report generation logic...
|
|
Console.WriteLine(""Generating report with many parameters..."");
|
|
}
|
|
}
|
|
}";
|
|
|
|
await File.WriteAllTextAsync(Path.Combine(directory, "ParameterHeavyService.cs"), content);
|
|
}
|
|
|
|
public async Task TestActualRefactoring(string filePath, string operations, bool apply)
|
|
{
|
|
Console.WriteLine($"[REFACTOR TEST] Running actual code refactoring on: {Path.GetFileName(filePath)}");
|
|
Console.WriteLine($"[INFO] Operations: {operations}, Apply: {apply}");
|
|
Console.WriteLine(new string('=', 80));
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["filePath"] = filePath,
|
|
["operations"] = operations,
|
|
["applyChanges"] = apply,
|
|
["maxMethodLength"] = 25,
|
|
["maxClassSize"] = 300,
|
|
["minComplexityForExtraction"] = 6
|
|
};
|
|
|
|
var result = await _pluginRegistry.CallFunctionAsync("CodeRefactoring", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine("[SUCCESS] Code refactoring completed!");
|
|
DisplayRefactoringResults(result.Data);
|
|
|
|
// Show before/after comparison if changes were applied
|
|
if (apply)
|
|
{
|
|
Console.WriteLine("\n[CHANGES APPLIED] File has been modified. Check the backup file for original version.");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("\n[PREVIEW MODE] No changes applied to file. Use --apply to make changes.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"[ERROR] Refactoring failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[ERROR] Test failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task PreviewReadmeAsync(string projectPath, string projectType)
|
|
{
|
|
Console.WriteLine($"[PREVIEW] README for: {projectPath}");
|
|
Console.WriteLine(new string('=', 60));
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["projectType"] = projectType,
|
|
["applyChanges"] = false
|
|
};
|
|
|
|
var result = await _pluginRegistry.CallFunctionAsync("ReadmeGenerator", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine("[SUCCESS] README preview generated!");
|
|
DisplayReadmeResults(result.Data);
|
|
|
|
// Show preview content
|
|
var resultJson = JsonSerializer.Serialize(result.Data, new JsonSerializerOptions { WriteIndented = true });
|
|
var resultElement = JsonSerializer.Deserialize<JsonElement>(resultJson);
|
|
|
|
if (resultElement.TryGetProperty("PreviewContent", out var previewContent))
|
|
{
|
|
Console.WriteLine("\n[PREVIEW CONTENT]");
|
|
Console.WriteLine(new string('-', 40));
|
|
Console.WriteLine(previewContent.GetString());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"[ERROR] Preview failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[ERROR] Preview failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task GenerateAIReadmeAsync(string projectPath, bool apply)
|
|
{
|
|
Console.WriteLine($"[AI README] Generating AI-enhanced README for: {projectPath}");
|
|
Console.WriteLine($"[INFO] Apply: {apply}");
|
|
Console.WriteLine(new string('=', 60));
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["projectType"] = "auto",
|
|
["enableAIEnhancement"] = true,
|
|
["aiGeneratedExamples"] = true,
|
|
["aiEnhancedApiDocs"] = true,
|
|
["applyChanges"] = apply
|
|
};
|
|
|
|
var result = await _pluginRegistry.CallFunctionAsync("AIReadmeGenerator", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine("[SUCCESS] AI README generation completed!");
|
|
DisplayReadmeResults(result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"[ERROR] AI README generation failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[ERROR] AI README test failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public async Task TestReadmeGeneratorAsync()
|
|
{
|
|
Console.WriteLine("[TEST] Testing README Generator on current project");
|
|
Console.WriteLine(new string('=', 60));
|
|
|
|
// Get current project directory
|
|
var currentDir = Directory.GetCurrentDirectory();
|
|
var projectPath = FindProjectDirectory(currentDir);
|
|
|
|
if (projectPath == null)
|
|
{
|
|
Console.WriteLine("[ERROR] Could not find project file in current directory");
|
|
return;
|
|
}
|
|
|
|
Console.WriteLine($"[INFO] Found project at: {projectPath}");
|
|
await GenerateReadmeAsync(projectPath, "auto", false);
|
|
}
|
|
|
|
public async Task GenerateReadmeAsync(string projectPath, string projectType, bool apply)
|
|
{
|
|
Console.WriteLine($"[README] Generating README for: {projectPath}");
|
|
Console.WriteLine($"[INFO] Project type: {projectType}, Apply: {apply}");
|
|
Console.WriteLine(new string('=', 60));
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["projectType"] = projectType,
|
|
["includeApiDocs"] = true,
|
|
["includeArchitecture"] = true,
|
|
["includeSetup"] = true,
|
|
["includeExamples"] = true,
|
|
["applyChanges"] = apply
|
|
};
|
|
|
|
var result = await _pluginRegistry.CallFunctionAsync("ReadmeGenerator", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine("[SUCCESS] README generation completed!");
|
|
DisplayReadmeResults(result.Data);
|
|
|
|
// Show preview if not applying
|
|
if (!apply)
|
|
{
|
|
var resultJson = JsonSerializer.Serialize(result.Data, new JsonSerializerOptions { WriteIndented = true });
|
|
var resultElement = JsonSerializer.Deserialize<JsonElement>(resultJson);
|
|
|
|
if (resultElement.TryGetProperty("PreviewContent", out var previewContent))
|
|
{
|
|
Console.WriteLine("\n[PREVIEW CONTENT - First 500 chars]");
|
|
Console.WriteLine(new string('-', 40));
|
|
var content = previewContent.GetString();
|
|
Console.WriteLine(content.Length > 500 ? content.Substring(0, 500) + "..." : content);
|
|
Console.WriteLine(new string('-', 40));
|
|
Console.WriteLine($"Full content length: {content.Length} characters");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"[ERROR] README generation failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[ERROR] Test failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private string FindProjectDirectory(string startPath)
|
|
{
|
|
var currentDir = new DirectoryInfo(startPath);
|
|
|
|
while (currentDir != null)
|
|
{
|
|
// Look for .csproj files
|
|
var projectFiles = currentDir.GetFiles("*.csproj");
|
|
if (projectFiles.Any())
|
|
{
|
|
return currentDir.FullName;
|
|
}
|
|
|
|
// Look for .sln files
|
|
var solutionFiles = currentDir.GetFiles("*.sln");
|
|
if (solutionFiles.Any())
|
|
{
|
|
return currentDir.FullName;
|
|
}
|
|
|
|
currentDir = currentDir.Parent;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void DisplayReadmeResults(object data)
|
|
{
|
|
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
|
|
var resultElement = JsonSerializer.Deserialize<JsonElement>(json);
|
|
|
|
Console.WriteLine("\n[RESULTS]");
|
|
DisplayJsonProperty(resultElement, "Message");
|
|
DisplayJsonProperty(resultElement, "ProjectType");
|
|
DisplayJsonProperty(resultElement, "FilesAnalyzed");
|
|
DisplayJsonProperty(resultElement, "ContentLength");
|
|
DisplayJsonProperty(resultElement, "ChangesApplied");
|
|
|
|
if (resultElement.TryGetProperty("ReadmePath", out var readmePath))
|
|
{
|
|
Console.WriteLine($" README saved to: {readmePath.GetString()}");
|
|
}
|
|
}
|
|
|
|
public async Task TestCompleteRefactoringWorkflow()
|
|
{
|
|
Console.WriteLine("[WORKFLOW TEST] Running complete refactoring workflow...");
|
|
Console.WriteLine(new string('=', 80));
|
|
|
|
// Create advanced samples
|
|
await CreateAdvancedSampleFiles();
|
|
Console.WriteLine();
|
|
|
|
var advancedDirectory = Path.Combine(Directory.GetCurrentDirectory(), "advanced_samples");
|
|
var testFiles = new[]
|
|
{
|
|
("ComplexCalculator.cs", "extract-methods,simplify-conditionals"),
|
|
("UserManagementSystem.cs", "split-classes,extract-methods"),
|
|
("DuplicateLogic.cs", "remove-duplicates,extract-methods"),
|
|
("ParameterHeavyService.cs", "introduce-parameter-objects")
|
|
};
|
|
|
|
foreach (var (fileName, operations) in testFiles)
|
|
{
|
|
var filePath = Path.Combine(advancedDirectory, fileName);
|
|
|
|
Console.WriteLine($"\n[STEP 1] Analyzing {fileName}...");
|
|
await TestCodeAnalysisOnFile(filePath);
|
|
|
|
Console.WriteLine($"\n[STEP 2] Refactoring {fileName}...");
|
|
await TestActualRefactoring(filePath, operations, false); // Preview first
|
|
|
|
Console.WriteLine(new string('-', 40));
|
|
}
|
|
|
|
Console.WriteLine("\n[SUCCESS] Complete refactoring workflow test completed!");
|
|
Console.WriteLine("\nTo apply the refactoring changes, run:");
|
|
Console.WriteLine(" test-refactor --file <filename> --operations <ops> --apply");
|
|
}
|
|
|
|
public async Task TestCodeAnalysisOnFile(string filePath)
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["path"] = filePath,
|
|
["analysisDepth"] = "detailed",
|
|
["includeComplexity"] = true,
|
|
["includeCodeSmells"] = true,
|
|
["includeSuggestions"] = true
|
|
};
|
|
|
|
var result = await _pluginRegistry.CallFunctionAsync("CodeAnalysis", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
var json = JsonSerializer.Serialize(result.Data, new JsonSerializerOptions { WriteIndented = true });
|
|
var analysisData = JsonSerializer.Deserialize<JsonElement>(json);
|
|
|
|
if (analysisData.TryGetProperty("Summary", out var summary))
|
|
{
|
|
DisplayJsonProperty(summary, "QualityScore");
|
|
DisplayJsonProperty(summary, "AverageComplexity");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DisplayRefactoringResults(object data)
|
|
{
|
|
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
|
|
var refactorData = JsonSerializer.Deserialize<JsonElement>(json);
|
|
|
|
DisplayJsonProperty(refactorData, "Message");
|
|
|
|
if (refactorData.TryGetProperty("Summary", out var summary))
|
|
{
|
|
Console.WriteLine("\n[REFACTORING SUMMARY]");
|
|
DisplayJsonProperty(summary, "TotalOperations");
|
|
DisplayJsonProperty(summary, "SuccessfulOperations");
|
|
DisplayJsonProperty(summary, "MethodsExtracted");
|
|
DisplayJsonProperty(summary, "ClassesSplit");
|
|
DisplayJsonProperty(summary, "ConditionalsSimplified");
|
|
DisplayJsonProperty(summary, "DuplicatesFound");
|
|
DisplayJsonProperty(summary, "ParameterObjectOpportunities");
|
|
}
|
|
|
|
if (refactorData.TryGetProperty("DetailedResult", out var detailed))
|
|
{
|
|
if (detailed.TryGetProperty("Operations", out var operations) && operations.ValueKind == JsonValueKind.Array)
|
|
{
|
|
Console.WriteLine("\n[DETAILED OPERATIONS]");
|
|
foreach (var operation in operations.EnumerateArray())
|
|
{
|
|
if (operation.TryGetProperty("Type", out var type) &&
|
|
operation.TryGetProperty("Success", out var success) &&
|
|
operation.TryGetProperty("Message", out var message))
|
|
{
|
|
var status = success.GetBoolean() ? "✓" : "✗";
|
|
Console.WriteLine($" {status} {type.GetString()}: {message.GetString()}");
|
|
|
|
// Show extracted methods
|
|
if (operation.TryGetProperty("ExtractedMethods", out var methods) && methods.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var method in methods.EnumerateArray())
|
|
{
|
|
if (method.TryGetProperty("OriginalMethodName", out var orig) &&
|
|
method.TryGetProperty("ExtractedMethodName", out var extracted) &&
|
|
method.TryGetProperty("LinesExtracted", out var lines))
|
|
{
|
|
Console.WriteLine($" → Extracted {extracted.GetString()} from {orig.GetString()} ({lines.GetInt32()} lines)");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show duplicate findings
|
|
if (operation.TryGetProperty("DuplicatesRemoved", out var duplicates) && duplicates.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var duplicate in duplicates.EnumerateArray())
|
|
{
|
|
Console.WriteLine($" → {duplicate.GetString()}");
|
|
}
|
|
}
|
|
|
|
// Show parameter object opportunities
|
|
if (operation.TryGetProperty("ParameterObjects", out var paramObjs) && paramObjs.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var paramObj in paramObjs.EnumerateArray())
|
|
{
|
|
Console.WriteLine($" → {paramObj.GetString()}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DisplayJsonProperty(JsonElement element, string propertyName)
|
|
{
|
|
if (element.TryGetProperty(propertyName, out var property))
|
|
{
|
|
var value = property.ValueKind switch
|
|
{
|
|
JsonValueKind.String => property.GetString(),
|
|
JsonValueKind.Number => property.GetDouble().ToString("F2"),
|
|
JsonValueKind.True => "True",
|
|
JsonValueKind.False => "False",
|
|
_ => property.ToString()
|
|
};
|
|
Console.WriteLine($" {propertyName}: {value}");
|
|
}
|
|
}
|
|
|
|
private async Task CreateComplexClassForExtraction(string directory)
|
|
{
|
|
await CreateComplexCalculator(directory);
|
|
}
|
|
} |