-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewritten command handling to separate responsibilities.
- Loading branch information
Showing
27 changed files
with
590 additions
and
432 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace MirrorSharp.Internal { | ||
public class Buffers { | ||
public char[] CharArray { get; } = new char[2048]; | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
MirrorSharp.Common/Internal/Commands/CommitCompletionHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public class CommitCompletionHandler : ICommandHandler { | ||
public IImmutableList<char> CommandIds { get; } = ImmutableList.Create('S'); | ||
|
||
public async Task ExecuteAsync(ArraySegment<byte> data, WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var itemIndex = FastConvert.Utf8ByteArrayToInt32(data); | ||
// ReSharper disable once PossibleNullReferenceException | ||
var item = session.CurrentCompletionList.Items[itemIndex]; | ||
var change = await session.CompletionService.GetChangeAsync(session.Document, item, cancellationToken: cancellationToken).ConfigureAwait(false); | ||
|
||
var writer = sender.StartJsonMessage("changes"); | ||
writer.WritePropertyStartArray("changes"); | ||
foreach (var textChange in change.TextChanges) { | ||
writer.WriteStartObject(); | ||
writer.WriteProperty("start", textChange.Span.Start); | ||
writer.WriteProperty("length", textChange.Span.Length); | ||
writer.WriteProperty("text", textChange.NewText); | ||
writer.WriteEndObject(); | ||
} | ||
writer.WriteEndArray(); | ||
await sender.SendJsonMessageAsync(cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
public bool CanChangeSession => false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using JetBrains.Annotations; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public interface ICommandHandler { | ||
[NotNull] IImmutableList<char> CommandIds { get; } | ||
[NotNull] Task ExecuteAsync(ArraySegment<byte> data, [NotNull] WorkSession session, [NotNull] ICommandResultSender sender, CancellationToken cancellationToken); | ||
bool CanChangeSession { get; } | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
MirrorSharp.Common/Internal/Commands/ICommandResultSender.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Newtonsoft.Json; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public interface ICommandResultSender { | ||
JsonWriter StartJsonMessage(string messageTypeName); | ||
Task SendJsonMessageAsync(CancellationToken cancellationToken); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public class MoveCursorHandler : ICommandHandler { | ||
public IImmutableList<char> CommandIds => ImmutableList.Create('M'); | ||
|
||
public Task ExecuteAsync(ArraySegment<byte> data, WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
session.CursorPosition = FastConvert.Utf8ByteArrayToInt32(data); | ||
return TaskEx.CompletedTask; | ||
} | ||
|
||
public bool CanChangeSession => true; | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
MirrorSharp.Common/Internal/Commands/ReplaceTextHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public class ReplaceTextHandler : ICommandHandler { | ||
public IImmutableList<char> CommandIds { get; } = ImmutableList.Create('P', 'R'); | ||
|
||
public Task ExecuteAsync(ArraySegment<byte> data, WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var endOffset = data.Offset + data.Count - 1; | ||
var partStart = data.Offset; | ||
|
||
int? start = null; | ||
int? length = null; | ||
int? cursorPosition = null; | ||
|
||
for (var i = data.Offset; i <= endOffset; i++) { | ||
if (data.Array[i] != (byte)':') | ||
continue; | ||
|
||
var part = new ArraySegment<byte>(data.Array, partStart, i - partStart); | ||
if (start == null) { | ||
start = FastConvert.Utf8ByteArrayToInt32(part); | ||
partStart = i + 1; | ||
continue; | ||
} | ||
|
||
if (length == null) { | ||
length = FastConvert.Utf8ByteArrayToInt32(part); | ||
partStart = i + 1; | ||
continue; | ||
} | ||
|
||
cursorPosition = FastConvert.Utf8ByteArrayToInt32(part); | ||
partStart = i + 1; | ||
break; | ||
} | ||
if (start == null || length == null || cursorPosition == null) | ||
throw new FormatException("Command arguments must be 'start:length:cursor:text'."); | ||
|
||
var text = Encoding.UTF8.GetString(data.Array, partStart, endOffset - partStart + 1); | ||
|
||
session.SourceText = session.SourceText.WithChanges(new TextChange(new TextSpan(start.Value, length.Value), text)); | ||
session.CursorPosition = cursorPosition.Value; | ||
return TaskEx.CompletedTask; | ||
} | ||
|
||
public bool CanChangeSession => true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public class SlowUpdateHandler : ICommandHandler { | ||
public IImmutableList<char> CommandIds { get; } = ImmutableList.Create('U'); | ||
|
||
public async Task ExecuteAsync(ArraySegment<byte> data, WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var compilation = await session.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); | ||
var diagnostics = await compilation.WithAnalyzers(session.Analyzers).GetAllDiagnosticsAsync(cancellationToken).ConfigureAwait(false); | ||
|
||
await SendSlowUpdateAsync(diagnostics, sender, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
private Task SendSlowUpdateAsync(ImmutableArray<Diagnostic> diagnostics, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var writer = sender.StartJsonMessage("slowUpdate"); | ||
writer.WritePropertyStartArray("diagnostics"); | ||
foreach (var diagnostic in diagnostics) { | ||
writer.WriteStartObject(); | ||
writer.WriteProperty("message", diagnostic.GetMessage()); | ||
writer.WriteProperty("severity", diagnostic.Severity.ToString("G").ToLowerInvariant()); | ||
writer.WritePropertyStartArray("tags"); | ||
foreach (var tag in diagnostic.Descriptor.CustomTags) { | ||
if (tag != WellKnownDiagnosticTags.Unnecessary) | ||
continue; | ||
writer.WriteValue(tag.ToLowerInvariant()); | ||
} | ||
writer.WriteEndArray(); | ||
writer.WritePropertyName("span"); | ||
writer.WriteSpan(diagnostic.Location.SourceSpan); | ||
writer.WriteEndObject(); | ||
} | ||
writer.WriteEndArray(); | ||
return sender.SendJsonMessageAsync(cancellationToken); | ||
} | ||
|
||
public bool CanChangeSession => false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Completion; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace MirrorSharp.Internal.Commands { | ||
public class TypeCharHandler : ICommandHandler { | ||
public IImmutableList<char> CommandIds { get; } = ImmutableList.Create('C'); | ||
|
||
public async Task ExecuteAsync(ArraySegment<byte> data, WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var @char = FastConvert.Utf8ByteArrayToChar(data, session.Buffers.CharArray); | ||
session.SourceText = session.SourceText.WithChanges( | ||
new TextChange(new TextSpan(session.CursorPosition, 0), FastConvert.CharToString(@char)) | ||
); | ||
session.CursorPosition += 1; | ||
|
||
if (!session.CompletionService.ShouldTriggerCompletion(session.SourceText, session.CursorPosition, CompletionTrigger.CreateInsertionTrigger(@char))) | ||
return; | ||
|
||
session.CurrentCompletionList = await session.CompletionService.GetCompletionsAsync(session.Document, session.CursorPosition, cancellationToken: cancellationToken).ConfigureAwait(false); | ||
if (session.CurrentCompletionList == null) | ||
return; | ||
|
||
await SendListAsync(session.CurrentCompletionList, sender, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
private Task SendListAsync(CompletionList completionList, ICommandResultSender sender, CancellationToken cancellationToken) { | ||
var writer = sender.StartJsonMessage("completions"); | ||
writer.WritePropertyStartObject("completions"); | ||
writer.WritePropertyName("span"); | ||
// ReSharper disable once PossibleNullReferenceException | ||
writer.WriteSpan(completionList.DefaultSpan); | ||
writer.WritePropertyStartArray("list"); | ||
foreach (var item in completionList.Items) { | ||
writer.WriteStartObject(); | ||
writer.WriteProperty("displayText", item.DisplayText); | ||
writer.WritePropertyStartArray("tags"); | ||
foreach (var tag in item.Tags) { | ||
writer.WriteValue(tag.ToLowerInvariant()); | ||
} | ||
writer.WriteEndArray(); | ||
if (item.Span != completionList.DefaultSpan) { | ||
writer.WritePropertyName("span"); | ||
writer.WriteSpan(item.Span); | ||
} | ||
writer.WriteEndObject(); | ||
} | ||
writer.WriteEndArray(); | ||
writer.WriteEndObject(); | ||
return sender.SendJsonMessageAsync(cancellationToken); | ||
} | ||
|
||
public bool CanChangeSession => true; | ||
} | ||
} |
Oops, something went wrong.