Skip to content

Commit

Permalink
Merge pull request #2463 from JoeRobich/add-lsp-handlers
Browse files Browse the repository at this point in the history
Add missing LSP Handlers
  • Loading branch information
JoeRobich authored Oct 26, 2022
2 parents e429cd6 + 89e2cec commit c214d90
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 21 deletions.
6 changes: 3 additions & 3 deletions src/OmniSharp.Abstractions/Models/v2/CodeFoldingBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public CodeFoldingBlock(Range textSpan, string type)

public class CodeFoldingBlockKinds
{
public static readonly string Comment = nameof(Comment);
public static readonly string Imports = nameof(Imports);
public static readonly string Region = nameof(Region);
public const string Comment = nameof(Comment);
public const string Imports = nameof(Imports);
public const string Region = nameof(Region);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Models;
using OmniSharp.Models.FindUsages;

namespace OmniSharp.LanguageServerProtocol.Handlers
{
internal sealed class OmniSharpDocumentHighlightHandler : DocumentHighlightHandlerBase
{
public static IEnumerable<IJsonRpcHandler> Enumerate(RequestHandlers handlers)
{
foreach (var (selector, handler) in handlers
.OfType<Mef.IRequestHandler<FindUsagesRequest, QuickFixResponse>>())
if (handler != null)
yield return new OmniSharpDocumentHighlightHandler(handler, selector);
}

private readonly Mef.IRequestHandler<FindUsagesRequest, QuickFixResponse> _findUsagesHandler;
private readonly DocumentSelector _documentSelector;

public OmniSharpDocumentHighlightHandler(Mef.IRequestHandler<FindUsagesRequest, QuickFixResponse> findUsagesHandler, DocumentSelector documentSelector)
{
_findUsagesHandler = findUsagesHandler;
_documentSelector = documentSelector;
}

public override async Task<DocumentHighlightContainer> Handle(DocumentHighlightParams request, CancellationToken token)
{
// TODO: Utilize Roslyn ExternalAccess to take advantage of HighlightingService.

var omnisharpRequest = new FindUsagesRequest
{
FileName = Helpers.FromUri(request.TextDocument.Uri),
Column = Convert.ToInt32(request.Position.Character),
Line = Convert.ToInt32(request.Position.Line),
OnlyThisFile = true,
ExcludeDefinition = false
};

var omnisharpResponse = await _findUsagesHandler.Handle(omnisharpRequest);

if (omnisharpResponse.QuickFixes is null)
{
return new DocumentHighlightContainer();
}

return new DocumentHighlightContainer(omnisharpResponse.QuickFixes.Select(x => new DocumentHighlight
{
Kind = DocumentHighlightKind.Read,
Range = x.ToRange()
}));
}

protected override DocumentHighlightRegistrationOptions CreateRegistrationOptions(DocumentHighlightCapability capability, ClientCapabilities clientCapabilities)
{
return new DocumentHighlightRegistrationOptions()
{
DocumentSelector = _documentSelector
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ protected override DocumentOnTypeFormattingRegistrationOptions CreateRegistratio
return new DocumentOnTypeFormattingRegistrationOptions()
{
DocumentSelector = _documentSelector,
FirstTriggerCharacter = ";",
// TODO: What should these be?
MoreTriggerCharacter = new[] {"}", ")"}
// Chose these triggers based on Roslyn's implementation https://github.com/dotnet/roslyn/blob/9e06c76c5ce94dc49821c5bd211c8292b3a984f0/src/Features/LanguageServer/Protocol/DefaultCapabilitiesProvider.cs#L71
FirstTriggerCharacter = "}",
MoreTriggerCharacter = new[] { ";", "\n" }
};
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Models.V2;
using static OmniSharp.LanguageServerProtocol.Helpers;

namespace OmniSharp.LanguageServerProtocol.Handlers
{
class OmniSharpFoldingRangenHandler : FoldingRangeHandlerBase
{
public static IEnumerable<IJsonRpcHandler> Enumerate(RequestHandlers handlers)
{
foreach (var (selector, handler) in handlers.OfType<Mef.IRequestHandler<BlockStructureRequest, BlockStructureResponse>>())
if (handler != null)
yield return new OmniSharpFoldingRangenHandler(handler, selector);
}

private readonly Mef.IRequestHandler<BlockStructureRequest, BlockStructureResponse> _definitionHandler;
private readonly DocumentSelector _documentSelector;

public OmniSharpFoldingRangenHandler(Mef.IRequestHandler<BlockStructureRequest, BlockStructureResponse> definitionHandler, DocumentSelector documentSelector)
{
_definitionHandler = definitionHandler;
_documentSelector = documentSelector;
}

public override async Task<Container<FoldingRange>> Handle(FoldingRangeRequestParam request, CancellationToken token)
{
var omnisharpRequest = new BlockStructureRequest()
{
FileName = FromUri(request.TextDocument.Uri)
};

var omnisharpResponse = await _definitionHandler.Handle(omnisharpRequest);

if (omnisharpResponse.Spans is null)
{
return new Container<FoldingRange>();
}

return new Container<FoldingRange>(omnisharpResponse.Spans.Select(block => new FoldingRange()
{
StartLine = block.Range.Start.Line,
StartCharacter = block.Range.Start.Column,
EndLine = block.Range.End.Line,
EndCharacter = block.Range.End.Column,
Kind = ConvertKind(block.Kind),
}));
}

private static FoldingRangeKind? ConvertKind(string kind)
{
return kind switch
{
CodeFoldingBlockKinds.Comment => FoldingRangeKind.Comment,
CodeFoldingBlockKinds.Imports => FoldingRangeKind.Imports,
CodeFoldingBlockKinds.Region => FoldingRangeKind.Region,
_ => null
};
}

protected override FoldingRangeRegistrationOptions CreateRegistrationOptions(FoldingRangeCapability capability, ClientCapabilities clientCapabilities)
{
return new FoldingRangeRegistrationOptions()
{
DocumentSelector = _documentSelector
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Models.SemanticHighlight;
using OmniSharp.Roslyn.CSharp.Services.SemanticHighlight;
using static OmniSharp.LanguageServerProtocol.Helpers;

namespace OmniSharp.LanguageServerProtocol.Handlers
{
class OmniSharpSemanticTokensHandler : SemanticTokensHandlerBase
{
public static IEnumerable<IJsonRpcHandler> Enumerate(RequestHandlers handlers)
{
foreach (var (selector, handler) in handlers.OfType<Mef.IRequestHandler<SemanticHighlightRequest, SemanticHighlightResponse>>())
if (handler != null)
yield return new OmniSharpSemanticTokensHandler(handler, selector);
}

private readonly Mef.IRequestHandler<SemanticHighlightRequest, SemanticHighlightResponse> _definitionHandler;
private readonly DocumentSelector _documentSelector;

private static readonly ImmutableDictionary<SemanticHighlightClassification, SemanticTokenType> _tokenTypes
= SemanticHighlightService._classificationMap
.OrderBy(kvp => kvp.Value)
.Aggregate(
new Dictionary<SemanticHighlightClassification, SemanticTokenType>(),
(dictionary, kvp) =>
{
if (!dictionary.ContainsKey(kvp.Value))
dictionary.Add(kvp.Value, new SemanticTokenType(kvp.Key));
return dictionary;
})
.ToImmutableDictionary();

private static readonly ImmutableDictionary<SemanticHighlightModifier, SemanticTokenModifier> _tokenModifiers
= SemanticHighlightService._modifierMap
.OrderBy(kvp => kvp.Value)
.Aggregate(
new Dictionary<SemanticHighlightModifier, SemanticTokenModifier>(),
(dictionary, kvp) =>
{
if (!dictionary.ContainsKey(kvp.Value))
dictionary.Add(kvp.Value, new SemanticTokenModifier(kvp.Key));
return dictionary;
})
.ToImmutableDictionary();

private readonly SemanticTokensLegend _legend = new()
{
TokenTypes = new Container<SemanticTokenType>(_tokenTypes.Values),
TokenModifiers = new Container<SemanticTokenModifier>(_tokenModifiers.Values),
};

public OmniSharpSemanticTokensHandler(Mef.IRequestHandler<SemanticHighlightRequest, SemanticHighlightResponse> definitionHandler, DocumentSelector documentSelector)
{
_definitionHandler = definitionHandler;
_documentSelector = documentSelector;
}

protected override async Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier, CancellationToken cancellationToken)
{
var omnisharpRequest = new SemanticHighlightRequest()
{
FileName = FromUri(identifier.TextDocument.Uri)
};

var omnisharpResponse = await _definitionHandler.Handle(omnisharpRequest);

if (omnisharpResponse.Spans is null)
{
return;
}

foreach (var span in omnisharpResponse.Spans)
{
var range = new Range(span.StartLine, span.StartColumn, span.EndLine, span.EndColumn);
builder.Push(range, _tokenTypes[span.Type], span.Modifiers.Select(modifier => _tokenModifiers[modifier]));
}
}

protected override Task<SemanticTokensDocument> GetSemanticTokensDocument(ITextDocumentIdentifierParams @params, CancellationToken cancellationToken)
{
return Task.FromResult(new SemanticTokensDocument(_legend));
}

protected override SemanticTokensRegistrationOptions CreateRegistrationOptions(SemanticTokensCapability capability, ClientCapabilities clientCapabilities)
{
return new SemanticTokensRegistrationOptions()
{
DocumentSelector = _documentSelector,
Full = new SemanticTokensCapabilityRequestFull
{
Delta = false
},
Range = true,
Legend = _legend
};
}
}
}
29 changes: 16 additions & 13 deletions src/OmniSharp.LanguageServerProtocol/LanguageServerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,22 +370,25 @@ internal static void RegisterHandlers(ILanguageServer server, CompositionHost co
var serializer = server.Services.GetRequiredService<ISerializer>();
server.Register(s =>
{
foreach (var handler in OmniSharpTextDocumentSyncHandler.Enumerate(handlers, workspace, documentVersions)
.Concat(OmniSharpTypeDefinitionHandler.Enumerate(handlers))
.Concat(OmniSharpDefinitionHandler.Enumerate(handlers))
.Concat(OmniSharpHoverHandler.Enumerate(handlers))
.Concat(OmniSharpCompletionHandler.Enumerate(handlers))
.Concat(OmniSharpSignatureHelpHandler.Enumerate(handlers))
.Concat(OmniSharpRenameHandler.Enumerate(handlers))
.Concat(OmniSharpWorkspaceSymbolsHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentSymbolHandler.Enumerate(handlers))
.Concat(OmniSharpReferencesHandler.Enumerate(handlers))
.Concat(OmniSharpImplementationHandler.Enumerate(handlers))
foreach (var handler in OmniSharpCodeActionHandler.Enumerate(handlers, serializer, server, documentVersions)
.Concat(OmniSharpCodeLensHandler.Enumerate(handlers))
.Concat(OmniSharpCodeActionHandler.Enumerate(handlers, serializer, server, documentVersions))
.Concat(OmniSharpCompletionHandler.Enumerate(handlers))
.Concat(OmniSharpDefinitionHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentFormattingHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentFormatRangeHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentOnTypeFormattingHandler.Enumerate(handlers)))
.Concat(OmniSharpDocumentOnTypeFormattingHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentHighlightHandler.Enumerate(handlers))
.Concat(OmniSharpDocumentSymbolHandler.Enumerate(handlers))
.Concat(OmniSharpFoldingRangenHandler.Enumerate(handlers))
.Concat(OmniSharpHoverHandler.Enumerate(handlers))
.Concat(OmniSharpImplementationHandler.Enumerate(handlers))
.Concat(OmniSharpReferencesHandler.Enumerate(handlers))
.Concat(OmniSharpRenameHandler.Enumerate(handlers))
.Concat(OmniSharpSemanticTokensHandler.Enumerate(handlers))
.Concat(OmniSharpSignatureHelpHandler.Enumerate(handlers))
.Concat(OmniSharpTextDocumentSyncHandler.Enumerate(handlers, workspace, documentVersions))
.Concat(OmniSharpTypeDefinitionHandler.Enumerate(handlers))
.Concat(OmniSharpWorkspaceSymbolsHandler.Enumerate(handlers)))
{
s.AddHandlers(handler);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class ClassifiedResult
public TextLineCollection Lines { get; set; }
}

private static readonly Dictionary<string, SemanticHighlightClassification> _classificationMap =
public static readonly Dictionary<string, SemanticHighlightClassification> _classificationMap =
new()
{
[ClassificationTypeNames.Comment] = SemanticHighlightClassification.Comment,
Expand Down Expand Up @@ -182,7 +182,7 @@ class ClassifiedResult
[ClassificationTypeNames.RegexOtherEscape] = SemanticHighlightClassification.RegexOtherEscape,
};

private static readonly Dictionary<string, SemanticHighlightModifier> _modifierMap =
public static readonly Dictionary<string, SemanticHighlightModifier> _modifierMap =
new()
{
[ClassificationTypeNames.StaticSymbol] = SemanticHighlightModifier.Static,
Expand Down

0 comments on commit c214d90

Please sign in to comment.