syntax highlighting refactor
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Composition.Hosting;
|
using System.Composition.Hosting;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
using Ardalis.GuardClauses;
|
using Ardalis.GuardClauses;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
@@ -439,6 +440,7 @@ public static class RoslynAnalysis
|
|||||||
return sharpIdeRazorSpans;
|
return sharpIdeRazorSpans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is expensive for files that have just been updated, making it suboptimal for real-time highlighting
|
||||||
public static async Task<IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)>> GetDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default)
|
public static async Task<IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)>> GetDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetDocumentSyntaxHighlighting)}");
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetDocumentSyntaxHighlighting)}");
|
||||||
@@ -684,12 +686,13 @@ public static class RoslynAnalysis
|
|||||||
|
|
||||||
public static async Task UpdateDocument(SharpIdeFile fileModel, string newContent)
|
public static async Task UpdateDocument(SharpIdeFile fileModel, string newContent)
|
||||||
{
|
{
|
||||||
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(UpdateDocument)}");
|
||||||
Guard.Against.Null(fileModel, nameof(fileModel));
|
Guard.Against.Null(fileModel, nameof(fileModel));
|
||||||
Guard.Against.NullOrEmpty(newContent, nameof(newContent));
|
Guard.Against.NullOrEmpty(newContent, nameof(newContent));
|
||||||
|
|
||||||
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
|
var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath);
|
||||||
|
|
||||||
var sourceText = SourceText.From(newContent);
|
var sourceText = SourceText.From(newContent, Encoding.UTF8);
|
||||||
var document = fileModel switch
|
var document = fileModel switch
|
||||||
{
|
{
|
||||||
{ IsRazorFile: true } => project.AdditionalDocuments.Single(s => s.FilePath == fileModel.Path),
|
{ IsRazorFile: true } => project.AdditionalDocuments.Single(s => s.FilePath == fileModel.Path),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis;
|
|||||||
using Microsoft.CodeAnalysis.Classification;
|
using Microsoft.CodeAnalysis.Classification;
|
||||||
using Microsoft.CodeAnalysis.CodeActions;
|
using Microsoft.CodeAnalysis.CodeActions;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
using SharpIDE.Application;
|
||||||
using SharpIDE.Application.Features.Analysis;
|
using SharpIDE.Application.Features.Analysis;
|
||||||
using SharpIDE.Application.Features.Debugging;
|
using SharpIDE.Application.Features.Debugging;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
@@ -207,25 +208,19 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
// GD.Print($"Selection changed to line {_currentLine}, start {_selectionStartCol}, end {_selectionEndCol}");
|
// GD.Print($"Selection changed to line {_currentLine}, start {_selectionStartCol}, end {_selectionEndCol}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ideally this method completes in < 35ms, to ~ handle 28 char/s spam typing
|
||||||
private async void OnTextChanged()
|
private async void OnTextChanged()
|
||||||
{
|
{
|
||||||
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
|
var __ = SharpIdeOtel.Source.StartActivity($"{nameof(SharpIdeCodeEdit)}.{nameof(OnTextChanged)}");
|
||||||
|
// Note that we are currently on the UI thread, so be very conscious of what we do here
|
||||||
|
// If we update the documents syntax highlighting here, we won't get any flashes of incorrect highlighting, most noticeable when inserting new lines
|
||||||
_currentFile.IsDirty.Value = true;
|
_currentFile.IsDirty.Value = true;
|
||||||
await Singletons.FileManager.UpdateFileTextInMemory(_currentFile, Text);
|
await Singletons.FileManager.UpdateFileTextInMemory(_currentFile, Text);
|
||||||
_ = Task.GodotRun(async () =>
|
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
||||||
{
|
var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile);
|
||||||
var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile);
|
SetSyntaxHighlightingModel(await syntaxHighlighting, await razorSyntaxHighlighting);
|
||||||
var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile);
|
__?.Dispose();
|
||||||
var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile);
|
_ = Task.GodotRun(async () => SetDiagnosticsModel(await RoslynAnalysis.GetDocumentDiagnostics(_currentFile)));
|
||||||
var slnDiagnostics = RoslynAnalysis.UpdateSolutionDiagnostics();
|
|
||||||
await Task.WhenAll(syntaxHighlighting, razorSyntaxHighlighting, diagnostics);
|
|
||||||
Callable.From(() =>
|
|
||||||
{
|
|
||||||
SetSyntaxHighlightingModel(syntaxHighlighting.Result, razorSyntaxHighlighting.Result);
|
|
||||||
SetDiagnosticsModel(diagnostics.Result);
|
|
||||||
}).CallDeferred();
|
|
||||||
await slnDiagnostics;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is now significantly slower, invoke -> text updated in editor
|
// TODO: This is now significantly slower, invoke -> text updated in editor
|
||||||
@@ -300,7 +295,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
_fileChangingSuppressBreakpointToggleEvent = false;
|
_fileChangingSuppressBreakpointToggleEvent = false;
|
||||||
});
|
});
|
||||||
await Task.WhenAll(syntaxHighlighting, razorSyntaxHighlighting, setTextTask); // Text must be set before setting syntax highlighting
|
await Task.WhenAll(syntaxHighlighting, razorSyntaxHighlighting, setTextTask); // Text must be set before setting syntax highlighting
|
||||||
SetSyntaxHighlightingModel(await syntaxHighlighting, await razorSyntaxHighlighting);
|
await this.InvokeAsync(async () => SetSyntaxHighlightingModel(await syntaxHighlighting, await razorSyntaxHighlighting));
|
||||||
SetDiagnosticsModel(await diagnostics);
|
SetDiagnosticsModel(await diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,18 +403,16 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
private void SetDiagnosticsModel(ImmutableArray<(FileLinePositionSpan fileSpan, Diagnostic diagnostic)> diagnostics)
|
private void SetDiagnosticsModel(ImmutableArray<(FileLinePositionSpan fileSpan, Diagnostic diagnostic)> diagnostics)
|
||||||
{
|
{
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
|
Callable.From(QueueRedraw).CallDeferred();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetSyntaxHighlightingModel(IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)> classifiedSpans, IEnumerable<SharpIdeRazorClassifiedSpan> razorClassifiedSpans)
|
private void SetSyntaxHighlightingModel(IEnumerable<(FileLinePositionSpan fileSpan, ClassifiedSpan classifiedSpan)> classifiedSpans, IEnumerable<SharpIdeRazorClassifiedSpan> razorClassifiedSpans)
|
||||||
{
|
{
|
||||||
_syntaxHighlighter.SetHighlightingData(classifiedSpans, razorClassifiedSpans);
|
_syntaxHighlighter.SetHighlightingData(classifiedSpans, razorClassifiedSpans);
|
||||||
Callable.From(() =>
|
//_syntaxHighlighter.ClearHighlightingCache();
|
||||||
{
|
_syntaxHighlighter.UpdateCache();
|
||||||
_syntaxHighlighter.ClearHighlightingCache();
|
SyntaxHighlighter = null;
|
||||||
//_syntaxHighlighter.UpdateCache();
|
SyntaxHighlighter = _syntaxHighlighter; // Reassign to trigger redraw
|
||||||
SyntaxHighlighter = null;
|
|
||||||
SyntaxHighlighter = _syntaxHighlighter; // Reassign to trigger redraw
|
|
||||||
}).CallDeferred();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCodeFixesRequested()
|
private void OnCodeFixesRequested()
|
||||||
|
|||||||
Reference in New Issue
Block a user