Skip to content

Commit 077642f

Browse files
authored
Merge pull request #74978 from davidwengier/CohostImplemenationAndSpellCheck
Expose Go To Impl and Spell Check to Razor
2 parents 3bd322d + 5b1d55d commit 077642f

File tree

5 files changed

+87
-13
lines changed

5 files changed

+87
-13
lines changed

src/LanguageServer/Protocol/Extensions/ProtocolConversions.cs

+10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using Microsoft.CodeAnalysis.NavigateTo;
2222
using Microsoft.CodeAnalysis.Options;
2323
using Microsoft.CodeAnalysis.PooledObjects;
24+
using Microsoft.CodeAnalysis.SpellCheck;
2425
using Microsoft.CodeAnalysis.Tags;
2526
using Microsoft.CodeAnalysis.Text;
2627
using Roslyn.Text.Adornments;
@@ -583,6 +584,15 @@ public static LSP.DocumentHighlightKind HighlightSpanKindToDocumentHighlightKind
583584
}
584585
}
585586

587+
public static LSP.VSInternalSpellCheckableRangeKind SpellCheckSpanKindToSpellCheckableRangeKind(SpellCheckKind kind)
588+
=> kind switch
589+
{
590+
SpellCheckKind.Identifier => LSP.VSInternalSpellCheckableRangeKind.Identifier,
591+
SpellCheckKind.Comment => LSP.VSInternalSpellCheckableRangeKind.Comment,
592+
SpellCheckKind.String => LSP.VSInternalSpellCheckableRangeKind.String,
593+
_ => throw ExceptionUtilities.UnexpectedValue(kind),
594+
};
595+
586596
public static Glyph SymbolKindToGlyph(LSP.SymbolKind kind)
587597
{
588598
switch (kind)

src/LanguageServer/Protocol/Handler/References/FindImplementationsHandler.cs

+12-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.CodeAnalysis.Options;
1212
using Microsoft.CodeAnalysis.PooledObjects;
1313
using Microsoft.CodeAnalysis.Shared.Extensions;
14+
using Microsoft.CodeAnalysis.Text;
1415
using LSP = Roslyn.LanguageServer.Protocol;
1516

1617
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
@@ -33,26 +34,32 @@ public FindImplementationsHandler(IGlobalOptionService globalOptions)
3334

3435
public LSP.TextDocumentIdentifier GetTextDocumentIdentifier(LSP.TextDocumentPositionParams request) => request.TextDocument;
3536

36-
public async Task<LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken)
37+
public Task<LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken)
3738
{
3839
var document = context.GetRequiredDocument();
39-
var clientCapabilities = context.GetRequiredClientCapabilities();
40+
var supportsVisualStudioExtensions = context.GetRequiredClientCapabilities().HasVisualStudioLspCapability();
41+
var linePosition = ProtocolConversions.PositionToLinePosition(request.Position);
42+
var classificationOptions = _globalOptions.GetClassificationOptionsProvider();
43+
44+
return FindImplementationsAsync(document, linePosition, classificationOptions, supportsVisualStudioExtensions, cancellationToken);
45+
}
4046

47+
internal static async Task<LSP.Location[]> FindImplementationsAsync(Document document, LinePosition linePosition, OptionsProvider<ClassificationOptions> classificationOptions, bool supportsVisualStudioExtensions, CancellationToken cancellationToken)
48+
{
4149
var locations = ArrayBuilder<LSP.Location>.GetInstance();
4250

4351
var findUsagesService = document.GetRequiredLanguageService<IFindUsagesLSPService>();
44-
var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);
52+
var position = await document.GetPositionFromLinePositionAsync(linePosition, cancellationToken).ConfigureAwait(false);
4553

4654
var findUsagesContext = new SimpleFindUsagesContext();
47-
var classificationOptions = _globalOptions.GetClassificationOptionsProvider();
4855
await findUsagesService.FindImplementationsAsync(findUsagesContext, document, position, classificationOptions, cancellationToken).ConfigureAwait(false);
4956

