Skip to content

Commit

Permalink
Merge pull request #2385 from JoeRobich/add-inlayhints-textedits
Browse files Browse the repository at this point in the history
Add TextEdits support to InlayHints
  • Loading branch information
JoeRobich authored Apr 18, 2022
2 parents 04a561c + c7b3354 commit 4356617
Show file tree
Hide file tree
Showing 23 changed files with 234 additions and 143 deletions.
2 changes: 1 addition & 1 deletion build/Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<MicrosoftTestPackageVersion>17.0.0</MicrosoftTestPackageVersion>
<MSBuildPackageVersion>17.0.0</MSBuildPackageVersion>
<NuGetPackageVersion>6.2.0-preview.2.80</NuGetPackageVersion>
<RoslynPackageVersion>4.2.0-3.22169.1</RoslynPackageVersion>
<RoslynPackageVersion>4.3.0-1.22215.1</RoslynPackageVersion>
<XunitPackageVersion>2.4.1</XunitPackageVersion>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion src/OmniSharp.Abstractions/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ internal static class Configuration
{
public static bool ZeroBasedIndices = false;

public const string RoslynVersion = "4.2.0.0";
public const string RoslynVersion = "4.3.0.0";
public const string RoslynPublicKeyToken = "31bf3856ad364e35";

public readonly static string RoslynFeatures = GetRoslynAssemblyFullName("Microsoft.CodeAnalysis.Features");
Expand Down
64 changes: 61 additions & 3 deletions src/OmniSharp.Abstractions/Models/v1/InlayHints/InlayHint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,88 @@ namespace OmniSharp.Models.v1.InlayHints;

public sealed record InlayHint
{
/// <summary>
/// The position of this hint.
/// </summary>
public Point Position { get; set; }

/// <summary>
/// The label of this hint. A human readable string.
/// </summary>
public string Label { get; set; }

/// <summary>
/// The tooltip text when you hover over this item.
/// </summary>
public string? Tooltip { get; set; }

/// <summary>
/// Optional text edits that are performed when accepting this inlay hint.
/// </summary>
public LinePositionSpanTextChange[]? TextEdits { get; set; }

/// <summary>
/// A data entry field that is preserved on a inlay hint between a <see cref="InlayHintRequest" /> and a <see cref="InlayHintResolveRequest" />.
/// </summary>
public (string SolutionVersion, int Position) Data { get; set; }

#nullable enable
public override string ToString()
{
return $"InlineHint {{ {nameof(Position)} = {Position}, {nameof(Label)} = {Label}, {nameof(Tooltip)} = {Tooltip} }}";
var textEdits = TextEdits is null ? "null" : $"[ {string.Join<LinePositionSpanTextChange>(", ", TextEdits)} ]";
return $"InlayHint {{ {nameof(Position)} = {Position}, {nameof(Label)} = {Label}, {nameof(Tooltip)} = {Tooltip ?? "null"}, {nameof(TextEdits)} = {textEdits} }}";
}

public bool Equals(InlayHint? other)
{
if (ReferenceEquals(this, other)) return true;
if (other is null) return false;

return Position == other.Position && Label == other.Label && Tooltip == other.Tooltip;
return Position == other.Position
&& Label == other.Label
&& Tooltip == other.Tooltip
&& TextEditsEqual(TextEdits, other.TextEdits);
}

private static bool TextEditsEqual(LinePositionSpanTextChange[]? a, LinePositionSpanTextChange[]? b)
{
if (a is null)
{
return b is null;
}

if (b is null)
{
return false;
}

if (a.Length != b.Length)
{
return false;
}

for (int index = 0; index < a.Length; index++)
{
if (!a[index].Equals(b[index]))
{
return false;
}
}

return true;
}

public override int GetHashCode() => (Position, Label, Tooltip).GetHashCode();
public override int GetHashCode() => (Position, Label, Tooltip, TextEdits?.GetHashCode() ?? 0).GetHashCode();
}

public enum InlayHintKind
{
/// <summary>
/// An inlay hint that is for a type annotation.
/// </summary>
Type = 1,
/// <summary>
/// An inlay hint that is for a parameter.
/// </summary>
Parameter = 2,
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public override string ToString()
{
var displayText = NewText != null
? NewText.Replace("\r", @"\r").Replace("\n", @"\n").Replace("\t", @"\t")
: string.Empty;
: "null";

return $"StartLine={StartLine}, StartColumn={StartColumn}, EndLine={EndLine}, EndColumn={EndColumn}, NewText='{displayText}'";
return $"LinePositionSpanTextChange {{ StartLine={StartLine}, StartColumn={StartColumn}, EndLine={EndLine}, EndColumn={EndColumn}, NewText={displayText} }}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ public CompletionHandler(OmniSharpWorkspace workspace) : base(workspace)

protected override Task<CompletionResponse> TranslateResponse(CompletionResponse response, CompletionRequest request)
{
if (response.Items is { Count: > 0 })
{
// In some instances, formatting changes to generated Cake DSL are being
// included in the CompletionItem as AdditionalTextEdits. The short term
// fix is to remove AdditionalTextEdits for now.
foreach (var item in response.Items)
{
item.AdditionalTextEdits = null;
}
}

return response.TranslateAsync(Workspace, request);
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/OmniSharp.Http.Driver/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Workspaces" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Features" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp.Features" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand Down
10 changes: 5 additions & 5 deletions src/OmniSharp.LanguageServerProtocol/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Workspaces" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.Features" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp.Features" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Dataflow" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Text;
using OmniSharp.Extensions;
using OmniSharp.Models;
using OmniSharp.Models.v1.Completion;
using OmniSharp.Roslyn.CSharp.Helpers;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Utilities;
using System.Collections.Generic;
using System.Collections.Immutable;
Expand All @@ -17,7 +19,6 @@
using CSharpCompletionItem = Microsoft.CodeAnalysis.Completion.CompletionItem;
using CSharpCompletionList = Microsoft.CodeAnalysis.Completion.CompletionList;
using CSharpCompletionService = Microsoft.CodeAnalysis.Completion.CompletionService;
using OmniSharp.Extensions;

namespace OmniSharp.Roslyn.CSharp.Services.Completion
{
Expand Down Expand Up @@ -270,7 +271,7 @@ private static void GetCompletionInfo(
static void handleNonInsertsectingEdit(SourceText sourceText, ref List<LinePositionSpanTextChange>? additionalTextEdits, ref int? adjustedNewPosition, TextChange textChange)
{
additionalTextEdits ??= new();
additionalTextEdits.Add(GetChangeForTextAndSpan(textChange.NewText!, textChange.Span, sourceText));
additionalTextEdits.Add(TextChanges.Convert(sourceText, textChange));

if (adjustedNewPosition is int newPosition)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
Expand All @@ -19,11 +18,12 @@
using OmniSharp.Models.v1.Completion;
using OmniSharp.Options;
using OmniSharp.Roslyn.CSharp.Helpers;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Utilities;
using Roslyn.Utilities;
using CompletionItem = OmniSharp.Models.v1.Completion.CompletionItem;
using CompletionTriggerKind = OmniSharp.Models.v1.Completion.CompletionTriggerKind;
using CSharpCompletionService = Microsoft.CodeAnalysis.Completion.CompletionService;
using Roslyn.Utilities;

namespace OmniSharp.Roslyn.CSharp.Services.Completion
{
Expand Down Expand Up @@ -207,7 +207,7 @@ public async Task<CompletionResolveResponse> Handle(CompletionResolveRequest req
continue;
}

additionalChanges.Add(CompletionListBuilder.GetChangeForTextAndSpan(textChange.NewText, textChange.Span, sourceText));
additionalChanges.Add(TextChanges.Convert(sourceText, textChange));
}

request.Item.AdditionalTextEdits = additionalChanges;
Expand Down Expand Up @@ -273,7 +273,7 @@ public async Task<CompletionAfterInsertResponse> Handle(CompletionAfterInsertReq

return new CompletionAfterInsertResponse
{
Changes = finalChange.TextChanges.SelectAsArray(changedText, static (c, changedText) => CompletionListBuilder.GetChangeForTextAndSpan(c.NewText, c.Span, changedText)),
Changes = finalChange.TextChanges.SelectAsArray(changedText, static (c, changedText) => TextChanges.Convert(changedText, c)),
Line = finalPosition.Line,
Column = finalPosition.Column,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
using Microsoft.Extensions.Options;
using OmniSharp.Extensions;
using OmniSharp.Mef;
using OmniSharp.Models;
using OmniSharp.Models.v1.InlayHints;
using OmniSharp.Options;
using OmniSharp.Roslyn.CSharp.Helpers;
using OmniSharp.Roslyn.Utilities;

#nullable enable

Expand Down Expand Up @@ -139,6 +141,7 @@ public List<InlayHint> MapAndCacheHints(ImmutableArray<OmniSharpInlineHint> rosl
{
Label = string.Concat(hint.DisplayParts),
Position = text.GetPointFromPosition(hint.Span.End),
TextEdits = ConvertToTextChanges(hint.ReplacementTextChange, text),
Data = (solutionVersionString, position)
});

Expand All @@ -152,6 +155,13 @@ public List<InlayHint> MapAndCacheHints(ImmutableArray<OmniSharpInlineHint> rosl
return resultList;
}

internal static LinePositionSpanTextChange[]? ConvertToTextChanges(TextChange? textChange, SourceText sourceText)
{
return textChange.HasValue
? new[] { TextChanges.Convert(sourceText, textChange.Value) }
: null;
}

public bool TryGetFromCache(InlayHint hint, out OmniSharpInlineHint roslynHint, [NotNullWhen(true)] out Document? document)
{
(roslynHint, document) = (default, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.MetadataAsSource;
using OmniSharp.Extensions;
using OmniSharp.Options;
using OmniSharp.Roslyn.CSharp.Workers.Formatting;

namespace OmniSharp.Roslyn
{
Expand All @@ -13,9 +15,12 @@ public class MetadataExternalSourceService : BaseExternalSourceService, IExterna
{
private const string MetadataKey = "$Metadata$";

private readonly OmniSharpOptions _omnisharpOptions;

[ImportingConstructor]
public MetadataExternalSourceService() : base()
public MetadataExternalSourceService(OmniSharpOptions omnisharpOptions) : base()
{
_omnisharpOptions = omnisharpOptions;
}

public async Task<(Document document, string documentPath)> GetAndAddExternalSymbolDocument(Project project, ISymbol symbol, CancellationToken cancellationToken)
Expand Down Expand Up @@ -47,11 +52,13 @@ public MetadataExternalSourceService() : base()
var topLevelSymbol = symbol.GetTopLevelContainingNamedType();

var temporaryDocument = metadataProject.AddDocument(fileName, string.Empty);
var formattingOptions = await FormattingWorker.GetFormattingOptionsAsync(temporaryDocument, _omnisharpOptions);

document = await OmniSharpMetadataAsSourceService.AddSourceToAsync(
temporaryDocument,
await metadataProject.GetCompilationAsync(),
topLevelSymbol,
formattingOptions,
cancellationToken);

_cache.TryAdd(fileName, document);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,16 @@ private async Task<Document> FixSpecificDiagnosticIdAsync(Document document, str
};

var fixAllContext = OmniSharpCodeFixContextFactory.CreateFixAllContext(
document, document.Project, codeFixProvider, roslynScope, action.EquivalenceKey, ImmutableArray.Create(diagnosticId), _fixAllDiagnosticProvider,
_ => codeActionOptions, cancellationToken);
document,
primaryDiagnostic.Location.SourceSpan,
document.Project,
codeFixProvider,
roslynScope,
action.EquivalenceKey,
ImmutableArray.Create(diagnosticId),
_fixAllDiagnosticProvider,
_ => codeActionOptions,
cancellationToken);

_logger.LogTrace("Finding FixAll fix for {0}.", diagnosticId);
var fixes = await fixAllProvider.GetFixAsync(fixAllContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class CSharpDiagnosticWorkerWithAnalyzers : ICsDiagnosticWorker, IDisposa
private readonly OmniSharpOptions _options;
private readonly OmniSharpWorkspace _workspace;

private const int WorkerWait = 250;

public CSharpDiagnosticWorkerWithAnalyzers(
OmniSharpWorkspace workspace,
[ImportMany] IEnumerable<ICodeActionProvider> providers,
Expand Down Expand Up @@ -114,6 +116,15 @@ private async Task Worker(AnalyzerWorkType workType)
.Where(x => x.projectId != null)
.ToImmutableArray();

if (documents.IsEmpty)
{
_workQueue.WorkComplete(workType);

await Task.Delay(WorkerWait);

continue;
}

var documentCount = documents.Length;
var documentCountRemaining = documentCount;

Expand Down Expand Up @@ -157,7 +168,7 @@ void decrementDocumentCountRemaining()

_workQueue.WorkComplete(workType);

await Task.Delay(50);
await Task.Delay(WorkerWait);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -219,7 +230,7 @@ public async Task<IEnumerable<Diagnostic>> AnalyzeDocumentAsync(Document documen
Project project = document.Project;
var allAnalyzers = GetAnalyzersForProject(project);
var compilation = await project.GetCompilationAsync(cancellationToken);

cancellationToken.ThrowIfCancellationRequested();
return await AnalyzeDocument(project, allAnalyzers, compilation, CreateAnalyzerOptions(document.Project), document);
}
Expand Down
Loading

0 comments on commit 4356617

Please sign in to comment.