未验证 提交 5e12b9ca 编写于 作者: D David Poeschl 提交者: GitHub

Merge pull request #42942 from dpoeschl/FixLambdaParameterCompletionBug

Improve completion's type inference for parameters of lambdas being passed as arguments
......@@ -10104,11 +10104,77 @@ void M(SomeCollection<SomeItem> c)
}
}";
await VerifyItemExistsAsync(markup, "Substring");
await VerifyItemIsAbsentAsync(markup, "Substring");
await VerifyItemExistsAsync(markup, "A");
await VerifyItemExistsAsync(markup, "B");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")]
public async Task CompletionForLambdaWithOverloads2()
{
var markup = @"
using System;
class C
{
void M(Action<int> a) { }
void M(string s) { }
void Test()
{
M(p => p.$$);
}
}";
await VerifyItemIsAbsentAsync(markup, "Substring");
await VerifyItemExistsAsync(markup, "GetTypeCode");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")]
public async Task CompletionForLambdaWithOverloads3()
{
var markup = @"
using System;
class C
{
void M(Action<int> a) { }
void M(Action<string> a) { }
void Test()
{
M((int p) => p.$$);
}
}";
await VerifyItemIsAbsentAsync(markup, "Substring");
await VerifyItemExistsAsync(markup, "GetTypeCode");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")]
public async Task CompletionForLambdaWithOverloads4()
{
var markup = @"
using System;
class C
{
void M(Action<int> a) { }
void M(Action<string> a) { }
void Test()
{
M(p => p.$$);
}
}";
await VerifyItemExistsAsync(markup, "Substring");
await VerifyItemExistsAsync(markup, "GetTypeCode");
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(40216, "https://github.com/dotnet/roslyn/issues/40216")]
public async Task CompletionForLambdaPassedAsNamedArgumentAtDifferentPositionFromCorrespondingParameter1()
......
......@@ -8110,11 +8110,89 @@ Namespace VBTest
End Namespace
]]></code>.Value
Await VerifyItemExistsAsync(source, "Substring")
Await VerifyItemIsAbsentAsync(source, "Substring")
Await VerifyItemExistsAsync(source, "A")
Await VerifyItemExistsAsync(source, "B")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")>
Public Async Function CompletionForLambdaWithOverloads2() As Task
Dim source =
<code><![CDATA[
Imports System
Class C
Sub M(a As Action(Of Integer))
End Sub
Sub M(a As String)
End Sub
Sub Test()
M(Sub(a) a.$$)
End Sub
End Class
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "Substring")
Await VerifyItemExistsAsync(source, "GetTypeCode")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")>
Public Async Function CompletionForLambdaWithOverloads3() As Task
Dim source =
<code><![CDATA[
Imports System
Class C
Sub M(a As Action(Of Integer))
End Sub
Sub M(a As Action(Of String))
End Sub
Sub Test()
M(Sub(a as Integer) a.$$)
End Sub
End Class
]]></code>.Value
Await VerifyItemIsAbsentAsync(source, "Substring")
Await VerifyItemExistsAsync(source, "GetTypeCode")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(1056325, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1056325")>
Public Async Function CompletionForLambdaWithOverloads4() As Task
Dim source =
<code><![CDATA[
Imports System
Class C
Sub M(a As Action(Of Integer))
End Sub
Sub M(a As Action(Of String))
End Sub
Sub Test()
M(Sub(a) a.$$)
End Sub
End Class
]]></code>.Value
Await VerifyItemExistsAsync(source, "Substring")
Await VerifyItemExistsAsync(source, "GetTypeCode")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
<WorkItem(40216, "https://github.com/dotnet/roslyn/issues/40216")>
Public Async Function CompletionForLambdaPassedAsNamedArgumentAtDifferentPositionFromCorrespondingParameter1() As Task
......
......@@ -2,8 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
......@@ -38,6 +40,27 @@ public override ImmutableArray<ISymbol> GetSymbols()
: GetSymbolsForCurrentContext();
}
public override bool TryGetExplicitTypeOfLambdaParameter(SyntaxNode lambdaSyntax, int ordinalInLambda, [NotNullWhen(true)] out ITypeSymbol explicitLambdaParameterType)
{
if (lambdaSyntax.IsKind<ParenthesizedLambdaExpressionSyntax>(SyntaxKind.ParenthesizedLambdaExpression, out var parenthesizedLambdaSyntax))
{
var parameters = parenthesizedLambdaSyntax.ParameterList.Parameters;
if (parameters.Count > ordinalInLambda)
{
var parameter = parameters[ordinalInLambda];
if (parameter.Type != null)
{
explicitLambdaParameterType = _context.SemanticModel.GetTypeInfo(parameter.Type, _cancellationToken).Type;
return explicitLambdaParameterType != null;
}
}
}
// Non-parenthesized lambdas cannot explicitly specify the type of the single parameter
explicitLambdaParameterType = null;
return false;
}
private ImmutableArray<ISymbol> GetSymbolsForCurrentContext()
{
if (_context.IsGlobalStatementContext)
......
......@@ -4,6 +4,7 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
......@@ -36,6 +37,8 @@ internal abstract class AbstractRecommendationServiceRunner<TSyntaxContext>
public abstract ImmutableArray<ISymbol> GetSymbols();
public abstract bool TryGetExplicitTypeOfLambdaParameter(SyntaxNode lambdaSyntax, int ordinalInLambda, [NotNullWhen(returnValue: true)] out ITypeSymbol explicitLambdaParameterType);
// This code is to help give intellisense in the following case:
// query.Include(a => a.SomeProperty).ThenInclude(a => a.
// where there are more than one overloads of ThenInclude accepting different types of parameters.
......@@ -74,13 +77,22 @@ protected ImmutableArray<ISymbol> GetSymbols(IParameterSymbol parameter, int pos
var ordinalInInvocation = arguments.IndexOf(lambdaSyntax.Parent);
var expressionOfInvocationExpression = syntaxFactsService.GetExpressionOfInvocationExpression(invocationExpression);
// Get all members potentially matching the invocation expression.
// We filter them out based on ordinality later.
var candidateSymbols = _context.SemanticModel.GetMemberGroup(expressionOfInvocationExpression, _cancellationToken);
var parameterTypeSymbols = ImmutableArray<ITypeSymbol>.Empty;
// parameter.Ordinal is the ordinal within (a,b,c) => b.
// For candidate symbols of (a,b,c) => b., get types of all possible b.
var parameterTypeSymbols = GetTypeSymbols(candidateSymbols, argumentName, ordinalInInvocation, ordinalInLambda: parameter.Ordinal);
if (TryGetExplicitTypeOfLambdaParameter(lambdaSyntax, parameter.Ordinal, out var explicitLambdaParameterType))
{
parameterTypeSymbols = ImmutableArray.Create(explicitLambdaParameterType);
}
else
{
// Get all members potentially matching the invocation expression.
// We filter them out based on ordinality later.
var candidateSymbols = _context.SemanticModel.GetMemberGroup(expressionOfInvocationExpression, _cancellationToken);
// parameter.Ordinal is the ordinal within (a,b,c) => b.
// For candidate symbols of (a,b,c) => b., get types of all possible b.
parameterTypeSymbols = GetTypeSymbols(candidateSymbols, argumentName, ordinalInInvocation, ordinalInLambda: parameter.Ordinal);
}
// For each type of b., return all suitable members.
return parameterTypeSymbols
......@@ -141,10 +153,8 @@ private ImmutableArray<ITypeSymbol> GetTypeSymbols(ImmutableArray<ISymbol> candi
continue;
}
type = parameters[ordinalInLambda].Type;
builder.Add(parameters[ordinalInLambda].Type);
}
builder.Add(type);
}
}
......
......@@ -3,7 +3,9 @@
' See the LICENSE file in the project root for more information.
Imports System.Collections.Immutable
Imports System.Diagnostics.CodeAnalysis
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Recommendations
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
......@@ -54,6 +56,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
Return ImmutableArray(Of ISymbol).Empty
End Function
Public Overrides Function TryGetExplicitTypeOfLambdaParameter(lambdaSyntax As SyntaxNode, ordinalInLambda As Integer, <NotNullWhen(True)> ByRef explicitLambdaParameterType As ITypeSymbol) As Boolean
Dim lambdaExpressionSyntax = DirectCast(lambdaSyntax, LambdaExpressionSyntax)
Dim parameters = lambdaExpressionSyntax.SubOrFunctionHeader.ParameterList.Parameters
If parameters.Count > ordinalInLambda Then
Dim parameterSyntax = parameters(ordinalInLambda)
If parameterSyntax.AsClause IsNot Nothing Then
explicitLambdaParameterType = _context.SemanticModel.GetTypeInfo(parameterSyntax.AsClause.Type, _cancellationToken).Type
Return explicitLambdaParameterType IsNot Nothing
End If
End If
Return False
End Function
Private Function IsWritableFieldOrLocal(symbol As ISymbol) As Boolean
If symbol.Kind() = SymbolKind.Field Then
Dim field = DirectCast(symbol, IFieldSymbol)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册