using MarketAlly.AIPlugin; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace MarketAlly.AIPlugin.Refactoring.Plugins { [AIPlugin("EnhancedDocumentationGenerator", "Enhanced documentation generation with multiple styles and AI-powered descriptions")] public class EnhancedDocumentationGeneratorPlugin : IAIPlugin { [AIParameter("Full path to the file to document", required: true)] public string FilePath { get; set; } [AIParameter("Documentation style: intelligent, comprehensive, basic, minimal", required: false)] public string Style { get; set; } = "intelligent"; [AIParameter("Include examples in documentation", required: false)] public bool IncludeExamples { get; set; } = false; [AIParameter("Include see-also references", required: false)] public bool IncludeSeeAlso { get; set; } = false; [AIParameter("Generate API documentation format", required: false)] public bool ApiDocFormat { get; set; } = false; [AIParameter("Apply changes to file", required: false)] public bool ApplyChanges { get; set; } = false; [AIParameter("Scope of documentation: public, protected, internal, all", required: false)] public string DocumentationScope { get; set; } = "public"; public IReadOnlyDictionary SupportedParameters => new Dictionary { ["filePath"] = typeof(string), ["filepath"] = typeof(string), // Allow lowercase ["style"] = typeof(string), ["includeExamples"] = typeof(bool), ["includeexamples"] = typeof(bool), // Allow lowercase ["includeSeeAlso"] = typeof(bool), ["includeseealso"] = typeof(bool), // Allow lowercase ["apiDocFormat"] = typeof(bool), ["apidocformat"] = typeof(bool), // Allow lowercase ["applyChanges"] = typeof(bool), ["applychanges"] = typeof(bool), // Allow lowercase ["documentationScope"] = typeof(string), ["documentationscope"] = typeof(string) // Allow lowercase }; public async Task ExecuteAsync(IReadOnlyDictionary parameters) { try { // Extract parameters with case-insensitive handling string filePath = GetParameterValue(parameters, "filePath", "filepath")?.ToString(); string style = GetParameterValue(parameters, "style")?.ToString()?.ToLower() ?? "intelligent"; bool includeExamples = GetBoolParameter(parameters, "includeExamples", "includeexamples"); bool includeSeeAlso = GetBoolParameter(parameters, "includeSeeAlso", "includeseealso"); bool apiDocFormat = GetBoolParameter(parameters, "apiDocFormat", "apidocformat"); bool applyChanges = GetBoolParameter(parameters, "applyChanges", "applychanges"); string scope = GetParameterValue(parameters, "documentationScope", "documentationscope")?.ToString()?.ToLower() ?? "public"; // Validate file exists if (!File.Exists(filePath)) { return new AIPluginResult( new FileNotFoundException($"File not found: {filePath}"), "File not found" ); } // Read and parse the file var sourceCode = await File.ReadAllTextAsync(filePath); var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); var root = syntaxTree.GetRoot(); // Analyze the code structure var codeAnalysis = await AnalyzeCodeStructure(root, filePath, scope); if (codeAnalysis.MembersNeedingDocumentation.Count == 0) { return new AIPluginResult(new { Message = "No members found that need documentation", FilePath = filePath, MembersAnalyzed = codeAnalysis.TotalMembers, Scope = scope, ChangesMade = false }); } // Generate documentation based on style var documentationSuggestions = await GenerateDocumentationByStyle( codeAnalysis, sourceCode, style, includeExamples, includeSeeAlso, apiDocFormat ); // Apply documentation to the code var modifiedContent = ApplyDocumentationToCode(sourceCode, documentationSuggestions); // Calculate statistics var stats = CalculateDocumentationStats(documentationSuggestions, codeAnalysis); if (applyChanges) { // Create backup var backupPath = $"{filePath}.{DateTime.Now:yyyyMMdd_HHmmss}.bak"; File.Copy(filePath, backupPath); // Write modified content await File.WriteAllTextAsync(filePath, modifiedContent, Encoding.UTF8); return new AIPluginResult(new { Message = $"Successfully added {style} documentation to {documentationSuggestions.Count} members", FilePath = filePath, BackupPath = backupPath, Style = style, ChangesMade = true, Statistics = stats, ModifiedContent = modifiedContent, Timestamp = DateTime.UtcNow }); } else { return new AIPluginResult(new { Message = $"Preview: Would add {style} documentation to {documentationSuggestions.Count} members", FilePath = filePath, Style = style, ChangesMade = false, Statistics = stats, PreviewContent = modifiedContent, DocumentationSuggestions = documentationSuggestions.Select(s => new { Member = s.Member.Name, Type = s.Member.Type, LineNumber = s.Member.LineNumber, Documentation = s.DocumentationLines, Quality = s.QualityScore }).ToList(), Timestamp = DateTime.UtcNow }); } } catch (Exception ex) { return new AIPluginResult(ex, $"Enhanced documentation generation failed: {ex.Message}"); } } private object GetParameterValue(IReadOnlyDictionary parameters, params string[] keys) { foreach (var key in keys) { if (parameters.TryGetValue(key, out var value)) return value; } return null; } private bool GetBoolParameter(IReadOnlyDictionary parameters, params string[] keys) { var value = GetParameterValue(parameters, keys); return value != null && Convert.ToBoolean(value); } private async Task AnalyzeCodeStructure(SyntaxNode root, string filePath, string scope) { var analysis = new EnhancedCodeAnalysis { FilePath = filePath, MembersNeedingDocumentation = new List() }; var accessibilityFilter = GetAccessibilityFilter(scope); // Analyze classes var classes = root.DescendantNodes().OfType(); foreach (var cls in classes) { if (ShouldDocumentMember(cls, accessibilityFilter) && !HasDocumentation(cls)) { var member = await CreateEnhancedCodeMember(cls, "class", root); analysis.MembersNeedingDocumentation.Add(member); } analysis.TotalMembers++; } // Analyze interfaces var interfaces = root.DescendantNodes().OfType(); foreach (var iface in interfaces) { if (ShouldDocumentMember(iface, accessibilityFilter) && !HasDocumentation(iface)) { var member = await CreateEnhancedCodeMember(iface, "interface", root); analysis.MembersNeedingDocumentation.Add(member); } analysis.TotalMembers++; } // Analyze methods var methods = root.DescendantNodes().OfType(); foreach (var method in methods) { if (ShouldDocumentMember(method, accessibilityFilter) && !HasDocumentation(method)) { var member = await CreateEnhancedCodeMember(method, "method", root); analysis.MembersNeedingDocumentation.Add(member); } analysis.TotalMembers++; } // Analyze properties var properties = root.DescendantNodes().OfType(); foreach (var prop in properties) { if (ShouldDocumentMember(prop, accessibilityFilter) && !HasDocumentation(prop)) { var member = await CreateEnhancedCodeMember(prop, "property", root); analysis.MembersNeedingDocumentation.Add(member); } analysis.TotalMembers++; } // Analyze events var events = root.DescendantNodes().OfType(); foreach (var evt in events) { if (ShouldDocumentMember(evt, accessibilityFilter) && !HasDocumentation(evt)) { var member = await CreateEnhancedCodeMember(evt, "event", root); analysis.MembersNeedingDocumentation.Add(member); } analysis.TotalMembers++; } return analysis; } private async Task CreateEnhancedCodeMember(SyntaxNode node, string type, SyntaxNode root) { var og = node.GetText().Lines.FirstOrDefault(); var member = new EnhancedCodeMember { Type = type, LineNumber = node.GetLocation().GetLineSpan().StartLinePosition.Line + 1, OriginalLine = (og == null) ? "" : og.ToString(), IndentLevel = GetIndentLevel(node), Context = await AnalyzeMemberContext(node, root) }; // Extract member-specific information switch (node) { case ClassDeclarationSyntax cls: member.Name = cls.Identifier.ValueText; member.Accessibility = GetAccessibility(cls.Modifiers); member.IsStatic = cls.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)); member.IsAbstract = cls.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword)); member.BaseTypes = cls.BaseList?.Types.Select(t => t.ToString()).ToList() ?? new List(); break; case InterfaceDeclarationSyntax iface: member.Name = iface.Identifier.ValueText; member.Accessibility = GetAccessibility(iface.Modifiers); member.BaseTypes = iface.BaseList?.Types.Select(t => t.ToString()).ToList() ?? new List(); break; case MethodDeclarationSyntax method: member.Name = method.Identifier.ValueText; member.Accessibility = GetAccessibility(method.Modifiers); member.IsStatic = method.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)); member.IsAsync = method.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)); member.Parameters = ExtractParameters(method.ParameterList); member.ReturnType = method.ReturnType.ToString(); member.IsOverride = method.Modifiers.Any(m => m.IsKind(SyntaxKind.OverrideKeyword)); member.IsVirtual = method.Modifiers.Any(m => m.IsKind(SyntaxKind.VirtualKeyword)); break; case PropertyDeclarationSyntax prop: member.Name = prop.Identifier.ValueText; member.Accessibility = GetAccessibility(prop.Modifiers); member.IsStatic = prop.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)); member.ReturnType = prop.Type.ToString(); member.HasGetter = prop.AccessorList?.Accessors.Any(a => a.IsKind(SyntaxKind.GetAccessorDeclaration)) ?? false; member.HasSetter = prop.AccessorList?.Accessors.Any(a => a.IsKind(SyntaxKind.SetAccessorDeclaration)) ?? false; break; case EventDeclarationSyntax evt: member.Name = evt.Identifier.ValueText; member.Accessibility = GetAccessibility(evt.Modifiers); member.IsStatic = evt.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)); member.ReturnType = evt.Type.ToString(); break; } return member; } private async Task AnalyzeMemberContext(SyntaxNode node, SyntaxNode root) { var context = new MemberContext(); // Find containing class/interface var containingType = node.Ancestors().OfType().FirstOrDefault(); if (containingType != null) { context.ContainingTypeName = containingType switch { ClassDeclarationSyntax cls => cls.Identifier.ValueText, InterfaceDeclarationSyntax iface => iface.Identifier.ValueText, _ => containingType.ToString() }; } // Find namespace var namespaceDeclaration = node.Ancestors().OfType().FirstOrDefault(); if (namespaceDeclaration != null) { context.Namespace = namespaceDeclaration.Name.ToString(); } // Analyze usage patterns if (node is MethodDeclarationSyntax method) { context.UsagePatterns = AnalyzeMethodUsage(method); context.ComplexityScore = CalculateMethodComplexity(method); } return context; } private async Task> GenerateDocumentationByStyle( EnhancedCodeAnalysis analysis, string sourceCode, string style, bool includeExamples, bool includeSeeAlso, bool apiDocFormat) { var suggestions = new List(); foreach (var member in analysis.MembersNeedingDocumentation) { var suggestion = new EnhancedDocumentationSuggestion { Member = member, DocumentationLines = new List() }; var indent = new string('\t', member.IndentLevel); switch (style) { case "intelligent": await GenerateIntelligentDocumentation(suggestion, member, indent, includeExamples, includeSeeAlso); break; case "comprehensive": await GenerateComprehensiveDocumentation(suggestion, member, indent, includeExamples, includeSeeAlso, apiDocFormat); break; case "basic": await GenerateBasicDocumentation(suggestion, member, indent); break; case "minimal": await GenerateMinimalDocumentation(suggestion, member, indent); break; default: await GenerateIntelligentDocumentation(suggestion, member, indent, includeExamples, includeSeeAlso); break; } // Calculate quality score suggestion.QualityScore = CalculateDocumentationQuality(suggestion, member); suggestions.Add(suggestion); } return suggestions; } private async Task GenerateIntelligentDocumentation( EnhancedDocumentationSuggestion suggestion, EnhancedCodeMember member, string indent, bool includeExamples, bool includeSeeAlso) { var docs = suggestion.DocumentationLines; docs.Add($"{indent}/// "); // Generate intelligent description based on member analysis var description = GenerateIntelligentDescription(member); docs.Add($"{indent}/// {description}"); docs.Add($"{indent}/// "); // Add type parameters for generic types if (member.Type == "class" || member.Type == "interface" || member.Type == "method") { // This would need more sophisticated generic type analysis // For now, we'll keep it simple } // Add parameters documentation if (member.Parameters?.Count > 0) { foreach (var param in member.Parameters) { var paramDescription = GenerateIntelligentParameterDescription(param, member); docs.Add($"{indent}/// {paramDescription}"); } } // Add return documentation if (!string.IsNullOrEmpty(member.ReturnType) && member.ReturnType != "void") { var returnDescription = GenerateIntelligentReturnDescription(member); docs.Add($"{indent}/// {returnDescription}"); } // Add exceptions for methods with complexity if (member.Type == "method" && member.Context?.ComplexityScore > 5) { var exceptions = GenerateExceptionDocumentation(member); foreach (var exception in exceptions) { docs.Add($"{indent}/// {exception.Description}"); } } // Add examples if requested if (includeExamples && ShouldIncludeExample(member)) { await GenerateExampleDocumentation(docs, member, indent); } // Add see-also references if requested if (includeSeeAlso) { var seeAlsoRefs = GenerateSeeAlsoReferences(member); foreach (var seeAlso in seeAlsoRefs) { docs.Add($"{indent}/// "); } } await Task.CompletedTask; } private async Task GenerateComprehensiveDocumentation( EnhancedDocumentationSuggestion suggestion, EnhancedCodeMember member, string indent, bool includeExamples, bool includeSeeAlso, bool apiDocFormat) { // Start with intelligent documentation await GenerateIntelligentDocumentation(suggestion, member, indent, true, includeSeeAlso); var docs = suggestion.DocumentationLines; // Add additional comprehensive elements if (member.Type == "method") { // Add complexity information as remarks if (member.Context?.ComplexityScore > 3) { docs.Add($"{indent}/// "); docs.Add($"{indent}/// This method has a complexity score of {member.Context.ComplexityScore}. "); docs.Add($"{indent}/// Consider refactoring if the complexity grows further."); docs.Add($"{indent}/// "); } // Add performance considerations if (member.Context?.UsagePatterns?.Contains("loop") == true) { docs.Add($"{indent}/// "); docs.Add($"{indent}/// Performance consideration: This method contains loops. "); docs.Add($"{indent}/// Consider the input size when calling this method."); docs.Add($"{indent}/// "); } } // Add version information for API documentation if (apiDocFormat) { docs.Add($"{indent}/// 1.0.0"); } await Task.CompletedTask; } private async Task GenerateBasicDocumentation( EnhancedDocumentationSuggestion suggestion, EnhancedCodeMember member, string indent) { var docs = suggestion.DocumentationLines; docs.Add($"{indent}/// "); docs.Add($"{indent}/// {GenerateBasicDescription(member)}"); docs.Add($"{indent}/// "); // Basic parameter documentation if (member.Parameters?.Count > 0) { foreach (var param in member.Parameters) { docs.Add($"{indent}/// The {param.Name} parameter"); } } // Basic return documentation if (!string.IsNullOrEmpty(member.ReturnType) && member.ReturnType != "void") { docs.Add($"{indent}/// The {member.ReturnType.ToLower()} result"); } await Task.CompletedTask; } private async Task GenerateMinimalDocumentation( EnhancedDocumentationSuggestion suggestion, EnhancedCodeMember member, string indent) { var docs = suggestion.DocumentationLines; docs.Add($"{indent}/// "); docs.Add($"{indent}/// {member.Name}"); docs.Add($"{indent}/// "); await Task.CompletedTask; } private string GenerateIntelligentDescription(EnhancedCodeMember member) { var name = member.Name; var type = member.Type; switch (type) { case "class": return GenerateClassDescription(member); case "interface": return GenerateInterfaceDescription(member); case "method": return GenerateMethodDescription(member); case "property": return GeneratePropertyDescription(member); case "event": return GenerateEventDescription(member); default: return $"Represents {SplitCamelCase(name).ToLower()}"; } } private string GenerateClassDescription(EnhancedCodeMember member) { var name = member.Name; var description = new StringBuilder(); // Analyze naming patterns if (name.EndsWith("Service")) description.Append($"Provides services for {SplitCamelCase(name.Replace("Service", "")).ToLower()}"); else if (name.EndsWith("Controller")) description.Append($"Handles requests for {SplitCamelCase(name.Replace("Controller", "")).ToLower()}"); else if (name.EndsWith("Repository")) description.Append($"Manages data operations for {SplitCamelCase(name.Replace("Repository", "")).ToLower()}"); else if (name.EndsWith("Manager")) description.Append($"Manages {SplitCamelCase(name.Replace("Manager", "")).ToLower()} operations"); else if (name.EndsWith("Factory")) description.Append($"Creates instances of {SplitCamelCase(name.Replace("Factory", "")).ToLower()}"); else if (name.EndsWith("Builder")) description.Append($"Builds {SplitCamelCase(name.Replace("Builder", "")).ToLower()} objects"); else if (name.EndsWith("Helper")) description.Append($"Provides helper methods for {SplitCamelCase(name.Replace("Helper", "")).ToLower()}"); else if (name.EndsWith("Utility") || name.EndsWith("Utils")) description.Append($"Utility class for {SplitCamelCase(name.Replace("Utility", "").Replace("Utils", "")).ToLower()}"); else if (name.EndsWith("Exception")) description.Append($"Exception thrown when {SplitCamelCase(name.Replace("Exception", "")).ToLower()} occurs"); else if (name.EndsWith("Attribute")) description.Append($"Attribute for {SplitCamelCase(name.Replace("Attribute", "")).ToLower()}"); else if (name.EndsWith("Plugin")) description.Append($"Plugin that provides {SplitCamelCase(name.Replace("Plugin", "")).ToLower()} functionality"); else description.Append($"Represents a {SplitCamelCase(name).ToLower()}"); // Add inheritance information if (member.BaseTypes?.Any() == true) { var baseType = member.BaseTypes.First(); if (!baseType.Equals("object", StringComparison.OrdinalIgnoreCase)) { description.Append($" that extends {baseType}"); } } // Add modifiers context if (member.IsAbstract) description.Append(". This is an abstract class"); else if (member.IsStatic) description.Append(". This is a static class"); return description.ToString(); } private string GenerateInterfaceDescription(EnhancedCodeMember member) { var name = member.Name; var cleanName = name.StartsWith("I") && char.IsUpper(name, 1) ? name.Substring(1) : name; return $"Defines the contract for {SplitCamelCase(cleanName).ToLower()} operations"; } private string GenerateMethodDescription(EnhancedCodeMember member) { var name = member.Name; var asyncPrefix = member.IsAsync ? "Asynchronously " : ""; // Common method patterns if (name.StartsWith("Get")) return $"{asyncPrefix}gets {SplitCamelCase(name.Substring(3)).ToLower()}"; else if (name.StartsWith("Set")) return $"{asyncPrefix}sets {SplitCamelCase(name.Substring(3)).ToLower()}"; else if (name.StartsWith("Create")) return $"{asyncPrefix}creates {SplitCamelCase(name.Substring(6)).ToLower()}"; else if (name.StartsWith("Update")) return $"{asyncPrefix}updates {SplitCamelCase(name.Substring(6)).ToLower()}"; else if (name.StartsWith("Delete") || name.StartsWith("Remove")) return $"{asyncPrefix}deletes {SplitCamelCase(name.Substring(6)).ToLower()}"; else if (name.StartsWith("Calculate")) return $"{asyncPrefix}calculates {SplitCamelCase(name.Substring(9)).ToLower()}"; else if (name.StartsWith("Process")) return $"{asyncPrefix}processes {SplitCamelCase(name.Substring(7)).ToLower()}"; else if (name.StartsWith("Execute")) return $"{asyncPrefix}executes {SplitCamelCase(name.Substring(7)).ToLower()}"; else if (name.StartsWith("Handle")) return $"{asyncPrefix}handles {SplitCamelCase(name.Substring(6)).ToLower()}"; else if (name.StartsWith("Parse")) return $"{asyncPrefix}parses {SplitCamelCase(name.Substring(5)).ToLower()}"; else if (name.StartsWith("Convert")) return $"{asyncPrefix}converts {SplitCamelCase(name.Substring(7)).ToLower()}"; else if (name.StartsWith("Validate")) return $"{asyncPrefix}validates {SplitCamelCase(name.Substring(8)).ToLower()}"; else if (name.StartsWith("Initialize") || name.StartsWith("Init")) return $"{asyncPrefix}initializes {SplitCamelCase(name.Replace("Initialize", "").Replace("Init", "")).ToLower()}"; else if (name.StartsWith("Build")) return $"{asyncPrefix}builds {SplitCamelCase(name.Substring(5)).ToLower()}"; else if (name.StartsWith("Configure")) return $"{asyncPrefix}configures {SplitCamelCase(name.Substring(9)).ToLower()}"; else if (name.StartsWith("Load")) return $"{asyncPrefix}loads {SplitCamelCase(name.Substring(4)).ToLower()}"; else if (name.StartsWith("Save")) return $"{asyncPrefix}saves {SplitCamelCase(name.Substring(4)).ToLower()}"; else if (name.StartsWith("Find")) return $"{asyncPrefix}finds {SplitCamelCase(name.Substring(4)).ToLower()}"; else if (name.StartsWith("Search")) return $"{asyncPrefix}searches for {SplitCamelCase(name.Substring(6)).ToLower()}"; else if (name.StartsWith("Check") || name.StartsWith("Is") || name.StartsWith("Has") || name.StartsWith("Can")) return $"{asyncPrefix}checks if {SplitCamelCase(name).ToLower()}"; else return $"{asyncPrefix}executes the {SplitCamelCase(name).ToLower()} operation"; } private string GeneratePropertyDescription(EnhancedCodeMember member) { var name = member.Name; var accessDescription = ""; if (member.HasGetter && member.HasSetter) accessDescription = "Gets or sets"; else if (member.HasGetter) accessDescription = "Gets"; else if (member.HasSetter) accessDescription = "Sets"; return $"{accessDescription} the {SplitCamelCase(name).ToLower()}"; } private string GenerateEventDescription(EnhancedCodeMember member) { var name = member.Name; return $"Occurs when {SplitCamelCase(name).ToLower()}"; } private string GenerateBasicDescription(EnhancedCodeMember member) { return $"{member.Type.Substring(0, 1).ToUpper() + member.Type.Substring(1)} for {member.Name}"; } private string GenerateIntelligentParameterDescription(ParameterInfo param, EnhancedCodeMember member) { var name = param.Name.ToLower(); var type = param.Type.ToLower(); // Common parameter patterns if (name.Contains("path") || name.Contains("filepath") || name.Contains("filename")) return "The file or directory path"; else if (name.Contains("id") || name.Contains("identifier")) return "The unique identifier"; else if (name.Contains("name")) return "The name value"; else if (name.Contains("count") || name.Contains("number")) return "The number of items"; else if (name.Contains("index")) return "The zero-based index"; else if (name.Contains("content") || name.Contains("data")) return "The content data"; else if (name.Contains("message") || name.Contains("text")) return "The message or text"; else if (name.Contains("url") || name.Contains("uri")) return "The URL address"; else if (name.Contains("token")) return "The authentication token"; else if (name.Contains("config") || name.Contains("settings")) return "The configuration settings"; else if (name.Contains("callback") || name.Contains("action")) return "The callback action to execute"; else if (name.Contains("predicate") || name.Contains("filter")) return "The filtering condition"; else if (type.Contains("bool")) return $"True to {SplitCamelCase(param.Name).ToLower()}, otherwise false"; else if (type.Contains("cancellation")) return "The cancellation token"; else return $"The {SplitCamelCase(param.Name).ToLower()} parameter"; } private string GenerateIntelligentReturnDescription(EnhancedCodeMember member) { var returnType = member.ReturnType.ToLower(); var methodName = member.Name.ToLower(); if (returnType == "task") return "A task representing the asynchronous operation"; else if (returnType.Contains("task<")) { var innerType = ExtractGenericType(member.ReturnType); return $"A task containing the {innerType.ToLower()} result"; } else if (returnType == "bool" || returnType == "boolean") { if (methodName.StartsWith("is") || methodName.StartsWith("has") || methodName.StartsWith("can") || methodName.StartsWith("check")) return "True if the condition is met, otherwise false"; else return "True if successful, otherwise false"; } else if (returnType == "string") return "The resulting string value"; else if (returnType == "int" || returnType == "integer") return "The resulting integer value"; else if (returnType.Contains("list") || returnType.Contains("collection") || returnType.Contains("enumerable")) return "A collection of results"; else if (methodName.StartsWith("get")) return $"The requested {SplitCamelCase(methodName.Substring(3)).ToLower()}"; else if (methodName.StartsWith("create")) return $"The created {SplitCamelCase(methodName.Substring(6)).ToLower()}"; else if (methodName.StartsWith("calculate")) return $"The calculated {SplitCamelCase(methodName.Substring(9)).ToLower()}"; else return $"The {member.ReturnType.ToLower()} result"; } // Helper methods continue... private async Task GenerateExampleDocumentation(List docs, EnhancedCodeMember member, string indent) { if (!ShouldIncludeExample(member)) return; docs.Add($"{indent}/// "); docs.Add($"{indent}/// "); switch (member.Type) { case "method": if (member.IsStatic) { docs.Add($"{indent}/// // Example usage:"); if (member.Parameters?.Any() == true) { var exampleParams = GenerateExampleParameters(member.Parameters); docs.Add($"{indent}/// var result = {member.Context?.ContainingTypeName}.{member.Name}({exampleParams});"); } else { docs.Add($"{indent}/// var result = {member.Context?.ContainingTypeName}.{member.Name}();"); } } else { docs.Add($"{indent}/// // Example usage:"); docs.Add($"{indent}/// var instance = new {member.Context?.ContainingTypeName}();"); if (member.Parameters?.Any() == true) { var exampleParams = GenerateExampleParameters(member.Parameters); docs.Add($"{indent}/// var result = instance.{member.Name}({exampleParams});"); } else { docs.Add($"{indent}/// var result = instance.{member.Name}();"); } } break; case "property": docs.Add($"{indent}/// // Example usage:"); docs.Add($"{indent}/// var instance = new {member.Context?.ContainingTypeName}();"); if (member.HasSetter) { docs.Add($"{indent}/// instance.{member.Name} = {GenerateExampleValue(member.ReturnType)};"); } if (member.HasGetter) { docs.Add($"{indent}/// var value = instance.{member.Name};"); } break; case "class": docs.Add($"{indent}/// // Example usage:"); docs.Add($"{indent}/// var instance = new {member.Name}();"); break; } docs.Add($"{indent}/// "); docs.Add($"{indent}/// "); } private string GenerateExampleParameters(List parameters) { return string.Join(", ", parameters.Select(p => GenerateExampleValue(p.Type))); } private string GenerateExampleValue(string type) { var lowerType = type.ToLower(); if (lowerType.Contains("string")) return "\"example\""; else if (lowerType.Contains("int") || lowerType.Contains("integer")) return "42"; else if (lowerType.Contains("bool")) return "true"; else if (lowerType.Contains("double") || lowerType.Contains("decimal")) return "3.14"; else if (lowerType.Contains("datetime")) return "DateTime.Now"; else if (lowerType.Contains("guid")) return "Guid.NewGuid()"; else return "null"; } private List GenerateExceptionDocumentation(EnhancedCodeMember member) { var exceptions = new List(); // Common exceptions based on method patterns if (member.Parameters?.Any(p => p.Type.Contains("string")) == true) { exceptions.Add(new ExceptionDocumentation { Type = "ArgumentNullException", Description = "Thrown when a required parameter is null" }); } if (member.Name.ToLower().Contains("file") || member.Parameters?.Any(p => p.Name.ToLower().Contains("path")) == true) { exceptions.Add(new ExceptionDocumentation { Type = "FileNotFoundException", Description = "Thrown when the specified file cannot be found" }); } if (member.Name.ToLower().Contains("parse") || member.Name.ToLower().Contains("convert")) { exceptions.Add(new ExceptionDocumentation { Type = "FormatException", Description = "Thrown when the input format is invalid" }); } return exceptions; } private List GenerateSeeAlsoReferences(EnhancedCodeMember member) { var references = new List(); // Add related types from base classes if (member.BaseTypes?.Any() == true) { references.AddRange(member.BaseTypes); } // Add related types from parameters if (member.Parameters?.Any() == true) { var complexTypes = member.Parameters .Where(p => !IsBuiltInType(p.Type)) .Select(p => p.Type) .Distinct(); references.AddRange(complexTypes); } // Add return type if it's a complex type if (!string.IsNullOrEmpty(member.ReturnType) && !IsBuiltInType(member.ReturnType)) { references.Add(member.ReturnType); } return references.Take(3).ToList(); // Limit to top 3 references } private bool ShouldIncludeExample(EnhancedCodeMember member) { // Include examples for public methods with parameters or complex return types return member.Accessibility == "public" && (member.Parameters?.Any() == true || (!string.IsNullOrEmpty(member.ReturnType) && !IsBuiltInType(member.ReturnType))); } private bool IsBuiltInType(string type) { var builtInTypes = new HashSet(StringComparer.OrdinalIgnoreCase) { "string", "int", "bool", "double", "float", "decimal", "char", "byte", "short", "long", "object", "void", "DateTime", "Guid", "TimeSpan" }; return builtInTypes.Contains(type.Split('<')[0].Trim()); } private string ExtractGenericType(string type) { var match = Regex.Match(type, @"<(.+?)>"); return match.Success ? match.Groups[1].Value : type; } private double CalculateDocumentationQuality(EnhancedDocumentationSuggestion suggestion, EnhancedCodeMember member) { double score = 0; // Base score for having documentation score += 20; // Score for summary var summaryLines = suggestion.DocumentationLines.Count(l => l.Contains("") || l.Contains("")); if (summaryLines >= 2) score += 25; // Score for parameter documentation if (member.Parameters?.Any() == true) { var paramDocCount = suggestion.DocumentationLines.Count(l => l.Contains(" l.Contains(""))) score += 15; } // Score for examples if (suggestion.DocumentationLines.Any(l => l.Contains(""))) score += 10; // Score for exception documentation if (suggestion.DocumentationLines.Any(l => l.Contains(" suggestions, EnhancedCodeAnalysis analysis) { var totalLines = suggestions.Sum(s => s.DocumentationLines.Count); var averageQuality = suggestions.Any() ? suggestions.Average(s => s.QualityScore) : 0; var typeBreakdown = suggestions .GroupBy(s => s.Member.Type) .ToDictionary(g => g.Key, g => g.Count()); return new { TotalMembersDocumented = suggestions.Count, TotalDocumentationLines = totalLines, AverageQualityScore = Math.Round(averageQuality, 1), TypeBreakdown = typeBreakdown, CoveragePercentage = analysis.TotalMembers > 0 ? Math.Round((double)suggestions.Count / analysis.TotalMembers * 100, 1) : 0 }; } private string ApplyDocumentationToCode(string originalContent, List suggestions) { var lines = originalContent.Split('\n').ToList(); // Sort by line number in reverse order to avoid line number shifting foreach (var suggestion in suggestions.OrderByDescending(s => s.Member.LineNumber)) { var insertIndex = suggestion.Member.LineNumber - 1; // Convert to 0-based index // Insert documentation lines before the member for (int i = suggestion.DocumentationLines.Count - 1; i >= 0; i--) { lines.Insert(insertIndex, suggestion.DocumentationLines[i]); } } return string.Join('\n', lines); } // Helper methods for parsing and analysis private HashSet GetAccessibilityFilter(string scope) { return scope.ToLower() switch { "public" => new HashSet { "public" }, "protected" => new HashSet { "public", "protected" }, "internal" => new HashSet { "public", "protected", "internal" }, "all" => new HashSet { "public", "protected", "internal", "private" }, _ => new HashSet { "public" } }; } private bool ShouldDocumentMember(SyntaxNode node, HashSet accessibilityFilter) { if (node is MemberDeclarationSyntax member) { var accessibility = GetAccessibility(member.Modifiers); return accessibilityFilter.Contains(accessibility); } return false; } private string GetAccessibility(SyntaxTokenList modifiers) { if (modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword))) return "public"; else if (modifiers.Any(m => m.IsKind(SyntaxKind.ProtectedKeyword))) return "protected"; else if (modifiers.Any(m => m.IsKind(SyntaxKind.InternalKeyword))) return "internal"; else if (modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))) return "private"; else return "private"; // Default accessibility } private bool HasDocumentation(SyntaxNode node) { return node.GetLeadingTrivia() .Any(trivia => trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia)); } private int GetIndentLevel(SyntaxNode node) { var og = node.GetText().Lines.FirstOrDefault(); var text = (og == null) ? "" : og.ToString(); int count = 0; foreach (char c in text) { if (c == '\t') count++; else if (c != ' ') break; } return count; } private List ExtractParameters(ParameterListSyntax parameterList) { return parameterList.Parameters.Select(p => new ParameterInfo { Name = p.Identifier.ValueText, Type = p.Type.ToString(), HasDefaultValue = p.Default != null, DefaultValue = p.Default?.Value?.ToString() }).ToList(); } private string SplitCamelCase(string input) { return Regex.Replace(input, "([A-Z])", " $1").Trim(); } private List AnalyzeMethodUsage(MethodDeclarationSyntax method) { var patterns = new List(); // Look for common patterns in method body var methodBody = method.Body?.ToString() ?? ""; if (methodBody.Contains("for") || methodBody.Contains("foreach") || methodBody.Contains("while")) patterns.Add("loop"); if (methodBody.Contains("await")) patterns.Add("async"); if (methodBody.Contains("try") || methodBody.Contains("catch")) patterns.Add("exception_handling"); if (methodBody.Contains("File.") || methodBody.Contains("Directory.")) patterns.Add("file_io"); if (methodBody.Contains("HttpClient") || methodBody.Contains("WebRequest")) patterns.Add("web_request"); return patterns; } private int CalculateMethodComplexity(MethodDeclarationSyntax method) { int complexity = 1; // Base complexity var decisionNodes = method.DescendantNodes().Where(node => node.IsKind(SyntaxKind.IfStatement) || node.IsKind(SyntaxKind.WhileStatement) || node.IsKind(SyntaxKind.ForStatement) || node.IsKind(SyntaxKind.ForEachStatement) || node.IsKind(SyntaxKind.SwitchStatement) || node.IsKind(SyntaxKind.CatchClause) ); complexity += decisionNodes.Count(); return complexity; } } // Supporting classes for enhanced documentation public class EnhancedCodeAnalysis { public string FilePath { get; set; } public List MembersNeedingDocumentation { get; set; } = new List(); public int TotalMembers { get; set; } } public class EnhancedCodeMember { public string Type { get; set; } public string Name { get; set; } public int LineNumber { get; set; } public string OriginalLine { get; set; } public int IndentLevel { get; set; } public string Accessibility { get; set; } public bool IsStatic { get; set; } public bool IsAbstract { get; set; } public bool IsAsync { get; set; } public bool IsOverride { get; set; } public bool IsVirtual { get; set; } public bool HasGetter { get; set; } public bool HasSetter { get; set; } public List BaseTypes { get; set; } = new List(); public List Parameters { get; set; } = new List(); public string ReturnType { get; set; } public MemberContext Context { get; set; } } public class MemberContext { public string ContainingTypeName { get; set; } public string Namespace { get; set; } public List UsagePatterns { get; set; } = new List(); public int ComplexityScore { get; set; } } public class EnhancedDocumentationSuggestion { public EnhancedCodeMember Member { get; set; } public List DocumentationLines { get; set; } = new List(); public double QualityScore { get; set; } } public class ExceptionDocumentation { public string Type { get; set; } public string Description { get; set; } } }