1326 lines
39 KiB
C#
Executable File
1326 lines
39 KiB
C#
Executable File
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
using System.Text.Json;
|
|
using Microsoft.Extensions.Logging;
|
|
using MarketAlly.AIPlugin;
|
|
using MarketAlly.AIPlugin.Analysis.Plugins;
|
|
|
|
namespace MarketAlly.AIPlugin.Analysis.TestConsole
|
|
{
|
|
class Program
|
|
{
|
|
private static readonly ILoggerFactory _loggerFactory = LoggerFactory.Create(builder =>
|
|
builder.AddConsole().SetMinimumLevel(LogLevel.Information));
|
|
private static readonly ILogger<Program> _logger = _loggerFactory.CreateLogger<Program>();
|
|
|
|
static async Task Main(string[] args)
|
|
{
|
|
Console.WriteLine("🚀 MarketAlly AI Plugin Analysis Test Console");
|
|
Console.WriteLine("==============================================");
|
|
|
|
try
|
|
{
|
|
// Initialize plugin registry with correct logger type
|
|
var registryLogger = _loggerFactory.CreateLogger<AIPluginRegistry>();
|
|
var registry = new AIPluginRegistry(registryLogger);
|
|
|
|
// Register all Analysis plugins
|
|
RegisterAnalysisPlugins(registry);
|
|
|
|
// Show menu options
|
|
await ShowMainMenu(registry);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"❌ Error during analysis: {ex.Message}");
|
|
_logger.LogError(ex, "Analysis failed");
|
|
}
|
|
finally
|
|
{
|
|
_loggerFactory?.Dispose();
|
|
}
|
|
|
|
Console.WriteLine();
|
|
Console.WriteLine("Press any key to exit...");
|
|
Console.ReadKey();
|
|
}
|
|
|
|
private static async Task ShowMainMenu(AIPluginRegistry registry)
|
|
{
|
|
while (true)
|
|
{
|
|
Console.WriteLine();
|
|
Console.WriteLine("📋 Analysis Options:");
|
|
Console.WriteLine("1. 📁 Analyze C# Project (Full Analysis Suite)");
|
|
Console.WriteLine("2. 🗄️ Analyze SQLite Database Schema");
|
|
Console.WriteLine("3. 🔍 Run Individual Analysis Plugin");
|
|
Console.WriteLine("4. 📊 Generate Sample Database for Testing");
|
|
Console.WriteLine("0. ❌ Exit");
|
|
Console.WriteLine();
|
|
Console.Write("Select an option (0-4): ");
|
|
|
|
var choice = Console.ReadLine();
|
|
|
|
switch (choice)
|
|
{
|
|
case "1":
|
|
await RunProjectAnalysis(registry);
|
|
break;
|
|
case "2":
|
|
await RunDatabaseAnalysis(registry);
|
|
break;
|
|
case "3":
|
|
await RunIndividualAnalysis(registry);
|
|
break;
|
|
case "4":
|
|
await GenerateSampleDatabase();
|
|
break;
|
|
case "0":
|
|
return;
|
|
default:
|
|
Console.WriteLine("❌ Invalid option. Please try again.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static async Task RunProjectAnalysis(AIPluginRegistry registry)
|
|
{
|
|
var testProjectPath = GetTestProjectPath();
|
|
|
|
if (string.IsNullOrEmpty(testProjectPath))
|
|
{
|
|
Console.WriteLine("❌ No test project path provided. Please specify a C# project directory.");
|
|
return;
|
|
}
|
|
|
|
Console.WriteLine($"📁 Analyzing project: {testProjectPath}");
|
|
Console.WriteLine();
|
|
|
|
// Run all analysis plugins
|
|
await RunComplexityAnalysis(registry, testProjectPath);
|
|
await RunPerformanceAnalysis(registry, testProjectPath);
|
|
await RunTechnicalDebtAnalysis(registry, testProjectPath);
|
|
await RunArchitectureValidation(registry, testProjectPath);
|
|
await RunTestAnalysis(registry, testProjectPath);
|
|
await RunBehaviorAnalysis(registry, testProjectPath);
|
|
|
|
// Generate comprehensive report
|
|
await GenerateComprehensiveReport(registry, testProjectPath);
|
|
|
|
Console.WriteLine();
|
|
Console.WriteLine("✅ Analysis complete! Check the generated reports for detailed results.");
|
|
}
|
|
|
|
private static async Task RunDatabaseAnalysis(AIPluginRegistry registry)
|
|
{
|
|
Console.WriteLine();
|
|
Console.WriteLine("🗄️ SQLite Database Schema Analysis");
|
|
Console.WriteLine("=====================================");
|
|
|
|
var databasePath = GetDatabasePath();
|
|
if (string.IsNullOrEmpty(databasePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Show database analysis options
|
|
Console.WriteLine();
|
|
Console.WriteLine("📋 Database Analysis Options:");
|
|
Console.WriteLine("1. 📖 Basic Schema (Structure only)");
|
|
Console.WriteLine("2. 📊 Detailed Analysis (with row counts and indexes)");
|
|
Console.WriteLine("3. 🔍 Comprehensive Analysis (everything + sample data)");
|
|
Console.WriteLine("4. 📝 Human-readable Report");
|
|
Console.WriteLine("5. 📄 JSON Export");
|
|
Console.WriteLine();
|
|
Console.Write("Select analysis type (1-5): ");
|
|
|
|
var choice = Console.ReadLine();
|
|
|
|
switch (choice)
|
|
{
|
|
case "1":
|
|
await RunBasicSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
case "2":
|
|
await RunDetailedSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
case "3":
|
|
await RunComprehensiveSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
case "4":
|
|
await RunReadableSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
case "5":
|
|
await RunJsonSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
default:
|
|
Console.WriteLine("❌ Invalid option. Running basic analysis...");
|
|
await RunBasicSchemaAnalysis(registry, databasePath);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static string GetDatabasePath()
|
|
{
|
|
// Check for sample database first
|
|
var sampleDbPath = "sample-database.db";
|
|
if (File.Exists(sampleDbPath))
|
|
{
|
|
Console.WriteLine($"🎯 Found sample database: {sampleDbPath}");
|
|
Console.Write("Use sample database? (y/n): ");
|
|
var useSample = Console.ReadLine()?.ToLower();
|
|
if (useSample == "y" || useSample == "yes" || string.IsNullOrEmpty(useSample))
|
|
{
|
|
return sampleDbPath;
|
|
}
|
|
}
|
|
|
|
// Look for .db files in current directory
|
|
var dbFiles = Directory.GetFiles(".", "*.db");
|
|
if (dbFiles.Length > 0)
|
|
{
|
|
Console.WriteLine("📂 Found SQLite database files:");
|
|
for (int i = 0; i < dbFiles.Length; i++)
|
|
{
|
|
Console.WriteLine($" {i + 1}. {Path.GetFileName(dbFiles[i])}");
|
|
}
|
|
Console.Write($"Select a database file (1-{dbFiles.Length}) or enter custom path: ");
|
|
|
|
var selection = Console.ReadLine();
|
|
if (int.TryParse(selection, out int index) && index >= 1 && index <= dbFiles.Length)
|
|
{
|
|
return dbFiles[index - 1];
|
|
}
|
|
|
|
// If not a number, treat as custom path
|
|
if (!string.IsNullOrEmpty(selection) && File.Exists(selection))
|
|
{
|
|
return selection;
|
|
}
|
|
}
|
|
|
|
// Prompt for custom path
|
|
Console.Write("Enter the path to a SQLite database file (.db): ");
|
|
var userPath = Console.ReadLine();
|
|
|
|
if (!string.IsNullOrEmpty(userPath) && File.Exists(userPath))
|
|
{
|
|
return userPath;
|
|
}
|
|
|
|
Console.WriteLine("❌ Database file not found or invalid path.");
|
|
return null;
|
|
}
|
|
|
|
private static async Task RunBasicSchemaAnalysis(AIPluginRegistry registry, string databasePath)
|
|
{
|
|
Console.WriteLine("🔍 Running Basic Schema Analysis...");
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["databasePath"] = databasePath,
|
|
["includeRowCounts"] = false,
|
|
["includeIndexes"] = false,
|
|
["includeForeignKeys"] = false,
|
|
["includeMetadata"] = false,
|
|
["outputFormat"] = "structured"
|
|
};
|
|
|
|
await ExecuteDatabaseAnalysis(registry, parameters, "basic-schema");
|
|
}
|
|
|
|
private static async Task RunDetailedSchemaAnalysis(AIPluginRegistry registry, string databasePath)
|
|
{
|
|
Console.WriteLine("📊 Running Detailed Schema Analysis...");
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["databasePath"] = databasePath,
|
|
["includeRowCounts"] = true,
|
|
["includeIndexes"] = true,
|
|
["includeForeignKeys"] = true,
|
|
["includeMetadata"] = true,
|
|
["outputFormat"] = "structured"
|
|
};
|
|
|
|
await ExecuteDatabaseAnalysis(registry, parameters, "detailed-schema");
|
|
}
|
|
|
|
private static async Task RunComprehensiveSchemaAnalysis(AIPluginRegistry registry, string databasePath)
|
|
{
|
|
Console.WriteLine("🔍 Running Comprehensive Schema Analysis...");
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["databasePath"] = databasePath,
|
|
["includeRowCounts"] = true,
|
|
["includeIndexes"] = true,
|
|
["includeForeignKeys"] = true,
|
|
["includeMetadata"] = true,
|
|
["outputFormat"] = "structured",
|
|
["maxSampleRows"] = 3
|
|
};
|
|
|
|
await ExecuteDatabaseAnalysis(registry, parameters, "comprehensive-schema");
|
|
}
|
|
|
|
private static async Task RunReadableSchemaAnalysis(AIPluginRegistry registry, string databasePath)
|
|
{
|
|
Console.WriteLine("📝 Running Human-Readable Schema Analysis...");
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["databasePath"] = databasePath,
|
|
["includeRowCounts"] = true,
|
|
["includeIndexes"] = true,
|
|
["includeForeignKeys"] = true,
|
|
["includeMetadata"] = true,
|
|
["outputFormat"] = "readable"
|
|
};
|
|
|
|
await ExecuteDatabaseAnalysis(registry, parameters, "readable-schema");
|
|
}
|
|
|
|
private static async Task RunJsonSchemaAnalysis(AIPluginRegistry registry, string databasePath)
|
|
{
|
|
Console.WriteLine("📄 Running JSON Schema Export...");
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["databasePath"] = databasePath,
|
|
["includeRowCounts"] = true,
|
|
["includeIndexes"] = true,
|
|
["includeForeignKeys"] = true,
|
|
["includeMetadata"] = true,
|
|
["outputFormat"] = "json"
|
|
};
|
|
|
|
await ExecuteDatabaseAnalysis(registry, parameters, "json-schema");
|
|
}
|
|
|
|
private static async Task ExecuteDatabaseAnalysis(AIPluginRegistry registry, Dictionary<string, object> parameters, string outputPrefix)
|
|
{
|
|
try
|
|
{
|
|
var result = await registry.CallFunctionAsync("SQLiteSchemaReader", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Database schema analysis completed");
|
|
|
|
var outputFormat = parameters["outputFormat"].ToString();
|
|
var dbName = Path.GetFileNameWithoutExtension(parameters["databasePath"].ToString());
|
|
|
|
if (outputFormat == "readable")
|
|
{
|
|
// For readable format, save as .txt and display preview
|
|
var filename = $"{outputPrefix}-{dbName}.txt";
|
|
await File.WriteAllTextAsync(filename, result.Data.ToString());
|
|
Console.WriteLine($" 📄 Human-readable report saved to: {filename}");
|
|
|
|
// Show preview
|
|
Console.WriteLine();
|
|
Console.WriteLine("📋 Schema Preview:");
|
|
Console.WriteLine(new string('=', 50));
|
|
var lines = result.Data.ToString().Split('\n');
|
|
for (int i = 0; i < Math.Min(20, lines.Length); i++)
|
|
{
|
|
Console.WriteLine(lines[i]);
|
|
}
|
|
if (lines.Length > 20)
|
|
{
|
|
Console.WriteLine($"... ({lines.Length - 20} more lines in full report)");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For structured/json formats, save as JSON
|
|
var filename = $"{outputPrefix}-{dbName}.json";
|
|
await SaveResultToFile(filename, result.Data);
|
|
PrintDatabaseSummary(result.Data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Database analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Database analysis error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void PrintDatabaseSummary(object data)
|
|
{
|
|
try
|
|
{
|
|
var jsonElement = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(data));
|
|
|
|
Console.WriteLine(" 📊 Database Summary:");
|
|
|
|
if (jsonElement.TryGetProperty("databaseName", out var name))
|
|
{
|
|
Console.WriteLine($" Database: {name.GetString()}");
|
|
}
|
|
|
|
if (jsonElement.TryGetProperty("tableCount", out var tableCount))
|
|
{
|
|
Console.WriteLine($" Tables: {tableCount.GetInt32()}");
|
|
}
|
|
|
|
if (jsonElement.TryGetProperty("tables", out var tables) && tables.ValueKind == JsonValueKind.Array)
|
|
{
|
|
Console.WriteLine(" Table Details:");
|
|
foreach (var table in tables.EnumerateArray())
|
|
{
|
|
if (table.TryGetProperty("name", out var tableName))
|
|
{
|
|
var name_str = tableName.GetString();
|
|
var details = new List<string>();
|
|
|
|
if (table.TryGetProperty("columns", out var columns) && columns.ValueKind == JsonValueKind.Array)
|
|
{
|
|
details.Add($"{columns.GetArrayLength()} columns");
|
|
}
|
|
|
|
if (table.TryGetProperty("rowCount", out var rowCount))
|
|
{
|
|
details.Add($"{rowCount.GetInt64():N0} rows");
|
|
}
|
|
|
|
if (table.TryGetProperty("indexes", out var indexes) && indexes.ValueKind == JsonValueKind.Array)
|
|
{
|
|
var indexCount = indexes.GetArrayLength();
|
|
if (indexCount > 0)
|
|
{
|
|
details.Add($"{indexCount} indexes");
|
|
}
|
|
}
|
|
|
|
if (table.TryGetProperty("foreignKeys", out var fks) && fks.ValueKind == JsonValueKind.Array)
|
|
{
|
|
var fkCount = fks.GetArrayLength();
|
|
if (fkCount > 0)
|
|
{
|
|
details.Add($"{fkCount} FKs");
|
|
}
|
|
}
|
|
|
|
Console.WriteLine($" • {name_str} ({string.Join(", ", details)})");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (jsonElement.TryGetProperty("metadata", out var metadata))
|
|
{
|
|
if (metadata.TryGetProperty("formattedSize", out var size))
|
|
{
|
|
Console.WriteLine($" Size: {size.GetString()}");
|
|
}
|
|
|
|
if (metadata.TryGetProperty("sqliteVersion", out var version))
|
|
{
|
|
Console.WriteLine($" SQLite Version: {version.GetString()}");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ⚠️ Could not parse database summary: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static async Task RunIndividualAnalysis(AIPluginRegistry registry)
|
|
{
|
|
Console.WriteLine();
|
|
Console.WriteLine("🔍 Individual Analysis Plugins");
|
|
Console.WriteLine("===============================");
|
|
Console.WriteLine("1. ComplexityAnalyzer");
|
|
Console.WriteLine("2. PerformanceAnalyzer");
|
|
Console.WriteLine("3. TechnicalDebt");
|
|
Console.WriteLine("4. ArchitectureValidator");
|
|
Console.WriteLine("5. TestAnalysis");
|
|
Console.WriteLine("6. BehaviorAnalysis");
|
|
Console.WriteLine("7. SQLiteSchemaReader");
|
|
Console.WriteLine();
|
|
Console.Write("Select plugin to run (1-7): ");
|
|
|
|
var choice = Console.ReadLine();
|
|
|
|
switch (choice)
|
|
{
|
|
case "1":
|
|
var projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunComplexityAnalysis(registry, projectPath);
|
|
break;
|
|
case "2":
|
|
projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunPerformanceAnalysis(registry, projectPath);
|
|
break;
|
|
case "3":
|
|
projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunTechnicalDebtAnalysis(registry, projectPath);
|
|
break;
|
|
case "4":
|
|
projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunArchitectureValidation(registry, projectPath);
|
|
break;
|
|
case "5":
|
|
projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunTestAnalysis(registry, projectPath);
|
|
break;
|
|
case "6":
|
|
projectPath = GetTestProjectPath();
|
|
if (!string.IsNullOrEmpty(projectPath))
|
|
await RunBehaviorAnalysis(registry, projectPath);
|
|
break;
|
|
case "7":
|
|
await RunDatabaseAnalysis(registry);
|
|
break;
|
|
default:
|
|
Console.WriteLine("❌ Invalid option.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static async Task GenerateSampleDatabase()
|
|
{
|
|
Console.WriteLine("📊 Generating Sample SQLite Database...");
|
|
|
|
try
|
|
{
|
|
var dbPath = "sample-database.db";
|
|
|
|
// Delete existing sample database if it exists
|
|
if (File.Exists(dbPath))
|
|
{
|
|
File.Delete(dbPath);
|
|
}
|
|
|
|
var connectionString = $"Data Source={dbPath}";
|
|
using var connection = new Microsoft.Data.Sqlite.SqliteConnection(connectionString);
|
|
await connection.OpenAsync();
|
|
|
|
// Create sample tables with various schema features
|
|
var createScript = @"
|
|
-- Users table with primary key and constraints
|
|
CREATE TABLE Users (
|
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
Username TEXT NOT NULL UNIQUE,
|
|
Email TEXT NOT NULL,
|
|
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
IsActive BOOLEAN DEFAULT 1,
|
|
ProfileData TEXT
|
|
);
|
|
|
|
-- Posts table with foreign key relationship
|
|
CREATE TABLE Posts (
|
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
UserId INTEGER NOT NULL,
|
|
Title TEXT NOT NULL,
|
|
Content TEXT,
|
|
PublishedAt DATETIME,
|
|
ViewCount INTEGER DEFAULT 0,
|
|
FOREIGN KEY (UserId) REFERENCES Users(Id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Comments table with multiple foreign keys
|
|
CREATE TABLE Comments (
|
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
PostId INTEGER NOT NULL,
|
|
UserId INTEGER NOT NULL,
|
|
ParentCommentId INTEGER,
|
|
Content TEXT NOT NULL,
|
|
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (PostId) REFERENCES Posts(Id) ON DELETE CASCADE,
|
|
FOREIGN KEY (UserId) REFERENCES Users(Id) ON DELETE CASCADE,
|
|
FOREIGN KEY (ParentCommentId) REFERENCES Comments(Id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Tags table for many-to-many relationship example
|
|
CREATE TABLE Tags (
|
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
Name TEXT NOT NULL UNIQUE,
|
|
Description TEXT,
|
|
Color TEXT DEFAULT '#000000'
|
|
);
|
|
|
|
-- Junction table for posts and tags
|
|
CREATE TABLE PostTags (
|
|
PostId INTEGER NOT NULL,
|
|
TagId INTEGER NOT NULL,
|
|
PRIMARY KEY (PostId, TagId),
|
|
FOREIGN KEY (PostId) REFERENCES Posts(Id) ON DELETE CASCADE,
|
|
FOREIGN KEY (TagId) REFERENCES Tags(Id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Create indexes for performance
|
|
CREATE INDEX idx_posts_userid ON Posts(UserId);
|
|
CREATE INDEX idx_posts_published ON Posts(PublishedAt);
|
|
CREATE INDEX idx_comments_postid ON Comments(PostId);
|
|
CREATE INDEX idx_comments_userid ON Comments(UserId);
|
|
CREATE UNIQUE INDEX idx_users_email ON Users(Email);
|
|
CREATE INDEX idx_tags_name ON Tags(Name);
|
|
|
|
-- Insert sample data
|
|
INSERT INTO Users (Username, Email, IsActive) VALUES
|
|
('john_doe', 'john@example.com', 1),
|
|
('jane_smith', 'jane@example.com', 1),
|
|
('bob_wilson', 'bob@example.com', 0),
|
|
('alice_brown', 'alice@example.com', 1),
|
|
('charlie_davis', 'charlie@example.com', 1);
|
|
|
|
INSERT INTO Tags (Name, Description, Color) VALUES
|
|
('Technology', 'Posts about technology and programming', '#007acc'),
|
|
('Science', 'Scientific discoveries and research', '#00cc7a'),
|
|
('Entertainment', 'Movies, music, and entertainment', '#cc7a00'),
|
|
('Sports', 'Sports news and updates', '#cc0000'),
|
|
('Travel', 'Travel guides and experiences', '#7a00cc');
|
|
|
|
INSERT INTO Posts (UserId, Title, Content, PublishedAt, ViewCount) VALUES
|
|
(1, 'Introduction to SQLite', 'SQLite is a lightweight database engine...', '2024-01-15 10:00:00', 150),
|
|
(1, 'Database Design Best Practices', 'When designing a database schema...', '2024-01-20 14:30:00', 89),
|
|
(2, 'Machine Learning Basics', 'Understanding the fundamentals of ML...', '2024-01-25 09:15:00', 234),
|
|
(4, 'Travel Tips for Europe', 'Here are some great tips for European travel...', '2024-02-01 16:45:00', 67),
|
|
(5, 'Football Season Preview', 'Looking ahead to the upcoming season...', '2024-02-05 11:20:00', 45);
|
|
|
|
INSERT INTO PostTags (PostId, TagId) VALUES
|
|
(1, 1), -- Introduction to SQLite -> Technology
|
|
(2, 1), -- Database Design -> Technology
|
|
(3, 1), -- Machine Learning -> Technology
|
|
(3, 2), -- Machine Learning -> Science
|
|
(4, 5), -- Travel Tips -> Travel
|
|
(5, 4); -- Football Preview -> Sports
|
|
|
|
INSERT INTO Comments (PostId, UserId, Content, CreatedAt) VALUES
|
|
(1, 2, 'Great introduction! Very helpful for beginners.', '2024-01-15 12:30:00'),
|
|
(1, 4, 'I agree, SQLite is perfect for small applications.', '2024-01-15 15:45:00'),
|
|
(2, 3, 'Could you cover indexing strategies next?', '2024-01-21 09:00:00'),
|
|
(3, 1, 'Nice overview of ML concepts.', '2024-01-26 08:30:00'),
|
|
(3, 5, 'What tools do you recommend for beginners?', '2024-01-26 10:15:00'),
|
|
(4, 2, 'I used these tips on my recent trip - very useful!', '2024-02-02 14:20:00');
|
|
";
|
|
|
|
using var command = connection.CreateCommand();
|
|
command.CommandText = createScript;
|
|
await command.ExecuteNonQueryAsync();
|
|
|
|
Console.WriteLine($" ✅ Sample database created: {dbPath}");
|
|
Console.WriteLine(" 📊 Database contains:");
|
|
Console.WriteLine(" • 5 tables (Users, Posts, Comments, Tags, PostTags)");
|
|
Console.WriteLine(" • Foreign key relationships");
|
|
Console.WriteLine(" • Various indexes");
|
|
Console.WriteLine(" • Sample data for testing");
|
|
Console.WriteLine();
|
|
Console.WriteLine(" 🎯 You can now use this database for schema analysis testing!");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Failed to generate sample database: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void RegisterAnalysisPlugins(AIPluginRegistry registry)
|
|
{
|
|
Console.WriteLine("🔧 Registering Analysis plugins...");
|
|
|
|
try
|
|
{
|
|
registry.RegisterPlugin(new ComplexityAnalyzerPlugin());
|
|
Console.WriteLine(" ✓ ComplexityAnalyzerPlugin registered");
|
|
|
|
registry.RegisterPlugin(new PerformanceAnalyzerPlugin());
|
|
Console.WriteLine(" ✓ PerformanceAnalyzerPlugin registered");
|
|
|
|
registry.RegisterPlugin(new TechnicalDebtPlugin());
|
|
Console.WriteLine(" ✓ TechnicalDebtPlugin registered");
|
|
|
|
registry.RegisterPlugin(new ArchitectureValidatorPlugin());
|
|
Console.WriteLine(" ✓ ArchitectureValidatorPlugin registered");
|
|
|
|
registry.RegisterPlugin(new TestAnalysisPlugin());
|
|
Console.WriteLine(" ✓ TestAnalysisPlugin registered");
|
|
|
|
registry.RegisterPlugin(new BehaviorAnalysisPlugin());
|
|
Console.WriteLine(" ✓ BehaviorAnalysisPlugin registered");
|
|
|
|
// Register the new SQLite Schema Reader plugin
|
|
var sqliteLogger = _loggerFactory.CreateLogger<SQLiteSchemaReaderPlugin>();
|
|
registry.RegisterPlugin(new SQLiteSchemaReaderPlugin(sqliteLogger));
|
|
Console.WriteLine(" ✓ SQLiteSchemaReaderPlugin registered");
|
|
|
|
Console.WriteLine($"📊 Total plugins registered: {registry.GetAllPluginSchemas().Count}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"❌ Failed to register plugins: {ex.Message}");
|
|
throw;
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static string GetTestProjectPath()
|
|
{
|
|
var args = Environment.GetCommandLineArgs();
|
|
|
|
// Check command line arguments
|
|
if (args.Length > 1 && Directory.Exists(args[1]))
|
|
{
|
|
return args[1];
|
|
}
|
|
|
|
// Try current directory
|
|
var currentDir = Directory.GetCurrentDirectory();
|
|
if (HasCSharpFiles(currentDir))
|
|
{
|
|
return currentDir;
|
|
}
|
|
|
|
// Try common project locations
|
|
var testPaths = new[]
|
|
{
|
|
Path.Combine(currentDir, "TestProject"),
|
|
Path.Combine(currentDir, "src"),
|
|
Path.Combine(currentDir, "Source"),
|
|
Path.Combine(Directory.GetParent(currentDir)?.FullName ?? "", "TestProject")
|
|
};
|
|
|
|
foreach (var testPath in testPaths)
|
|
{
|
|
if (Directory.Exists(testPath) && HasCSharpFiles(testPath))
|
|
{
|
|
return testPath;
|
|
}
|
|
}
|
|
|
|
// Prompt user for path
|
|
Console.Write("Enter the path to a C# project directory: ");
|
|
var userPath = Console.ReadLine();
|
|
|
|
if (!string.IsNullOrEmpty(userPath) && Directory.Exists(userPath))
|
|
{
|
|
return userPath;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static bool HasCSharpFiles(string directory)
|
|
{
|
|
try
|
|
{
|
|
return Directory.GetFiles(directory, "*.cs", SearchOption.AllDirectories).Length > 0;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static async Task RunComplexityAnalysis(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("🔍 Running Complexity Analysis...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["path"] = projectPath,
|
|
["calculateCyclomatic"] = true,
|
|
["calculateCognitive"] = true,
|
|
["maxCyclomaticComplexity"] = 10,
|
|
["maxCognitiveComplexity"] = 15,
|
|
["generateSuggestions"] = true,
|
|
["includeMethodBreakdown"] = true
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("ComplexityAnalyzer", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Complexity analysis completed");
|
|
PrintResultSummary("Complexity", result.Data);
|
|
await SaveResultToFile("complexity-analysis.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Complexity analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Complexity analysis error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task RunPerformanceAnalysis(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("⚡ Running Performance Analysis...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["path"] = projectPath,
|
|
["analyzeComplexity"] = true,
|
|
["checkLoops"] = true,
|
|
["analyzeMemory"] = true,
|
|
["checkDatabase"] = true,
|
|
["suggestCaching"] = true,
|
|
["analysisDepth"] = "comprehensive"
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("PerformanceAnalyzer", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Performance analysis completed");
|
|
PrintResultSummary("Performance", result.Data);
|
|
await SaveResultToFile("performance-analysis.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Performance analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Performance analysis error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task RunTechnicalDebtAnalysis(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("💳 Running Technical Debt Analysis...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["calculateComplexityDebt"] = true,
|
|
["analyzeDocumentationDebt"] = true,
|
|
["checkDependencyDebt"] = true,
|
|
["analyzeTestDebt"] = true,
|
|
["generateImprovementPlan"] = true,
|
|
["trackTrends"] = true
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("TechnicalDebt", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Technical debt analysis completed");
|
|
PrintResultSummary("Technical Debt", result.Data);
|
|
await SaveResultToFile("technical-debt-analysis.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Technical debt analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Technical debt analysis error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task RunArchitectureValidation(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("🏗️ Running Architecture Validation...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["architecturePattern"] = "auto",
|
|
["checkLayerBoundaries"] = true,
|
|
["checkCircularDependencies"] = true,
|
|
["validateNaming"] = true,
|
|
["checkAntiPatterns"] = true,
|
|
["generateDocumentation"] = true
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("ArchitectureValidator", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Architecture validation completed");
|
|
PrintResultSummary("Architecture", result.Data);
|
|
await SaveResultToFile("architecture-validation.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Architecture validation failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Architecture validation error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task RunTestAnalysis(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("🧪 Running Test Analysis...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["projectPath"] = projectPath,
|
|
["calculateCoverage"] = true,
|
|
["identifyUntested"] = true,
|
|
["analyzeTestQuality"] = true,
|
|
["generateTestStubs"] = true,
|
|
["suggestAdvancedTesting"] = true,
|
|
["checkRedundantTests"] = true
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("TestAnalysis", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Test analysis completed");
|
|
PrintResultSummary("Test", result.Data);
|
|
await SaveResultToFile("test-analysis.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Test analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Test analysis error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task RunBehaviorAnalysis(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("🎭 Running Behavior Analysis...");
|
|
|
|
try
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["path"] = projectPath,
|
|
["generateSummaries"] = true,
|
|
["compareVersions"] = true,
|
|
["detectBreakingChanges"] = true,
|
|
["validateIntent"] = true,
|
|
["suggestTests"] = true
|
|
};
|
|
|
|
var result = await registry.CallFunctionAsync("BehaviorAnalysis", parameters);
|
|
|
|
if (result.Success)
|
|
{
|
|
Console.WriteLine(" ✅ Behavior analysis completed");
|
|
PrintResultSummary("Behavior", result.Data);
|
|
await SaveResultToFile("behavior-analysis.json", result.Data);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" ❌ Behavior analysis failed: {result.Message}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Behavior analysis error: {ex.Message}");
|
|
}
|
|
|
|
Console.WriteLine();
|
|
}
|
|
|
|
private static async Task GenerateComprehensiveReport(AIPluginRegistry registry, string projectPath)
|
|
{
|
|
Console.WriteLine("📋 Generating Comprehensive Analysis Report...");
|
|
|
|
try
|
|
{
|
|
var reportData = new
|
|
{
|
|
GeneratedAt = DateTime.UtcNow,
|
|
ProjectPath = projectPath,
|
|
AnalysisType = "Comprehensive Code Quality Assessment",
|
|
PluginsUsed = new[]
|
|
{
|
|
"ComplexityAnalyzer - Cyclomatic and cognitive complexity analysis",
|
|
"PerformanceAnalyzer - Performance bottleneck detection",
|
|
"TechnicalDebt - Debt quantification and improvement planning",
|
|
"ArchitectureValidator - Architectural pattern validation",
|
|
"TestAnalysis - Test coverage and quality assessment",
|
|
"BehaviorAnalysis - Code behavior and intent validation"
|
|
},
|
|
Summary = new
|
|
{
|
|
TotalAnalysisPlugins = 6,
|
|
AnalysisScope = "Full project analysis including complexity, performance, debt, architecture, testing, and behavior",
|
|
OutputFiles = new[]
|
|
{
|
|
"complexity-analysis.json",
|
|
"performance-analysis.json",
|
|
"technical-debt-analysis.json",
|
|
"architecture-validation.json",
|
|
"test-analysis.json",
|
|
"behavior-analysis.json"
|
|
}
|
|
},
|
|
Recommendations = new[]
|
|
{
|
|
"Review high-complexity methods identified in complexity analysis",
|
|
"Address performance bottlenecks found in performance analysis",
|
|
"Follow improvement plan from technical debt analysis",
|
|
"Fix architecture violations found in validation",
|
|
"Improve test coverage based on test analysis results",
|
|
"Align code behavior with specifications per behavior analysis"
|
|
},
|
|
NextSteps = new[]
|
|
{
|
|
"Prioritize issues by severity and impact",
|
|
"Create development tasks for high-priority improvements",
|
|
"Implement recommended refactoring and optimizations",
|
|
"Re-run analysis to track progress",
|
|
"Integrate analysis into CI/CD pipeline for continuous monitoring"
|
|
}
|
|
};
|
|
|
|
await SaveResultToFile("comprehensive-analysis-report.json", reportData);
|
|
|
|
// Generate markdown report
|
|
var markdownReport = GenerateMarkdownReport(reportData);
|
|
await File.WriteAllTextAsync("analysis-report.md", markdownReport);
|
|
|
|
Console.WriteLine(" ✅ Comprehensive report generated");
|
|
Console.WriteLine(" 📄 JSON Report: comprehensive-analysis-report.json");
|
|
Console.WriteLine(" 📝 Markdown Report: analysis-report.md");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Report generation error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void PrintResultSummary(string analysisType, object data)
|
|
{
|
|
try
|
|
{
|
|
var jsonElement = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(data));
|
|
|
|
if (jsonElement.TryGetProperty("Summary", out var summary))
|
|
{
|
|
Console.WriteLine($" 📊 {analysisType} Summary:");
|
|
PrintJsonProperties(summary, " ");
|
|
}
|
|
else if (jsonElement.TryGetProperty("OverallComplexityScore", out var score))
|
|
{
|
|
Console.WriteLine($" 📊 {analysisType} Score: {score}");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" 📊 {analysisType} analysis data captured");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ⚠️ Could not parse {analysisType} summary: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void PrintJsonProperties(JsonElement element, string indent)
|
|
{
|
|
foreach (var property in element.EnumerateObject())
|
|
{
|
|
var value = property.Value.ValueKind switch
|
|
{
|
|
JsonValueKind.String => property.Value.GetString(),
|
|
JsonValueKind.Number => property.Value.GetRawText(),
|
|
JsonValueKind.True => "true",
|
|
JsonValueKind.False => "false",
|
|
JsonValueKind.Array => $"[{property.Value.GetArrayLength()} items]",
|
|
JsonValueKind.Object => "[object]",
|
|
_ => property.Value.GetRawText()
|
|
};
|
|
|
|
Console.WriteLine($"{indent}{property.Name}: {value}");
|
|
}
|
|
}
|
|
|
|
private static async Task SaveResultToFile(string filename, object data)
|
|
{
|
|
try
|
|
{
|
|
var json = JsonSerializer.Serialize(data, new JsonSerializerOptions
|
|
{
|
|
WriteIndented = true,
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
|
});
|
|
|
|
await File.WriteAllTextAsync(filename, json);
|
|
Console.WriteLine($" 💾 Results saved to: {filename}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" ❌ Failed to save {filename}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static string GenerateMarkdownReport(object reportData)
|
|
{
|
|
return @"# MarketAlly AI Plugin Analysis Report
|
|
|
|
## Executive Summary
|
|
|
|
This report presents a comprehensive analysis of the codebase using the MarketAlly AI Plugin Analysis toolkit. The analysis covers six key areas: complexity, performance, technical debt, architecture, testing, and behavior.
|
|
|
|
## Analysis Overview
|
|
|
|
| Analysis Type | Status | Output File |
|
|
|---------------|--------|-------------|
|
|
| Complexity Analysis | ✅ Complete | `complexity-analysis.json` |
|
|
| Performance Analysis | ✅ Complete | `performance-analysis.json` |
|
|
| Technical Debt Analysis | ✅ Complete | `technical-debt-analysis.json` |
|
|
| Architecture Validation | ✅ Complete | `architecture-validation.json` |
|
|
| Test Analysis | ✅ Complete | `test-analysis.json` |
|
|
| Behavior Analysis | ✅ Complete | `behavior-analysis.json` |
|
|
|
|
## Key Findings
|
|
|
|
### 🔍 Complexity Analysis
|
|
- Analyzed cyclomatic and cognitive complexity
|
|
- Identified high-complexity methods requiring refactoring
|
|
- Generated specific reduction suggestions
|
|
|
|
### ⚡ Performance Analysis
|
|
- Detected performance bottlenecks and optimization opportunities
|
|
- Analyzed loop efficiency and memory allocation patterns
|
|
- Suggested caching and database optimization strategies
|
|
|
|
### 💳 Technical Debt Analysis
|
|
- Quantified debt across complexity, documentation, dependencies, and testing
|
|
- Generated prioritized improvement plan with effort estimates
|
|
- Tracked debt trends over time
|
|
|
|
### 🏗️ Architecture Validation
|
|
- Validated architectural patterns and layer boundaries
|
|
- Detected circular dependencies and anti-patterns
|
|
- Assessed naming convention compliance
|
|
|
|
### 🧪 Test Analysis
|
|
- Evaluated test coverage and quality
|
|
- Identified untested functions and quality issues
|
|
- Suggested advanced testing strategies
|
|
|
|
### 🎭 Behavior Analysis
|
|
- Analyzed code behavior against specifications
|
|
- Detected semantic drift and breaking changes
|
|
- Generated behavior test suggestions
|
|
|
|
## Recommendations
|
|
|
|
1. **Immediate Actions**
|
|
- Review and address high-severity issues from all analyses
|
|
- Implement suggested refactoring for complex methods
|
|
- Fix critical architecture violations
|
|
|
|
2. **Short-term Improvements**
|
|
- Follow technical debt improvement plan
|
|
- Enhance test coverage based on analysis results
|
|
- Optimize performance bottlenecks
|
|
|
|
3. **Long-term Strategy**
|
|
- Integrate analysis tools into CI/CD pipeline
|
|
- Establish coding standards based on findings
|
|
- Regular re-analysis to track progress
|
|
|
|
## Detailed Results
|
|
|
|
For detailed analysis results, please refer to the individual JSON files generated for each analysis type.
|
|
|
|
---
|
|
|
|
*Report generated by MarketAlly AI Plugin Analysis Toolkit*
|
|
*Generated on: " + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC") + @"*
|
|
";
|
|
}
|
|
}
|
|
|
|
// Sample test classes to analyze if no project is provided
|
|
public class SampleComplexClass
|
|
{
|
|
private readonly string _connectionString;
|
|
private readonly ILogger _logger;
|
|
|
|
public SampleComplexClass(string connectionString, ILogger logger)
|
|
{
|
|
_connectionString = connectionString;
|
|
_logger = logger;
|
|
}
|
|
|
|
// High complexity method
|
|
public async Task<string> ProcessComplexBusinessLogic(int type, string data, bool validate)
|
|
{
|
|
if (string.IsNullOrEmpty(data))
|
|
throw new ArgumentException("Data cannot be null or empty");
|
|
|
|
var result = "";
|
|
|
|
for (int i = 0; i < data.Length; i++)
|
|
{
|
|
if (validate)
|
|
{
|
|
if (char.IsDigit(data[i]))
|
|
{
|
|
if (type == 1)
|
|
{
|
|
result += data[i];
|
|
}
|
|
else if (type == 2)
|
|
{
|
|
result += (char)(data[i] + 1);
|
|
}
|
|
else
|
|
{
|
|
switch (type)
|
|
{
|
|
case 3:
|
|
result += data[i].ToString().ToUpper();
|
|
break;
|
|
case 4:
|
|
result += data[i].ToString().ToLower();
|
|
break;
|
|
default:
|
|
result += data[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (char.IsLetter(data[i]))
|
|
{
|
|
if (type == 1 || type == 2)
|
|
{
|
|
result += data[i].ToString().ToUpper();
|
|
}
|
|
else
|
|
{
|
|
result += data[i].ToString().ToLower();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result += data[i];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Database access method (simulated without SqlClient dependency)
|
|
public async Task<List<string>> GetDataFromDatabase(string query)
|
|
{
|
|
var results = new List<string>();
|
|
|
|
try
|
|
{
|
|
// Simulate database access without SqlClient dependency
|
|
_logger?.LogInformation("Executing database query: {Query}", query);
|
|
|
|
// Simulate async database operation
|
|
await Task.Delay(100);
|
|
|
|
// Simulate some results
|
|
results.Add("Sample Result 1");
|
|
results.Add("Sample Result 2");
|
|
results.Add("Sample Result 3");
|
|
|
|
_logger?.LogInformation("Retrieved {Count} records", results.Count);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "Database query failed");
|
|
throw;
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
// Method lacking documentation
|
|
public bool ValidateInput(string input)
|
|
{
|
|
return !string.IsNullOrEmpty(input) && input.Length > 3;
|
|
}
|
|
|
|
// Method with file system access
|
|
public async Task<string> ProcessFileAsync(string filePath)
|
|
{
|
|
if (File.Exists(filePath))
|
|
{
|
|
var content = await File.ReadAllTextAsync(filePath);
|
|
Console.WriteLine($"Processing file: {filePath}");
|
|
return content.ToUpperInvariant();
|
|
}
|
|
return string.Empty;
|
|
}
|
|
|
|
// Method with network communication simulation
|
|
public async Task<string> FetchDataFromApiAsync(string endpoint)
|
|
{
|
|
try
|
|
{
|
|
// Simulate HTTP client usage
|
|
await Task.Delay(200); // Simulate network delay
|
|
_logger?.LogInformation("Fetching data from: {Endpoint}", endpoint);
|
|
|
|
// Simulate API response
|
|
return $"{{\"data\": \"response from {endpoint}\"}}";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger?.LogError(ex, "API call failed for endpoint: {Endpoint}", endpoint);
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class UtilityHelper
|
|
{
|
|
public static string FormatString(string input)
|
|
{
|
|
return input?.Trim().ToLowerInvariant() ?? "";
|
|
}
|
|
|
|
public static int CalculateSum(int[] numbers)
|
|
{
|
|
int sum = 0;
|
|
for (int i = 0; i < numbers.Length; i++)
|
|
{
|
|
sum += numbers[i];
|
|
}
|
|
return sum;
|
|
}
|
|
}
|
|
} |