Skip to content

Commit

Permalink
Filter out inline hint spans out of hte bounds of hte span we are que…
Browse files Browse the repository at this point in the history
…rying for (#76493)
  • Loading branch information
CyrusNajmabadi authored Dec 18, 2024
2 parents 7edae94 + f87368f commit 1f096ee
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 21 deletions.
12 changes: 6 additions & 6 deletions src/EditorFeatures/Test2/InlineHints/AbstractInlineHintsTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@

Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Editor.InlineHints
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.InlineHints
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.[Shared].Utilities
Imports Microsoft.CodeAnalysis.Text

Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InlineHints
Expand All @@ -30,8 +26,10 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InlineHints
Dim snapshot = hostDocument.GetTextBuffer().CurrentSnapshot
Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id)
Dim tagService = document.GetRequiredLanguageService(Of IInlineParameterNameHintsService)

Dim span = If(hostDocument.SelectedSpans.Any(), hostDocument.SelectedSpans.Single(), New TextSpan(0, snapshot.Length))
Dim inlineHints = Await tagService.GetInlineHintsAsync(
document, New Text.TextSpan(0, snapshot.Length), options, displayOptions, displayAllOverride:=False, CancellationToken.None)
document, span, options, displayOptions, displayAllOverride:=False, CancellationToken.None)

Dim producedTags = From hint In inlineHints
Select hint.DisplayParts.GetFullText().TrimEnd() + hint.Span.ToString
Expand Down Expand Up @@ -88,8 +86,10 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.InlineHints
Dim snapshot = hostDocument.GetTextBuffer().CurrentSnapshot
Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id)
Dim tagService = document.GetRequiredLanguageService(Of IInlineTypeHintsService)

Dim span = If(hostDocument.SelectedSpans.Any(), hostDocument.SelectedSpans.Single(), New TextSpan(0, snapshot.Length))
Dim typeHints = Await tagService.GetInlineHintsAsync(
document, New Text.TextSpan(0, snapshot.Length), options, displayOptions, displayAllOverride:=ephemeral, CancellationToken.None)
document, span, options, displayOptions, displayAllOverride:=ephemeral, CancellationToken.None)

Dim producedTags = From hint In typeHints
Select hint.DisplayParts.GetFullText() + ":" + hint.Span.ToString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1255,5 +1255,48 @@ class C

Await VerifyParamHints(input, output)
End Function

<WpfFact>
Public Async Function TestOnlyProduceTagsWithinSelection() As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class A
{
int testMethod(int a, int b, int c, int d, int e)
{
return x;
}
void Main()
{
testMethod(1, [|{|b:|}2, {|c:|}3, {|d:|}4|], 5);
}
}
</Document>
</Project>
</Workspace>

Dim output =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class A
{
int testMethod(int a, int b, int c, int d, int e)
{
return x;
}
void Main()
{
testMethod(1, b: 2, c: 3, d: 4, 5);
}
}
</Document>
</Project>
</Workspace>

Await VerifyParamHints(input, output)
End Function
End Class
End Namespace
41 changes: 41 additions & 0 deletions src/EditorFeatures/Test2/InlineHints/CSharpInlineTypeHintsTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -848,5 +848,46 @@ class A

Await VerifyTypeHints(input, output)
End Function

<WpfFact>
Public Async Function TestOnlyProduceTagsWithinSelection() As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class A
{
void Main()
{
var a = 0;
[|var {|int :|}b = 0;
var {|int :|}c = 0;|]
var d = 0;
}
}
</Document>
</Project>
</Workspace>

Dim output =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class A
{
void Main()
{
var a = 0;
int b = 0;
int c = 0;
var d = 0;
}
}
</Document>
</Project>
</Workspace>

Await VerifyTypeHints(input, output)
End Function
End Class
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ namespace Microsoft.CodeAnalysis.CSharp.InlineHints;
/// The service to locate all positions where inline hints should be placed.
/// </summary>
[ExportLanguageService(typeof(IInlineHintsService), LanguageNames.CSharp), Shared]
internal class CSharpInlineHintsService : AbstractInlineHintsService
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpInlineHintsService()
{
}
}
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class CSharpInlineHintsService() : AbstractInlineHintsService;
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ void AddHintsIfAppropriate(SyntaxNode node)

foreach (var (position, argument, parameter, kind) in buffer)
{
// We get hints on *nodes* that intersect the passed in text span. However, while the full node may
// intersect the span, the positions of the all the sub-nodes in it that we make hints for (like the
// positions of the arguments in an invocation) may not. So, filter out any hints that aren't actually
// in the span we care about here.
if (!textSpan.IntersectsWith(position))
continue;

if (string.IsNullOrEmpty(parameter?.Name))
continue;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.InlineHints;

internal abstract class AbstractInlineTypeHintsService : IInlineTypeHintsService
{
protected static readonly SymbolDisplayFormat s_minimalTypeStyle = new SymbolDisplayFormat(
protected static readonly SymbolDisplayFormat s_minimalTypeStyle = new(
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes);

Expand Down Expand Up @@ -55,24 +55,31 @@ public async Task<ImmutableArray<InlineHint>> GetInlineHintsAsync(

foreach (var node in root.DescendantNodes(n => n.Span.IntersectsWith(textSpan)))
{
var hintOpt = TryGetTypeHint(
var hint = TryGetTypeHint(
semanticModel, node,
displayAllOverride,
forImplicitVariableTypes,
forLambdaParameterTypes,
forImplicitObjectCreation,
forCollectionExpressions,
cancellationToken);
if (hintOpt == null)
if (hint is not var (type, span, textChange, prefix, suffix))
continue;

var (type, span, textChange, prefix, suffix) = hintOpt.Value;
var spanStart = span.Start;

// We get hints on *nodes* that intersect the passed in text span. However, while the full node may
// intersect the span, the positions of the all the sub-nodes in it that we make hints for (like the
// positions of the arguments in an invocation) may not. So, filter out any hints that aren't actually
// in the span we care about here.
if (!textSpan.IntersectsWith(spanStart))
continue;

using var _2 = ArrayBuilder<SymbolDisplayPart>.GetInstance(out var finalParts);
finalParts.AddRange(prefix);

var parts = type.ToDisplayParts(s_minimalTypeStyle);
AddParts(anonymousTypeService, finalParts, parts, semanticModel, span.Start);
AddParts(anonymousTypeService, finalParts, parts, semanticModel, spanStart);

// If we have nothing to show, then don't bother adding this hint.
if (finalParts.All(p => string.IsNullOrWhiteSpace(p.ToString())))
Expand All @@ -83,7 +90,7 @@ public async Task<ImmutableArray<InlineHint>> GetInlineHintsAsync(

result.Add(new InlineHint(
span, taggedText, textChange, ranking: InlineHintsConstants.TypeRanking,
InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken), displayOptions)));
InlineHintHelpers.GetDescriptionFunction(spanStart, type.GetSymbolKey(cancellationToken), displayOptions)));
}

return result.ToImmutableAndClear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineHints
''' The service to locate all positions where inline hints should be placed.
''' </summary>
<ExportLanguageService(GetType(IInlineHintsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicInlineHintsService
Friend NotInheritable Class VisualBasicInlineHintsService
Inherits AbstractInlineHintsService

<ImportingConstructor>
Expand Down

0 comments on commit 1f096ee

Please sign in to comment.