提交 0178773e 编写于 作者: J jmarolf

GFU in dictionary initializers (changeset 1381842)

上级 11e6790c
......@@ -461,60 +461,57 @@ private static bool CanReplace(ISymbol symbol)
}
}
// Technically, you could introduce an LValue for "Foo" in "Foo()" even if "Foo" binds
// to a method. (i.e. by assigning to a Func<...> type). However, this is so contrived
// and none of the features that use this extension consider this replaceable.
if (expression.Parent is InvocationExpressionSyntax)
switch (expression.Parent.CSharpKind())
{
if (expression.IsKind(SyntaxKind.IdentifierName) || expression is MemberAccessExpressionSyntax)
{
// If it looks like a method then we don't allow it to be replaced if it is a
// method (or if it doesn't bind).
case SyntaxKind.InvocationExpression:
// Technically, you could introduce an LValue for "Foo" in "Foo()" even if "Foo" binds
// to a method. (i.e. by assigning to a Func<...> type). However, this is so contrived
// and none of the features that use this extension consider this replaceable.
if (expression.IsKind(SyntaxKind.IdentifierName) || expression is MemberAccessExpressionSyntax)
{
// If it looks like a method then we don't allow it to be replaced if it is a
// method (or if it doesn't bind).
var symbolInfo = semanticModel.GetSymbolInfo(expression, cancellationToken);
return symbolInfo.GetBestOrAllSymbols().Any() && !symbolInfo.GetBestOrAllSymbols().Any(s => s is IMethodSymbol);
}
else
{
// It doesn't look like a method, we allow this to be replaced.
var symbolInfo = semanticModel.GetSymbolInfo(expression, cancellationToken);
return symbolInfo.GetBestOrAllSymbols().Any() && !symbolInfo.GetBestOrAllSymbols().Any(s => s is IMethodSymbol);
}
else
{
// It doesn't look like a method, we allow this to be replaced.
return true;
}
case SyntaxKind.IsExpression:
case SyntaxKind.AsExpression:
// Can't introduce a variable for the type portion of an is/as check.
var isOrAsExpression = (BinaryExpressionSyntax)expression.Parent;
return expression == isOrAsExpression.Left;
case SyntaxKind.EqualsValueClause:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.ArrayInitializerExpression:
case SyntaxKind.CollectionInitializerExpression:
case SyntaxKind.ConditionalAccessExpression:
case SyntaxKind.Argument:
case SyntaxKind.AttributeArgument:
case SyntaxKind.AnonymousObjectMemberDeclarator:
case SyntaxKind.ArrowExpressionClause:
case SyntaxKind.AwaitExpression:
case SyntaxKind.ReturnStatement:
case SyntaxKind.YieldReturnStatement:
case SyntaxKind.ParenthesizedLambdaExpression:
case SyntaxKind.SimpleLambdaExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.ArrayRankSpecifier:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.IfStatement:
case SyntaxKind.CatchFilterClause:
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.InterpolatedStringInsert:
case SyntaxKind.ComplexElementInitializerExpression:
// Direct parent kind checks.
return true;
}
}
// Direct parent kind checks.
if (expression.IsParentKind(SyntaxKind.ExpressionStatement) ||
expression.IsParentKind(SyntaxKind.EqualsValueClause) ||
expression.IsParentKind(SyntaxKind.ArrayInitializerExpression) ||
expression.IsParentKind(SyntaxKind.CollectionInitializerExpression) ||
expression.IsParentKind(SyntaxKind.ConditionalAccessExpression) ||
expression.IsParentKind(SyntaxKind.Argument) ||
expression.IsParentKind(SyntaxKind.AttributeArgument) ||
expression.IsParentKind(SyntaxKind.AnonymousObjectMemberDeclarator) ||
expression.IsParentKind(SyntaxKind.ArrowExpressionClause) ||
expression.IsParentKind(SyntaxKind.ReturnStatement) ||
expression.IsParentKind(SyntaxKind.YieldReturnStatement) ||
expression.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression) ||
expression.IsParentKind(SyntaxKind.SimpleLambdaExpression) ||
expression.IsParentKind(SyntaxKind.ParenthesizedExpression) ||
expression.IsParentKind(SyntaxKind.ArrayRankSpecifier) ||
expression.IsParentKind(SyntaxKind.ConditionalExpression) ||
expression.IsParentKind(SyntaxKind.IfStatement) ||
expression.IsParentKind(SyntaxKind.CatchFilterClause) ||
expression.IsParentKind(SyntaxKind.WhileStatement) ||
expression.IsParentKind(SyntaxKind.DoStatement) ||
expression.IsParentKind(SyntaxKind.ThrowStatement) ||
expression.IsParentKind(SyntaxKind.SwitchStatement) ||
expression.IsParentKind(SyntaxKind.InterpolatedStringInsert))
{
return true;
}
if (expression.IsParentKind(SyntaxKind.IsExpression) ||
expression.IsParentKind(SyntaxKind.AsExpression))
{
// Can't introduce a variable for the type portion of an is/as check.
var isOrAsExpression = (BinaryExpressionSyntax)expression.Parent;
return expression == isOrAsExpression.Left;
}
if (expression.Parent is PrefixUnaryExpressionSyntax)
......@@ -525,11 +522,6 @@ private static bool CanReplace(ISymbol symbol)
}
}
if (expression.Parent is AwaitExpressionSyntax)
{
return true;
}
var parentNonExpression = expression.GetAncestors().SkipWhile(n => n is ExpressionSyntax).FirstOrDefault();
var topExpression = expression;
while (topExpression.Parent is TypeSyntax)
......
......@@ -354,6 +354,22 @@ private IEnumerable<ITypeSymbol> InferTypeInArgument(ArgumentSyntax argument, Sy
}
}
if (argument.Parent.IsParentKind(SyntaxKind.ImplicitElementAccess) &&
argument.Parent.Parent.IsParentKind(SyntaxKind.SimpleAssignmentExpression) &&
argument.Parent.Parent.Parent.IsParentKind(SyntaxKind.ObjectInitializerExpression) &&
argument.Parent.Parent.Parent.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
{
var objectCreation = (ObjectCreationExpressionSyntax)argument.Parent.Parent.Parent.Parent.Parent;
var types = GetTypes(objectCreation);
if (types.Any(t => t is INamedTypeSymbol))
{
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t,
parameterIndex: 0));
}
}
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
}
......@@ -978,8 +994,8 @@ private IEnumerable<ITypeSymbol> InferTypeInPropertyDeclaration(PropertyDeclarat
Contract.Assert(propertyDeclaration?.Type != null, "Property type should never be null");
var typeInfo = this.semanticModel.GetTypeInfo(propertyDeclaration.Type);
return typeInfo.Type != null
? SpecializedCollections.SingletonEnumerable(typeInfo.Type)
return typeInfo.Type != null
? SpecializedCollections.SingletonEnumerable(typeInfo.Type)
: SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
}
......@@ -1116,6 +1132,13 @@ private IEnumerable<ITypeSymbol> InferTypeInIfStatement(IfStatementSyntax ifStat
else if (initializerExpression.IsParentKind(SyntaxKind.ArrayCreationExpression))
{
// new int[] { Foo() }
var symbols = this.semanticModel.GetCollectionInitializerSymbolInfo(initializerExpression).GetAllSymbols();
if (symbols.Any(t => t is INamedTypeSymbol))
{
return symbols.OfType<INamedTypeSymbol>();
}
var arrayCreation = (ArrayCreationExpressionSyntax)initializerExpression.Parent;
IEnumerable<ITypeSymbol> types = GetTypes(arrayCreation);
......@@ -1127,21 +1150,30 @@ private IEnumerable<ITypeSymbol> InferTypeInIfStatement(IfStatementSyntax ifStat
else if (initializerExpression.IsParentKind(SyntaxKind.ObjectCreationExpression))
{
// new List<T> { Foo() }
var objectCreation = (ObjectCreationExpressionSyntax)initializerExpression.Parent;
IEnumerable<ITypeSymbol> types = GetTypes(objectCreation);
if (types.Any(t => t is INamedTypeSymbol))
{
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t, parameterIndex: 0, parameterCount: 1));
GetCollectionElementType(t, parameterIndex: 0));
}
}
else if (
initializerExpression.IsParentKind(SyntaxKind.ComplexElementInitializerExpression) &&
initializerExpression.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
else if ((initializerExpression.IsParentKind(SyntaxKind.ComplexElementInitializerExpression) &&
initializerExpression.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression)) ||
(initializerExpression.IsKind(SyntaxKind.ComplexElementInitializerExpression) &&
initializerExpression.IsParentKind(SyntaxKind.CollectionInitializerExpression) &&
initializerExpression.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression)))
{
// new Dictionary<K,V> { { Foo(), ... } }
var objectCreation = (ObjectCreationExpressionSyntax)initializerExpression.Parent.Parent;
var symbols = this.semanticModel.GetCollectionInitializerSymbolInfo(initializerExpression).GetAllSymbols();
if (symbols.Any(t => t is INamedTypeSymbol))
{
return symbols.OfType<INamedTypeSymbol>();
}
IEnumerable<ITypeSymbol> types = GetTypes(objectCreation);
......@@ -1153,13 +1185,19 @@ private IEnumerable<ITypeSymbol> InferTypeInIfStatement(IfStatementSyntax ifStat
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t,
parameterIndex: parameterIndex,
parameterCount: initializerExpression.Expressions.Count));
parameterIndex: parameterIndex));
}
}
else if (initializerExpression.IsParentKind(SyntaxKind.SimpleAssignmentExpression))
{
// new Foo { a = { Foo() } }
var symbols = this.semanticModel.GetCollectionInitializerSymbolInfo(initializerExpression).GetAllSymbols();
if (symbols.Any(t => t is INamedTypeSymbol))
{
return symbols.OfType<INamedTypeSymbol>();
}
var assignExpression = (AssignmentExpressionSyntax)initializerExpression.Parent;
IEnumerable<ITypeSymbol> types = GetTypes(assignExpression.Left);
......@@ -1171,8 +1209,7 @@ private IEnumerable<ITypeSymbol> InferTypeInIfStatement(IfStatementSyntax ifStat
return types.OfType<INamedTypeSymbol>().SelectMany(t =>
GetCollectionElementType(t,
parameterIndex: parameterIndex,
parameterCount: initializerExpression.Expressions.Count));
parameterIndex: parameterIndex));
}
}
......@@ -1570,21 +1607,17 @@ private IEnumerable<ITypeSymbol> InferTypeInWhileStatement(WhileStatementSyntax
return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean));
}
private IEnumerable<ITypeSymbol> GetCollectionElementType(INamedTypeSymbol type, int parameterIndex, int parameterCount)
private IEnumerable<ITypeSymbol> GetCollectionElementType(INamedTypeSymbol type, int parameterIndex)
{
if (type != null)
{
// TODO(cyrusn): Move to use matt's Lookup method once he's checked in.
#if false
var addMethods = this.Binding.Lookup(leftType, "Add").OfType<MethodSymbol>();
var method = addMethods.Where(m => !m.IsStatic)
.Where(m => m.Arity == 0)
.Where(m => m.Parameters.Count == parameterCount).FirstOrDefault();
if (method != null)
{
return method.Parameters[parameterIndex].Type;
}
#endif
var parameters = type.GetAllTypeArguments();
var elementType = parameters.ElementAtOrDefault(parameterIndex);
if (elementType != null)
{
return SpecializedCollections.SingletonCollection(elementType);
}
}
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册