提交 161e37f8 编写于 作者: R Ravi Chande

Give the TypeInferenceService the ability to communicate additional info about the inferred type.

上级 01915211
......@@ -644,6 +644,20 @@ class 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,19 +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 inferredTypes = typeInferrer.GetTypeInferenceInfo(semanticModel, position, cancellationToken: cancellationToken);
return inferredTypes.Any(type => GetDelegateType(type, semanticModel.Compilation).IsDelegateType());
}
private ITypeSymbol GetDelegateType(ITypeSymbol type, Compilation compilation)
private ITypeSymbol GetDelegateType(TypeInferenceInfo type, Compilation compilation)
{
if (type.IsArrayType())
ITypeSymbol typeSymbol = type.InferredType;
if (type.IsParams && type.InferredType.IsArrayType())
{
type = ((IArrayTypeSymbol)type).ElementType;
typeSymbol = ((IArrayTypeSymbol)type.InferredType).ElementType;
}
return type.GetDelegateType(compilation);
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,20 @@ 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)
{
return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(expression as TExpressionSyntax).Select(t => t.InferredType);
}
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,28 @@ 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
{
private bool isParams;
public TypeInferenceInfo(ITypeSymbol type) : this()
{
InferredType = type;
}
public TypeInferenceInfo(ITypeSymbol type, bool isParams) : this()
{
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.
先完成此消息的编辑!
想要评论请 注册