display underline for diagnostics
This commit is contained in:
@@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using Microsoft.CodeAnalysis.MSBuild;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using NuGet.Packaging;
|
||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||
|
||||
namespace SharpIDE.Application.Features.Analysis;
|
||||
@@ -125,6 +126,23 @@ public static class RoslynAnalysis
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public static async Task<ImmutableArray<Diagnostic>> GetDocumentDiagnostics(SharpIdeFile fileModel)
|
||||
{
|
||||
await _solutionLoadedTcs.Task;
|
||||
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);
|
||||
//var document = _workspace!.CurrentSolution.GetDocument(fileModel.Path);
|
||||
Guard.Against.Null(document, nameof(document));
|
||||
|
||||
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
|
||||
Guard.Against.Null(semanticModel, nameof(semanticModel));
|
||||
|
||||
var diagnostics = semanticModel.GetDiagnostics(cancellationToken: cancellationToken);
|
||||
diagnostics = diagnostics.Where(d => d.Severity is not DiagnosticSeverity.Hidden).ToImmutableArray();
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public static async Task<ImmutableArray<CodeAction>> GetCodeFixesAsync(Diagnostic diagnostic)
|
||||
{
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
@@ -14,6 +14,17 @@ public interface IExpandableSharpIdeNode
|
||||
public interface IChildSharpIdeNode
|
||||
{
|
||||
public IExpandableSharpIdeNode Parent { get; set; }
|
||||
|
||||
// TODO: Profile/redesign
|
||||
public SharpIdeProjectModel? GetNearestProjectNode()
|
||||
{
|
||||
var current = this;
|
||||
while (current is not SharpIdeProjectModel && current?.Parent is not null)
|
||||
{
|
||||
current = current.Parent as IChildSharpIdeNode;
|
||||
}
|
||||
return current as SharpIdeProjectModel;
|
||||
}
|
||||
}
|
||||
|
||||
public class SharpIdeSolutionModel : ISharpIdeNode, IExpandableSharpIdeNode
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using Microsoft.Build.Locator;
|
||||
using Microsoft.CodeAnalysis.CodeFixes;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
using SharpIDE.Application.Features.Analysis;
|
||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||
|
||||
@@ -16,14 +12,18 @@ public partial class IdeRoot : Control
|
||||
{
|
||||
private Button _openSlnButton = null!;
|
||||
private FileDialog _fileDialog = null!;
|
||||
private SharpIdeCodeEdit _sharpIdeCodeEdit = null!;
|
||||
public override void _Ready()
|
||||
{
|
||||
MSBuildLocator.RegisterDefaults();
|
||||
|
||||
_openSlnButton = GetNode<Button>("%OpenSlnButton");
|
||||
_sharpIdeCodeEdit = GetNode<SharpIdeCodeEdit>("%SharpIdeCodeEdit");
|
||||
_fileDialog = GetNode<FileDialog>("%OpenSolutionDialog");
|
||||
_fileDialog.FileSelected += OnFileSelected;
|
||||
_openSlnButton.Pressed += () => _fileDialog.Visible = true;
|
||||
//_fileDialog.Visible = true;
|
||||
OnFileSelected(@"C:\Users\Matthew\Documents\Git\BlazorCodeBreaker\BlazorCodeBreaker.slnx");
|
||||
}
|
||||
|
||||
private async void OnFileSelected(string path)
|
||||
@@ -33,6 +33,12 @@ public partial class IdeRoot : Control
|
||||
GD.Print($"Selected: {path}");
|
||||
var solutionModel = await VsPersistenceMapper.GetSolutionModel(path);
|
||||
RoslynAnalysis.StartSolutionAnalysis(path);
|
||||
var infraProject = solutionModel.AllProjects.Single(s => s.Name == "Infrastructure");
|
||||
var diFile = infraProject.Files.Single(s => s.Name == "DependencyInjection.cs");
|
||||
var fileContents = await File.ReadAllTextAsync(diFile.Path);
|
||||
_sharpIdeCodeEdit.SetText(fileContents);
|
||||
var diagnostics = await RoslynAnalysis.GetDocumentDiagnostics(diFile);
|
||||
_sharpIdeCodeEdit.ProvideDiagnostics(diagnostics);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,7 @@ split_offset = 250
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SharpIdeCodeEdit" type="CodeEdit" parent="VBoxContainer/HBoxContainer/HSplitContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("2_rk34b")
|
||||
highlight_current_line = true
|
||||
@@ -56,7 +57,6 @@ gutters_draw_line_numbers = true
|
||||
code_completion_enabled = true
|
||||
auto_brace_completion_enabled = true
|
||||
script = ExtResource("2_qjf5e")
|
||||
HighlightStartOffset = 0
|
||||
|
||||
[node name="OpenSolutionDialog" type="FileDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Immutable;
|
||||
using Godot;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace SharpIDE.Godot;
|
||||
|
||||
@@ -7,15 +9,11 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
||||
[Signal]
|
||||
public delegate void CodeFixesRequestedEventHandler();
|
||||
|
||||
[Export]
|
||||
public int HighlightStartOffset = 0;
|
||||
|
||||
[Export]
|
||||
public int HighlightEndOffset = 0;
|
||||
|
||||
private int _currentLine;
|
||||
private int _selectionStartCol;
|
||||
private int _selectionEndCol;
|
||||
|
||||
private ImmutableArray<Diagnostic> _diagnostics = [];
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
@@ -44,18 +42,19 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
||||
int lineLength = GetLine(line).Length;
|
||||
caretStartCol = Mathf.Clamp(caretStartCol, 0, lineLength);
|
||||
caretEndCol = Mathf.Clamp(caretEndCol, 0, lineLength);
|
||||
|
||||
var charRect = GetRectAtLineColumn(line, caretEndCol);
|
||||
var charWidth = charRect.Size.X;
|
||||
|
||||
var startPos = GetPosAtLineColumn(line, caretStartCol);
|
||||
// GetRectAtLineColumn returns the rectangle for the character before the column passed in, or the first character if the column is 0.
|
||||
var startRect = GetRectAtLineColumn(line, caretStartCol);
|
||||
var endRect = GetRectAtLineColumn(line, caretEndCol);
|
||||
//DrawLine(startRect.Position, startRect.End, color);
|
||||
//DrawLine(endRect.Position, endRect.End, color);
|
||||
|
||||
var startPos = startRect.End;
|
||||
if (caretStartCol is 0)
|
||||
{
|
||||
startPos.X -= 9; // Seems to be a bug or intended "feature" of GetPosAtLineColumn
|
||||
startPos.X -= startRect.Size.X;
|
||||
}
|
||||
var endPos = GetPosAtLineColumn(line, caretEndCol);
|
||||
startPos.X += charWidth;
|
||||
endPos.X += charWidth;
|
||||
var endPos = endRect.End;
|
||||
startPos.Y -= 1;
|
||||
endPos.Y -= 1;
|
||||
DrawLine(startPos, endPos, color, thickness);
|
||||
@@ -63,7 +62,28 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
||||
public override void _Draw()
|
||||
{
|
||||
UnderlineRange(_currentLine, _selectionStartCol, _selectionEndCol, new Color(1, 0, 0));
|
||||
//UnderlineRange(_currentLine, 0, 7, new Color(1, 0, 0));
|
||||
foreach (var diagnostic in _diagnostics)
|
||||
{
|
||||
if (diagnostic.Location.IsInSource)
|
||||
{
|
||||
var mappedLineSpan = (diagnostic.Location.SourceTree?.GetMappedLineSpan(diagnostic.Location.SourceSpan))!.Value;
|
||||
var line = mappedLineSpan.StartLinePosition.Line;
|
||||
var startCol = mappedLineSpan.StartLinePosition.Character;
|
||||
var endCol = mappedLineSpan.EndLinePosition.Character;
|
||||
var color = diagnostic.Severity switch
|
||||
{
|
||||
DiagnosticSeverity.Error => new Color(1, 0, 0),
|
||||
DiagnosticSeverity.Warning => new Color(1, 1, 0),
|
||||
_ => new Color(0, 1, 0) // Info or other
|
||||
};
|
||||
UnderlineRange(line, startCol, endCol, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ProvideDiagnostics(ImmutableArray<Diagnostic> diagnostics)
|
||||
{
|
||||
_diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
private void OnCodeFixesRequested()
|
||||
|
||||
Reference in New Issue
Block a user