5057
foreach (var definition in findUsagesContext.GetDefinitions())
5158
{
5259
var text = definition.GetClassifiedText();
5360
foreach (var sourceSpan in definition.SourceSpans)
5461
{
55-
if (clientCapabilities.HasVisualStudioLspCapability() == true)
62+
if (supportsVisualStudioExtensions)
5663
{
5764
locations.AddIfNotNull(await ProtocolConversions.DocumentSpanToLocationWithTextAsync(sourceSpan, text, cancellationToken).ConfigureAwait(false));
5865
}

src/LanguageServer/Protocol/Handler/SpellCheck/AbstractSpellCheckingHandler.cs

+1-8
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ private async IAsyncEnumerable<TReport> ComputeAndReportCurrentSpansAsync(
156156
{
157157
var textDocumentIdentifier = ProtocolConversions.DocumentToTextDocumentIdentifier(document);
158158

159-
var text = await document.GetValueTextAsync(cancellationToken).ConfigureAwait(false);
160159
var spans = await service.GetSpansAsync(document, cancellationToken).ConfigureAwait(false);
161160

162161
// protocol requires the results be in sorted order
@@ -186,13 +185,7 @@ private async IAsyncEnumerable<TReport> ComputeAndReportCurrentSpansAsync(
186185
{
187186
var span = spans[i];
188187

189-
var kind = span.Kind switch
190-
{
191-
SpellCheckKind.Identifier => VSInternalSpellCheckableRangeKind.Identifier,
192-
SpellCheckKind.Comment => VSInternalSpellCheckableRangeKind.Comment,
193-
SpellCheckKind.String => VSInternalSpellCheckableRangeKind.String,
194-
_ => throw ExceptionUtilities.UnexpectedValue(span.Kind),
195-
};
188+
var kind = ProtocolConversions.SpellCheckSpanKindToSpellCheckableRangeKind(span.Kind);
196189

197190
triples[triplesIndex++] = (int)kind;
198191
triples[triplesIndex++] = span.TextSpan.Start - lastSpanEnd;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Immutable;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.LanguageServer;
9+
using Microsoft.CodeAnalysis.PooledObjects;
10+
using Microsoft.CodeAnalysis.Shared.Extensions;
11+
using Microsoft.CodeAnalysis.SpellCheck;
12+
using Roslyn.LanguageServer.Protocol;
13+
14+
namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers;
15+
16+
internal static class SpellCheck
17+
{
18+
public readonly record struct SpellCheckSpan(int StartIndex, int Length, VSInternalSpellCheckableRangeKind Kind);
19+
20+
public static async Task<ImmutableArray<SpellCheckSpan>> GetSpellCheckSpansAsync(Document document, CancellationToken cancellationToken)
21+
{
22+
var service = document.GetLanguageService<ISpellCheckSpanService>();
23+
if (service is null)
24+
{
25+
return [];
26+
}
27+
28+
var spans = await service.GetSpansAsync(document, cancellationToken).ConfigureAwait(false);
29+
30+
using var _ = ArrayBuilder<SpellCheckSpan>.GetInstance(spans.Length, out var razorSpans);
31+
foreach (var span in spans)
32+
{
33+
var kind = ProtocolConversions.SpellCheckSpanKindToSpellCheckableRangeKind(span.Kind);
34+
razorSpans.Add(new SpellCheckSpan(span.TextSpan.Start, span.TextSpan.Length, kind));
35+
}
36+
37+
return razorSpans.ToImmutable();
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.CodeAnalysis.LanguageServer.Handler;
8+
using Microsoft.CodeAnalysis.Classification;
9+
using Microsoft.CodeAnalysis.Options;
10+
using Microsoft.CodeAnalysis.Text;
11+
12+
namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers;
13+
14+
using Location = Roslyn.LanguageServer.Protocol.Location;
15+
16+
internal static class GoToImplementation
17+
{
18+
public static Task<Location[]> FindImplementationsAsync(Document document, LinePosition linePosition, bool supportsVisualStudioExtensions, CancellationToken cancellationToken)
19+
{
20+
var globalOptions = document.Project.Solution.Services.ExportProvider.GetService<IGlobalOptionService>();
21+
var classificationOptions = globalOptions.GetClassificationOptionsProvider();
22+
23+
return FindImplementationsHandler.FindImplementationsAsync(document, linePosition, classificationOptions, supportsVisualStudioExtensions, cancellationToken);
24+
}
25+
}

0 commit comments

Comments
 (0)