diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..b9ff5d5
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,13 @@
+
+
+ net8.0
+ enable
+ enable
+ latest
+ Linux
+
+
+
+ $(MSBuildThisFileDirectory)
+
+
\ No newline at end of file
diff --git a/DocGpt.Roslyn/DocGpt.Roslyn.csproj b/DocGpt.Roslyn/DocGpt.Roslyn.csproj
index 37957d7..1138d3e 100644
--- a/DocGpt.Roslyn/DocGpt.Roslyn.csproj
+++ b/DocGpt.Roslyn/DocGpt.Roslyn.csproj
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/DocGpt.Roslyn/DocGptAnalyzer.cs b/DocGpt.Roslyn/DocGptAnalyzer.cs
index 85eb0f4..302e7ce 100644
--- a/DocGpt.Roslyn/DocGptAnalyzer.cs
+++ b/DocGpt.Roslyn/DocGptAnalyzer.cs
@@ -1,76 +1,75 @@
-namespace DocGpt
-{
- using System.Collections.Immutable;
+namespace DocGpt;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CSharp;
- using Microsoft.CodeAnalysis.CSharp.Syntax;
- using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
- using static Helpers;
+using System.Collections.Immutable;
- ///
- /// Represents a diagnostic analyzer for the DocGptAnalyzer class.
- ///
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class DocGptAnalyzer : DiagnosticAnalyzer
- {
- public const string DiagnosticId = "DGPT001";
+using static Helpers;
- // You can change these strings in the AnalyzerResources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat.
- // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Localizing%20Analyzers.md for more on localization
- private static readonly LocalizableString Title = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerTitle), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
- private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerMessageFormat), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
- private static readonly LocalizableString Description = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerDescription), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
- private const string Category = "Documentation";
+///
+/// Represents a diagnostic analyzer for the DocGptAnalyzer class.
+///
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public class DocGptAnalyzer : DiagnosticAnalyzer
+{
+ public const string DiagnosticId = "DGPT001";
- internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Info, isEnabledByDefault: true, description: Description);
+ // You can change these strings in the AnalyzerResources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat.
+ // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Localizing%20Analyzers.md for more on localization
+ private static readonly LocalizableString Title = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerTitle), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
+ private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerMessageFormat), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
+ private static readonly LocalizableString Description = new LocalizableResourceString(nameof(AnalyzerResources.AnalyzerDescription), AnalyzerResources.ResourceManager, typeof(AnalyzerResources));
+ private const string Category = "Documentation";
- ///
- public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
+ internal static readonly DiagnosticDescriptor Rule = new(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Info, isEnabledByDefault: true, description: Description);
- ///
- public override void Initialize(AnalysisContext context)
- {
- context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
- context.EnableConcurrentExecution();
+ ///
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
- foreach (SyntaxKind k in DocGptExecutor.SupportedSyntaxes)
- {
- context.RegisterSyntaxNodeAction(AnalyzeNode, k);
- }
- }
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
- ///
- /// Analyzes the given syntax node.
- /// If XML documentation exists for the node, no diagnostic is reported.
- /// If no XML documentation is found, a diagnostic for missing XML documentation is created and reported.
- ///
- private void AnalyzeNode(SyntaxNodeAnalysisContext context)
+ foreach (SyntaxKind k in DocGptExecutor.SupportedSyntaxes)
{
- SyntaxNode node = context.Node;
+ context.RegisterSyntaxNodeAction(AnalyzeNode, k);
+ }
+ }
- if (ShouldSkip(node))
- {
- return;
- }
+ ///
+ /// Analyzes the given syntax node.
+ /// If XML documentation exists for the node, no diagnostic is reported.
+ /// If no XML documentation is found, a diagnostic for missing XML documentation is created and reported.
+ ///
+ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
+ {
+ SyntaxNode node = context.Node;
- // Create and report the diagnostic
- (Location loc, var name) = getLocationAndName();
- var diagnostic = Diagnostic.Create(Rule, loc, node.Kind(), name);
- context.ReportDiagnostic(diagnostic);
+ if (ShouldSkip(node))
+ {
+ return;
+ }
- (Location, string) getLocationAndName()
- {
- if (node is FieldDeclarationSyntax fs)
- {
- SyntaxToken vi = fs.Declaration.Variables.First().Identifier;
- return (vi.GetLocation(), vi.ValueText);
- }
+ // Create and report the diagnostic
+ (Location loc, var name) = getLocationAndName();
+ var diagnostic = Diagnostic.Create(Rule, loc, node.Kind(), name);
+ context.ReportDiagnostic(diagnostic);
- ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(node);
- return (symbol.Locations[0], symbol.Name);
+ (Location, string) getLocationAndName()
+ {
+ if (node is FieldDeclarationSyntax fs)
+ {
+ SyntaxToken vi = fs.Declaration.Variables.First().Identifier;
+ return (vi.GetLocation(), vi.ValueText);
}
+
+ ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(node);
+ return (symbol.Locations[0], symbol.Name);
}
}
}
diff --git a/DocGpt.Roslyn/DocGptCodeAction.cs b/DocGpt.Roslyn/DocGptCodeAction.cs
index 1fb4978..92c1ddd 100644
--- a/DocGpt.Roslyn/DocGptCodeAction.cs
+++ b/DocGpt.Roslyn/DocGptCodeAction.cs
@@ -1,88 +1,84 @@
-namespace DocGpt
+namespace DocGpt;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.Formatting;
+
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Document = Microsoft.CodeAnalysis.Document;
+
+///
+/// This is an internal implementation of CodeAction, that uses OpenAI technology for generating summary text for a member's definition.
+/// Preview and Change operations are overridden to add XML documentation to a document at a specified location. This happens asynchronously.
+///
+///
+/// Initializes a new instance of the class.
+///
+/// The document associated with the action.
+/// The location within the document where the action is applied.
+internal class DocGptCodeAction(Document doc, Location location) : CodeAction
{
- using System.Collections.Generic;
- using System.Threading;
- using System.Threading.Tasks;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CodeActions;
- using Microsoft.CodeAnalysis.Formatting;
+ ///
+ public override string EquivalenceKey { get; } = nameof(CodeFixResources.CodeFixTitle);
- using Document = Microsoft.CodeAnalysis.Document;
+ ///
+ public override string Title { get; } = CodeFixResources.CodeFixTitle;
- ///
- /// This is an internal implementaion of CodeAction, that uses OpenAI technology for generating summary text for a member's definition.
- /// Preview and Change operations are overridden to add XML documentation to a document at a specified location. This happens asynchronously.
- ///
- internal class DocGptCodeAction : CodeAction
+ ///
+ protected override async Task> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
{
- private readonly Document _doc;
- private readonly Location _location;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The document associated with the action.
- /// The location within the document where the action is applied.
- public DocGptCodeAction(Document doc, Location location)
- {
- _doc = doc;
- _location = location;
- }
+ Microsoft.CodeAnalysis.Text.TextSpan diagnosticSpan = location.SourceSpan;
+ SyntaxNode? root = await doc.GetSyntaxRootAsync(cancellationToken);
+ SyntaxNode? node = root?.FindNode(diagnosticSpan);
- ///
- public override string EquivalenceKey { get; } = nameof(CodeFixResources.CodeFixTitle);
-
- ///
- public override string Title { get; } = CodeFixResources.CodeFixTitle;
-
- ///
- protected override async Task> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
- {
- Microsoft.CodeAnalysis.Text.TextSpan diagnosticSpan = _location.SourceSpan;
- SyntaxNode root = await _doc.GetSyntaxRootAsync(cancellationToken);
- SyntaxNode node = root.FindNode(diagnosticSpan);
+ return node is not null && DocGptExecutor.NodeTriggersGpt(node)
+ ? DocGptCodeActionPreviewOperation.InstanceArray
+ : await base.ComputePreviewOperationsAsync(cancellationToken);
+ }
- return DocGptExecutor.NodeTriggersGpt(node)
- ? DocGptCodeActionPreviewOperation.InstanceArray
- : await base.ComputePreviewOperationsAsync(cancellationToken);
- }
+ ///
+ protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken)
+ {
+ // Find the node at the diagnostic span
+ Microsoft.CodeAnalysis.Text.TextSpan diagnosticSpan = location.SourceSpan;
+ SyntaxNode? root = await doc.GetSyntaxRootAsync(cancellationToken);
+ SyntaxNode? node = root?.FindNode(diagnosticSpan);
- ///
- protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken)
+ if (node is not null)
{
- // Find the node at the diagnostic span
- Microsoft.CodeAnalysis.Text.TextSpan diagnosticSpan = _location.SourceSpan;
- SyntaxNode root = await _doc.GetSyntaxRootAsync(cancellationToken);
- SyntaxNode node = root.FindNode(diagnosticSpan);
-
(SyntaxNode newNode, SyntaxNode nodeToReplace) = await DocGptExecutor.AddXmlDocumentationAsync(node, cancellationToken);
- SyntaxNode newRoot = root.ReplaceNode(nodeToReplace, newNode);
+ SyntaxNode? newRoot = root?.ReplaceNode(nodeToReplace, newNode);
// return a document with the new syntax root
- return _doc.WithSyntaxRoot(Formatter.Format(newRoot, _doc.Project.Solution.Workspace));
+ return newRoot is null ? doc : doc.WithSyntaxRoot(Formatter.Format(newRoot, doc.Project.Solution.Workspace));
}
+ return doc;
+ }
+
+ ///
+ /// Represents an operation that sends the entire member's definition to the defined OpenAI endpoint for summary text generation and applies the result.
+ /// This operation provides a preview of such operation in its title property. The preview can be asynchronously obtained via GetPreviewAsync method.
+ ///
+ private class DocGptCodeActionPreviewOperation : PreviewOperation
+ {
+ public static readonly DocGptCodeActionPreviewOperation Instance = new();
+ public static readonly IEnumerable InstanceArray = [Instance];
+
///
- /// Represents an operation that sends the entire member's definition to the defined OpenAI endpoint for summary text generation and applies the result.
- /// This operation provides a preview of such operation in its title property. The preview can be asynchronously obtained via GetPreviewAsync method.
+ /// Initializes a new instance of the DocGptCodeActionPreviewOperation class.
///
- private class DocGptCodeActionPreviewOperation : PreviewOperation
- {
- public static readonly DocGptCodeActionPreviewOperation Instance = new DocGptCodeActionPreviewOperation();
- public static readonly IEnumerable InstanceArray = new CodeActionOperation[] { Instance };
-
- ///
- /// Initializes a new instance of the DocGptCodeActionPreviewOperation class.
- ///
- private DocGptCodeActionPreviewOperation() { }
+ private DocGptCodeActionPreviewOperation() { }
- ///
- public override string Title { get; } = "Sends this entire member's definition (and body) to the defined OpenAI endpoint for summary text generation and applies the result.";
+ ///
+ public override string Title { get; } = "Sends this entire member's definition (and body) to the defined OpenAI endpoint for summary text generation and applies the result.";
- ///
- public override Task