提交 38a54fad 编写于 作者: R Ravi Chande 提交者: GitHub

Merge pull request #12910 from rchande/fix12818

Fix #12818
......@@ -630,6 +630,34 @@ public async Task PartialInterfaceName()
await VerifyBuilderAsync(markup);
}
[WorkItem(12818, "https://github.com/dotnet/roslyn/issues/12818")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task UnwrapParamsArray()
{
var markup = @"
using System;
class C {
C(params Action<int>[] a) {
new C($$
}
}";
await VerifyBuilderAsync(markup);
}
[WorkItem(12818, "https://github.com/dotnet/roslyn/issues/12818")]
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task DoNotUnwrapRegularArray()
{
var markup = @"
using System;
class C {
C(Action<int>[] a) {
new C($$
}
}";
await VerifyNotBuilderAsync(markup);
}
private async Task VerifyNotBuilderAsync(string markup)
{
await VerifyWorkerAsync(markup, isBuilder: false);
......
......@@ -157,9 +157,20 @@ private bool IsLambdaExpression(SemanticModel semanticModel, int position, Synta
// If we're an argument to a function with multiple overloads,
// open the builder if any overload takes a delegate at our argument position
var inferredTypes = typeInferrer.InferTypes(semanticModel, position, cancellationToken: cancellationToken);
var inferredTypeInfo = typeInferrer.GetTypeInferenceInfo(semanticModel, position, cancellationToken: cancellationToken);
return inferredTypes.Any(type => type.GetDelegateType(semanticModel.Compilation).IsDelegateType());
return inferredTypeInfo.Any(type => GetDelegateType(type, semanticModel.Compilation).IsDelegateType());
}
private ITypeSymbol GetDelegateType(TypeInferenceInfo typeInferenceInfo, Compilation compilation)
{
ITypeSymbol typeSymbol = typeInferenceInfo.InferredType;
if (typeInferenceInfo.IsParams && typeInferenceInfo.InferredType.IsArrayType())
{
typeSymbol = ((IArrayTypeSymbol)typeInferenceInfo.InferredType).ElementType;
}
return typeSymbol.GetDelegateType(compilation);
}
}
}
......@@ -13,36 +13,37 @@ internal abstract class AbstractTypeInferenceService<TExpressionSyntax> : ITypeI
{
protected abstract class AbstractTypeInferrer
{
protected readonly CancellationToken CancellationToken;
protected readonly SemanticModel SemanticModel;
protected readonly Func<ITypeSymbol, bool> IsUsableTypeFunc;
protected readonly Func<TypeInferenceInfo, bool> IsUsableTypeFunc;
private readonly HashSet<TExpressionSyntax> _seenExpressionInferType = new HashSet<TExpressionSyntax>();
private readonly HashSet<TExpressionSyntax> _seenExpressionGetType = new HashSet<TExpressionSyntax>();
private static readonly Func<ITypeSymbol, bool> s_isNotNull = t => t != null;
private static readonly Func<TypeInferenceInfo, bool> s_isNotNull = t => t.InferredType != null;
protected AbstractTypeInferrer(SemanticModel semanticModel, CancellationToken cancellationToken)
{
this.SemanticModel = semanticModel;
this.CancellationToken = cancellationToken;
this.IsUsableTypeFunc = t => t != null && !IsUnusableType(t);
this.IsUsableTypeFunc = t => t.InferredType != null && !IsUnusableType(t.InferredType);
}
protected abstract IEnumerable<ITypeSymbol> InferTypesWorker_DoNotCallDirectly(int position);
protected abstract IEnumerable<ITypeSymbol> InferTypesWorker_DoNotCallDirectly(TExpressionSyntax expression);
protected abstract IEnumerable<ITypeSymbol> GetTypes_DoNotCallDirectly(TExpressionSyntax expression, bool objectAsDefault);
protected abstract IEnumerable<TypeInferenceInfo> InferTypesWorker_DoNotCallDirectly(int position);
protected abstract IEnumerable<TypeInferenceInfo> InferTypesWorker_DoNotCallDirectly(TExpressionSyntax expression);
protected abstract IEnumerable<TypeInferenceInfo> GetTypes_DoNotCallDirectly(TExpressionSyntax expression, bool objectAsDefault);
protected abstract bool IsUnusableType(ITypeSymbol arg);
protected Compilation Compilation => SemanticModel.Compilation;
public IEnumerable<ITypeSymbol> InferTypes(int position)
public IEnumerable<TypeInferenceInfo> InferTypes(int position)
{
var types = InferTypesWorker_DoNotCallDirectly(position);
return Filter(types);
}
public IEnumerable<ITypeSymbol> InferTypes(TExpressionSyntax expression, bool filterUnusable = true)
public IEnumerable<TypeInferenceInfo> InferTypes(TExpressionSyntax expression, bool filterUnusable = true)
{
if (expression != null)
{
......@@ -53,20 +54,20 @@ public IEnumerable<ITypeSymbol> InferTypes(TExpressionSyntax expression, bool fi
}
}
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
protected IEnumerable<ITypeSymbol> GetTypes(TExpressionSyntax expression, bool objectAsDefault = false)
protected IEnumerable<TypeInferenceInfo> GetTypes(TExpressionSyntax expression, bool objectAsDefault = false)
{
if (_seenExpressionGetType.Add(expression))
{
return GetTypes_DoNotCallDirectly(expression, objectAsDefault);
}
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
}
private IEnumerable<ITypeSymbol> Filter(IEnumerable<ITypeSymbol> types, bool filterUnusable = true)
private IEnumerable<TypeInferenceInfo> Filter(IEnumerable<TypeInferenceInfo> types, bool filterUnusable = true)
{
return types.Where(filterUnusable ? IsUsableTypeFunc : s_isNotNull)
.Distinct()
......@@ -95,10 +96,27 @@ protected IEnumerable<ITypeSymbol> ExpandParamsParameter(IParameterSymbol parame
public IEnumerable<ITypeSymbol> InferTypes(SemanticModel semanticModel, int position, CancellationToken cancellationToken)
{
return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(position);
return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(position).Select(t => t.InferredType);
}
public IEnumerable<ITypeSymbol> InferTypes(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken)
{
var result = new List<ITypeSymbol>();
var typeInferenceInfo = CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(expression as TExpressionSyntax);
foreach (var info in typeInferenceInfo)
{
result.Add(info.InferredType);
}
return result;
}
public IEnumerable<TypeInferenceInfo> GetTypeInferenceInfo(SemanticModel semanticModel, int position, CancellationToken cancellationToken)
{
return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(position);
}
public IEnumerable<TypeInferenceInfo> GetTypeInferenceInfo(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken)
{
return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(expression as TExpressionSyntax);
}
......
......@@ -24,5 +24,27 @@ internal interface ITypeInferenceService : ILanguageService
{
IEnumerable<ITypeSymbol> InferTypes(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken);
IEnumerable<ITypeSymbol> InferTypes(SemanticModel semanticModel, int position, CancellationToken cancellationToken);
IEnumerable<TypeInferenceInfo> GetTypeInferenceInfo(SemanticModel semanticModel, int position, CancellationToken cancellationToken);
IEnumerable<TypeInferenceInfo> GetTypeInferenceInfo(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken);
}
internal struct TypeInferenceInfo
{
public TypeInferenceInfo(ITypeSymbol type)
{
InferredType = type;
IsParams = false;
}
public TypeInferenceInfo(ITypeSymbol type, bool isParams)
{
InferredType = type;
IsParams = isParams;
}
public ITypeSymbol InferredType { get; }
public bool IsParams { get; }
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册