Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter out inline hint spans out of hte bounds of hte span we are querying for #76493

Merged
merged 3 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading