get code fixes at position
This commit is contained in:
@@ -162,6 +162,35 @@ public static class RoslynAnalysis
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<ImmutableArray<CodeAction>> GetCodeFixesForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition)
|
||||||
|
{
|
||||||
|
var cancellationToken = CancellationToken.None;
|
||||||
|
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
|
||||||
|
var document = project.Documents.Single(s => s.FilePath == fileModel.Path);
|
||||||
|
Guard.Against.Null(document, nameof(document));
|
||||||
|
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
|
||||||
|
Guard.Against.Null(semanticModel, nameof(semanticModel));
|
||||||
|
|
||||||
|
var diagnostics = semanticModel.GetDiagnostics();
|
||||||
|
var sourceText = await document.GetTextAsync(cancellationToken);
|
||||||
|
var position = sourceText.Lines.GetPosition(linePosition);
|
||||||
|
var diagnosticsAtPosition = diagnostics
|
||||||
|
.Where(d => d.Location.IsInSource && d.Location.SourceSpan.Contains(position))
|
||||||
|
.ToImmutableArray();
|
||||||
|
|
||||||
|
ImmutableArray<CodeAction> codeActions = [];
|
||||||
|
foreach (var diagnostic in diagnosticsAtPosition)
|
||||||
|
{
|
||||||
|
var actions = await GetCodeFixesAsync(document, diagnostic);
|
||||||
|
codeActions = codeActions.AddRange(actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
var linePositionSpan = new LinePositionSpan(linePosition, new LinePosition(linePosition.Line, linePosition.Character + 1));
|
||||||
|
var selectedSpan = sourceText.Lines.GetTextSpan(linePositionSpan);
|
||||||
|
codeActions = codeActions.AddRange(await GetCodeRefactoringsAsync(document, selectedSpan));
|
||||||
|
return codeActions;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<ImmutableArray<(FileLinePositionSpan fileSpan, CodeAction codeAction)>> GetCodeFixesAsync(Diagnostic diagnostic)
|
public static async Task<ImmutableArray<(FileLinePositionSpan fileSpan, CodeAction codeAction)>> GetCodeFixesAsync(Diagnostic diagnostic)
|
||||||
{
|
{
|
||||||
var cancellationToken = CancellationToken.None;
|
var cancellationToken = CancellationToken.None;
|
||||||
@@ -175,7 +204,6 @@ public static class RoslynAnalysis
|
|||||||
private static async Task<ImmutableArray<CodeAction>> GetCodeFixesAsync(Document document, Diagnostic diagnostic)
|
private static async Task<ImmutableArray<CodeAction>> GetCodeFixesAsync(Document document, Diagnostic diagnostic)
|
||||||
{
|
{
|
||||||
var cancellationToken = CancellationToken.None;
|
var cancellationToken = CancellationToken.None;
|
||||||
var position = diagnostic.Location.SourceSpan.Start;
|
|
||||||
var codeActions = new List<CodeAction>();
|
var codeActions = new List<CodeAction>();
|
||||||
var context = new CodeFixContext(
|
var context = new CodeFixContext(
|
||||||
document,
|
document,
|
||||||
@@ -192,9 +220,16 @@ public static class RoslynAnalysis
|
|||||||
await provider.RegisterCodeFixesAsync(context);
|
await provider.RegisterCodeFixesAsync(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return codeActions.ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<ImmutableArray<CodeAction>> GetCodeRefactoringsAsync(Document document, TextSpan span)
|
||||||
|
{
|
||||||
|
var cancellationToken = CancellationToken.None;
|
||||||
|
var codeActions = new List<CodeAction>();
|
||||||
var refactorContext = new CodeRefactoringContext(
|
var refactorContext = new CodeRefactoringContext(
|
||||||
document,
|
document,
|
||||||
diagnostic.Location.SourceSpan,
|
span,
|
||||||
action => codeActions.Add(action),
|
action => codeActions.Add(action),
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
@@ -204,11 +239,6 @@ public static class RoslynAnalysis
|
|||||||
await provider.ComputeRefactoringsAsync(refactorContext).ConfigureAwait(false);
|
await provider.ComputeRefactoringsAsync(refactorContext).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codeActions.Count is not 0)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return codeActions.ToImmutableArray();
|
return codeActions.ToImmutableArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,13 +35,7 @@ public partial class IdeRoot : Control
|
|||||||
RoslynAnalysis.StartSolutionAnalysis(path);
|
RoslynAnalysis.StartSolutionAnalysis(path);
|
||||||
var infraProject = solutionModel.AllProjects.Single(s => s.Name == "Infrastructure");
|
var infraProject = solutionModel.AllProjects.Single(s => s.Name == "Infrastructure");
|
||||||
var diFile = infraProject.Files.Single(s => s.Name == "DependencyInjection.cs");
|
var diFile = infraProject.Files.Single(s => s.Name == "DependencyInjection.cs");
|
||||||
var fileContents = await File.ReadAllTextAsync(diFile.Path);
|
await _sharpIdeCodeEdit.SetSharpIdeFile(diFile);
|
||||||
_sharpIdeCodeEdit.SetText(fileContents);
|
|
||||||
var syntaxHighlighting = await RoslynAnalysis.GetDocumentSyntaxHighlighting(diFile);
|
|
||||||
_sharpIdeCodeEdit.ProvideSyntaxHighlighting(syntaxHighlighting);
|
|
||||||
var diagnostics = await RoslynAnalysis.GetDocumentDiagnostics(diFile);
|
|
||||||
_sharpIdeCodeEdit.ProvideDiagnostics(diagnostics);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Microsoft.Build.Utilities;
|
using Microsoft.Build.Utilities;
|
||||||
@@ -8,6 +9,7 @@ using Microsoft.CodeAnalysis;
|
|||||||
using Microsoft.CodeAnalysis.Classification;
|
using Microsoft.CodeAnalysis.Classification;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using SharpIDE.Application.Features.Analysis;
|
using SharpIDE.Application.Features.Analysis;
|
||||||
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using Task = System.Threading.Tasks.Task;
|
using Task = System.Threading.Tasks.Task;
|
||||||
|
|
||||||
namespace SharpIDE.Godot;
|
namespace SharpIDE.Godot;
|
||||||
@@ -21,6 +23,8 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
private int _selectionStartCol;
|
private int _selectionStartCol;
|
||||||
private int _selectionEndCol;
|
private int _selectionEndCol;
|
||||||
|
|
||||||
|
private SharpIdeFile _currentFile = null!;
|
||||||
|
|
||||||
private CustomHighlighter _syntaxHighlighter = new();
|
private CustomHighlighter _syntaxHighlighter = new();
|
||||||
private PopupMenu _popupMenu = null!;
|
private PopupMenu _popupMenu = null!;
|
||||||
|
|
||||||
@@ -45,6 +49,17 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
this.SyntaxHighlighter = _syntaxHighlighter;
|
this.SyntaxHighlighter = _syntaxHighlighter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task SetSharpIdeFile(SharpIdeFile file)
|
||||||
|
{
|
||||||
|
_currentFile = file;
|
||||||
|
var fileContents = await File.ReadAllTextAsync(_currentFile.Path);
|
||||||
|
SetText(fileContents);
|
||||||
|
var syntaxHighlighting = await RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
||||||
|
SetSyntaxHighlightingModel(syntaxHighlighting);
|
||||||
|
var diagnostics = await RoslynAnalysis.GetDocumentDiagnostics(_currentFile);
|
||||||
|
SetDiagnosticsModel(diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
public void UnderlineRange(int line, int caretStartCol, int caretEndCol, Color color, float thickness = 1.5f)
|
public void UnderlineRange(int line, int caretStartCol, int caretEndCol, Color color, float thickness = 1.5f)
|
||||||
{
|
{
|
||||||
if (line < 0 || line >= GetLineCount())
|
if (line < 0 || line >= GetLineCount())
|
||||||
@@ -104,11 +119,12 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProvideDiagnostics(ImmutableArray<(FileLinePositionSpan fileSpan, Diagnostic diagnostic)> diagnostics)
|
private void SetDiagnosticsModel(ImmutableArray<(FileLinePositionSpan fileSpan, Diagnostic diagnostic)> diagnostics)
|
||||||
{
|
{
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
}
|
}
|
||||||
public void ProvideSyntaxHighlighting(IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)> classifiedSpans)
|
|
||||||
|
private void SetSyntaxHighlightingModel(IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)> classifiedSpans)
|
||||||
{
|
{
|
||||||
_syntaxHighlighter.ClassifiedSpans = classifiedSpans;
|
_syntaxHighlighter.ClassifiedSpans = classifiedSpans;
|
||||||
Callable.From(() =>
|
Callable.From(() =>
|
||||||
@@ -135,14 +151,14 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var linePos = new LinePosition(caretLine, caretColumn);
|
var linePos = new LinePosition(caretLine, caretColumn);
|
||||||
var diagnostic = _diagnostics.FirstOrDefault(d =>
|
// var diagnostic = _diagnostics.FirstOrDefault(d =>
|
||||||
d.fileSpan.StartLinePosition <= linePos && d.fileSpan.EndLinePosition >= linePos);
|
// d.fileSpan.StartLinePosition <= linePos && d.fileSpan.EndLinePosition >= linePos);
|
||||||
if (diagnostic is (_, null)) return;
|
// if (diagnostic is (_, null)) return;
|
||||||
var codeActions = await RoslynAnalysis.GetCodeFixesAsync(diagnostic.diagnostic);
|
var codeActions = await RoslynAnalysis.GetCodeFixesForDocumentAtPosition(_currentFile, linePos);
|
||||||
Callable.From(() =>
|
Callable.From(() =>
|
||||||
{
|
{
|
||||||
_popupMenu.Clear();
|
_popupMenu.Clear();
|
||||||
foreach (var (index, (fileSpan, codeAction)) in codeActions.Index())
|
foreach (var (index, codeAction) in codeActions.Index())
|
||||||
{
|
{
|
||||||
_popupMenu.AddItem(codeAction.Title, index);
|
_popupMenu.AddItem(codeAction.Title, index);
|
||||||
//_popupMenu.SetItemMetadata(menuItem, codeAction);
|
//_popupMenu.SetItemMetadata(menuItem, codeAction);
|
||||||
|
|||||||
Reference in New Issue
Block a user