From 161e37f80af8f724026a6374c6b5b2fb92716df3 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Fri, 5 Aug 2016 09:57:17 -0700 Subject: [PATCH] Give the TypeInferenceService the ability to communicate additional info about the inferred type. --- .../SuggestionModeCompletionProviderTests.cs | 14 + .../CSharpSuggestionModeCompletionProvider.cs | 11 +- ...CSharpTypeInferenceService.TypeInferrer.cs | 452 +++++++++--------- .../AbstractTypeInferenceService.cs | 37 +- .../ITypeInferenceService.cs | 23 + ...lBasicTypeInferenceService.TypeInferrer.vb | 304 ++++++------ 6 files changed, 449 insertions(+), 392 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.cs index 475c0f575a6..478c1722879 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.cs @@ -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[] a) { + new C($$ + } +}"; + await VerifyNotBuilderAsync(markup); + } + private async Task VerifyNotBuilderAsync(string markup) { await VerifyWorkerAsync(markup, isBuilder: false); diff --git a/src/Features/CSharp/Portable/Completion/SuggestionMode/CSharpSuggestionModeCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/SuggestionMode/CSharpSuggestionModeCompletionProvider.cs index ca69920c45f..7932afdbd4a 100644 --- a/src/Features/CSharp/Portable/Completion/SuggestionMode/CSharpSuggestionModeCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/SuggestionMode/CSharpSuggestionModeCompletionProvider.cs @@ -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); } } } diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs index 56aa054bb53..9ffff8d845c 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.LanguageServices; namespace Microsoft.CodeAnalysis.CSharp { @@ -30,7 +31,7 @@ protected override bool IsUnusableType(ITypeSymbol otherSideType) (otherSideType.Name == string.Empty || otherSideType.Name == "var"); } - protected override IEnumerable GetTypes_DoNotCallDirectly(ExpressionSyntax expression, bool objectAsDefault) + protected override IEnumerable GetTypes_DoNotCallDirectly(ExpressionSyntax expression, bool objectAsDefault) { var types = GetTypesSimple(expression).Where(IsUsableTypeFunc); if (types.Any()) @@ -66,7 +67,7 @@ private static bool DecomposeBinaryOrAssignmentExpression(ExpressionSyntax expre return false; } - private IEnumerable GetTypesComplex(ExpressionSyntax expression) + private IEnumerable GetTypesComplex(ExpressionSyntax expression) { SyntaxToken operatorToken; ExpressionSyntax left, right; @@ -82,10 +83,10 @@ private IEnumerable GetTypesComplex(ExpressionSyntax expression) } // TODO(cyrusn): More cases if necessary. - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable GetTypesSimple(ExpressionSyntax expression) + private IEnumerable GetTypesSimple(ExpressionSyntax expression) { if (expression != null) { @@ -94,15 +95,15 @@ private IEnumerable GetTypesSimple(ExpressionSyntax expression) if (symbolInfo.CandidateReason != CandidateReason.WrongArity) { - ITypeSymbol type = typeInfo.Type; + TypeInferenceInfo type = new TypeInferenceInfo(typeInfo.Type); // If it bound to a method, try to get the Action/Func form of that method. - if (type == null && + if (type.InferredType == null && symbolInfo.GetAllSymbols().Count() == 1 && symbolInfo.GetAllSymbols().First().Kind == SymbolKind.Method) { var method = symbolInfo.GetAllSymbols().First(); - type = method.ConvertToType(this.Compilation); + type = new TypeInferenceInfo(method.ConvertToType(this.Compilation)); } if (IsUsableTypeFunc(type)) @@ -112,10 +113,10 @@ private IEnumerable GetTypesSimple(ExpressionSyntax expression) } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - protected override IEnumerable InferTypesWorker_DoNotCallDirectly( + protected override IEnumerable InferTypesWorker_DoNotCallDirectly( ExpressionSyntax expression) { expression = expression.WalkUpParentheses(); @@ -161,10 +162,10 @@ private IEnumerable GetTypesSimple(ExpressionSyntax expression) (UsingStatementSyntax usingStatement) => InferTypeInUsingStatement(usingStatement), (WhileStatementSyntax whileStatement) => InferTypeInWhileStatement(whileStatement), (YieldStatementSyntax yieldStatement) => InferTypeInYieldStatement(yieldStatement), - _ => SpecializedCollections.EmptyEnumerable()); + _ => SpecializedCollections.EmptyEnumerable()); } - private IEnumerable InferTypeInArrowExpressionClause(ArrowExpressionClauseSyntax arrowClause) + private IEnumerable InferTypeInArrowExpressionClause(ArrowExpressionClauseSyntax arrowClause) { if (arrowClause.IsParentKind(SyntaxKind.PropertyDeclaration)) { @@ -176,10 +177,10 @@ private IEnumerable InferTypeInArrowExpressionClause(ArrowExpressio return InferTypeInBaseMethodDeclaration(arrowClause.Parent as BaseMethodDeclarationSyntax); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - protected override IEnumerable InferTypesWorker_DoNotCallDirectly(int position) + protected override IEnumerable InferTypesWorker_DoNotCallDirectly(int position) { var syntaxTree = SemanticModel.SyntaxTree; var token = syntaxTree.FindTokenOnLeftOfPosition(position, CancellationToken); @@ -232,10 +233,10 @@ protected override IEnumerable InferTypesWorker_DoNotCallDirectly(i (UsingStatementSyntax usingStatement) => InferTypeInUsingStatement(usingStatement, token), (WhileStatementSyntax whileStatement) => InferTypeInWhileStatement(whileStatement, token), (YieldStatementSyntax yieldStatement) => InferTypeInYieldStatement(yieldStatement, token), - _ => SpecializedCollections.EmptyEnumerable()); + _ => SpecializedCollections.EmptyEnumerable()); } - private IEnumerable InferTypeInArgument( + private IEnumerable InferTypeInArgument( ArgumentSyntax argument, SyntaxToken? previousToken = null) { if (previousToken.HasValue) @@ -243,7 +244,7 @@ protected override IEnumerable InferTypesWorker_DoNotCallDirectly(i // If we have a position, then it must be after the colon in a named argument. if (argument.NameColon == null || argument.NameColon.ColonToken != previousToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } } @@ -299,7 +300,7 @@ protected override IEnumerable InferTypesWorker_DoNotCallDirectly(i var objectCreation = (ObjectCreationExpressionSyntax)argument.Parent.Parent.Parent.Parent.Parent; var types = GetTypes(objectCreation); - if (types.Any(t => t is INamedTypeSymbol)) + if (types.Any(t => t.InferredType is INamedTypeSymbol)) { return types.OfType().SelectMany(t => GetCollectionElementType(t, @@ -307,17 +308,17 @@ protected override IEnumerable InferTypesWorker_DoNotCallDirectly(i } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInAttributeArgument(AttributeArgumentSyntax argument, SyntaxToken? previousToken = null, ArgumentSyntax argumentOpt = null) + private IEnumerable InferTypeInAttributeArgument(AttributeArgumentSyntax argument, SyntaxToken? previousToken = null, ArgumentSyntax argumentOpt = null) { if (previousToken.HasValue) { // If we have a position, then it must be after the colon or equals in an argument. if (argument.NameColon == null || argument.NameColon.ColonToken != previousToken || argument.NameEquals.EqualsToken != previousToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } } @@ -331,17 +332,17 @@ private IEnumerable InferTypeInAttributeArgument(AttributeArgumentS } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInConstructorInitializer(ConstructorInitializerSyntax initializer, int index, ArgumentSyntax argument = null) + private IEnumerable InferTypeInConstructorInitializer(ConstructorInitializerSyntax initializer, int index, ArgumentSyntax argument = null) { var info = SemanticModel.GetSymbolInfo(initializer, CancellationToken); var methods = info.GetBestOrAllSymbols().OfType(); return InferTypeInArgument(index, methods, argument); } - private IEnumerable InferTypeInObjectCreationExpression(ObjectCreationExpressionSyntax expression, SyntaxToken previousToken) + private IEnumerable InferTypeInObjectCreationExpression(ObjectCreationExpressionSyntax expression, SyntaxToken previousToken) { // A couple of broken code scenarios where the new keyword in objectcreationexpression // appears to be a part of a subsequent assignment. For example: @@ -372,14 +373,14 @@ private IEnumerable InferTypeInObjectCreationExpression(ObjectCreat return InferTypes(expression); } - private IEnumerable InferTypeInObjectCreationExpression(ObjectCreationExpressionSyntax creation, int index, ArgumentSyntax argumentOpt = null) + private IEnumerable InferTypeInObjectCreationExpression(ObjectCreationExpressionSyntax creation, int index, ArgumentSyntax argumentOpt = null) { var info = SemanticModel.GetSymbolInfo(creation.Type, CancellationToken); var type = info.Symbol as INamedTypeSymbol; if (type == null) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (type.TypeKind == TypeKind.Delegate) @@ -388,14 +389,14 @@ private IEnumerable InferTypeInObjectCreationExpression(ObjectCreat // // They're actually instantiating a delegate, so the delegate type is // that type. - return SpecializedCollections.SingletonEnumerable(type); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(type)); } var constructors = type.InstanceConstructors.Where(m => m.Parameters.Length > index); return InferTypeInArgument(index, constructors, argumentOpt); } - private IEnumerable InferTypeInInvocationExpression( + private IEnumerable InferTypeInInvocationExpression( InvocationExpressionSyntax invocation, int index, ArgumentSyntax argumentOpt = null) { // Check all the methods that have at least enough arguments to support @@ -421,12 +422,12 @@ private IEnumerable InferTypeInObjectCreationExpression(ObjectCreat return InferTypeInArgument(index, methods, argumentOpt); } - private IEnumerable InferTypeInArgumentList(ArgumentListSyntax argumentList, SyntaxToken previousToken) + private IEnumerable InferTypeInArgumentList(ArgumentListSyntax argumentList, SyntaxToken previousToken) { // Has to follow the ( or a , if (previousToken != argumentList.OpenParenToken && previousToken.Kind() != SyntaxKind.CommaToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var invocation = argumentList.Parent as InvocationExpressionSyntax; @@ -450,15 +451,15 @@ private IEnumerable InferTypeInArgumentList(ArgumentListSyntax argu return InferTypeInConstructorInitializer(constructorInitializer, index); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInAttributeArgumentList(AttributeArgumentListSyntax attributeArgumentList, SyntaxToken previousToken) + private IEnumerable InferTypeInAttributeArgumentList(AttributeArgumentListSyntax attributeArgumentList, SyntaxToken previousToken) { // Has to follow the ( or a , if (previousToken != attributeArgumentList.OpenParenToken && previousToken.Kind() != SyntaxKind.CommaToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var attribute = attributeArgumentList.Parent as AttributeSyntax; @@ -468,17 +469,17 @@ private IEnumerable InferTypeInAttributeArgumentList(AttributeArgum return InferTypeInAttribute(attribute, index); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInAttribute(AttributeSyntax attribute, int index, AttributeArgumentSyntax argumentOpt = null) + private IEnumerable InferTypeInAttribute(AttributeSyntax attribute, int index, AttributeArgumentSyntax argumentOpt = null) { var info = SemanticModel.GetSymbolInfo(attribute, CancellationToken); var methods = info.GetBestOrAllSymbols().OfType(); return InferTypeInAttributeArgument(index, methods, argumentOpt); } - private IEnumerable InferTypeInElementAccessExpression( + private IEnumerable InferTypeInElementAccessExpression( ElementAccessExpressionSyntax elementAccess, int index, ArgumentSyntax argumentOpt = null) { var info = SemanticModel.GetTypeInfo(elementAccess.Expression, CancellationToken); @@ -501,15 +502,15 @@ private IEnumerable InferTypeInAttribute(AttributeSyntax attribute, // // This does, however, cover the more common cases of // arrays/pointers/errors/dynamic. - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } - private IEnumerable InferTypeInAttributeArgument(int index, IEnumerable methods, AttributeArgumentSyntax argumentOpt = null) + private IEnumerable InferTypeInAttributeArgument(int index, IEnumerable methods, AttributeArgumentSyntax argumentOpt = null) { return InferTypeInAttributeArgument(index, methods.Select(m => m.Parameters), argumentOpt); } - private IEnumerable InferTypeInArgument(int index, IEnumerable methods, ArgumentSyntax argumentOpt) + private IEnumerable InferTypeInArgument(int index, IEnumerable methods, ArgumentSyntax argumentOpt) { if (argumentOpt != null) { @@ -520,7 +521,7 @@ private IEnumerable InferTypeInArgument(int index, IEnumerable t.InferredType).ToList(); var instantiatedMethods = methods.Select(m => Instantiate(m, invocationTypes)).ToList(); // Now that we've instantiated the methods, filter down to the ones that @@ -637,7 +638,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol } } - private IEnumerable InferTypeInAttributeArgument( + private IEnumerable InferTypeInAttributeArgument( int index, IEnumerable> parameterizedSymbols, AttributeArgumentSyntax argumentOpt = null) @@ -653,7 +654,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol return InferTypeInArgument(index, parameterizedSymbols, name); } - private IEnumerable InferTypeInArgument( + private IEnumerable InferTypeInArgument( int index, IEnumerable> parameterizedSymbols, ArgumentSyntax argumentOpt) @@ -662,7 +663,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol return InferTypeInArgument(index, parameterizedSymbols, name); } - private IEnumerable InferTypeInArgument( + private IEnumerable InferTypeInArgument( int index, IEnumerable> parameterizedSymbols, string name) @@ -673,7 +674,7 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol { var parameters = parameterizedSymbols.SelectMany(m => m) .Where(p => p.Name == name) - .Select(p => p.Type); + .Select(p => new TypeInferenceInfo(p.Type, p.IsParams)); if (parameters.Any()) { return parameters; @@ -685,21 +686,22 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol // based on index. var q = from parameterSet in parameterizedSymbols where index < parameterSet.Length - select parameterSet[index].Type; + let param = parameterSet[index] + select new TypeInferenceInfo(param.Type, param.IsParams); return q; } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInArrayCreationExpression( + private IEnumerable InferTypeInArrayCreationExpression( ArrayCreationExpressionSyntax arrayCreationExpression, SyntaxToken? previousToken = null) { if (previousToken.HasValue && previousToken.Value != arrayCreationExpression.NewKeyword) { // Has to follow the 'new' keyword. - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (previousToken.HasValue && previousToken.Value.GetPreviousToken().Kind() == SyntaxKind.EqualsToken) @@ -721,24 +723,24 @@ private void DetermineTypeParameterMapping(ITypeSymbol inferredType, ITypeSymbol return outerTypes.Where(o => o is IArrayTypeSymbol); } - private IEnumerable InferTypeInArrayRankSpecifier(ArrayRankSpecifierSyntax arrayRankSpecifier, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInArrayRankSpecifier(ArrayRankSpecifierSyntax arrayRankSpecifier, SyntaxToken? previousToken = null) { // If we have a token, and it's not the open bracket or one of the commas, then no // inference. if (previousToken == arrayRankSpecifier.CloseBracketToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } - private IEnumerable InferTypeInArrayType(ArrayTypeSyntax arrayType, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInArrayType(ArrayTypeSyntax arrayType, SyntaxToken? previousToken = null) { if (previousToken.HasValue) { // TODO(cyrusn): NYI. Handle this appropriately if we need to. - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } // Bind the array type, then unwrap whatever we get back based on the number of rank @@ -746,47 +748,47 @@ private IEnumerable InferTypeInArrayType(ArrayTypeSyntax arrayType, var currentTypes = InferTypes(arrayType); for (var i = 0; i < arrayType.RankSpecifiers.Count; i++) { - currentTypes = currentTypes.OfType().Select(c => c.ElementType); + currentTypes = currentTypes.OfType().Select(c => new TypeInferenceInfo(c.ElementType)); } return currentTypes; } - private IEnumerable InferTypeInAttribute(AttributeSyntax attribute) + private IEnumerable InferTypeInAttribute(AttributeSyntax attribute) { - return SpecializedCollections.SingletonEnumerable(this.Compilation.AttributeType()); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.AttributeType())); } - private IEnumerable InferTypeInAttributeDeclaration(AttributeListSyntax attributeDeclaration, SyntaxToken? previousToken) + private IEnumerable InferTypeInAttributeDeclaration(AttributeListSyntax attributeDeclaration, SyntaxToken? previousToken) { // If we have a position, then it has to be after the open bracket. if (previousToken.HasValue && previousToken.Value != attributeDeclaration.OpenBracketToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.AttributeType()); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.AttributeType())); } - private IEnumerable InferTypeInAttributeTargetSpecifier( + private IEnumerable InferTypeInAttributeTargetSpecifier( AttributeTargetSpecifierSyntax attributeTargetSpecifier, SyntaxToken? previousToken) { // If we have a position, then it has to be after the colon. if (previousToken.HasValue && previousToken.Value != attributeTargetSpecifier.ColonToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.AttributeType()); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.AttributeType())); } - private IEnumerable InferTypeInBracketedArgumentList(BracketedArgumentListSyntax bracketedArgumentList, SyntaxToken previousToken) + private IEnumerable InferTypeInBracketedArgumentList(BracketedArgumentListSyntax bracketedArgumentList, SyntaxToken previousToken) { // Has to follow the [ or a , if (previousToken != bracketedArgumentList.OpenBracketToken && previousToken.Kind() != SyntaxKind.CommaToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var elementAccess = bracketedArgumentList.Parent as ElementAccessExpressionSyntax; @@ -797,7 +799,7 @@ private IEnumerable InferTypeInBracketedArgumentList(BracketedArgum elementAccess, index); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } private int GetArgumentListIndex(BaseArgumentListSyntax argumentList, SyntaxToken previousToken) @@ -838,7 +840,7 @@ private int GetArgumentListIndex(AttributeArgumentListSyntax attributeArgumentLi return (tokenIndex + 1) / 2; } - private IEnumerable InferTypeInBinaryOrAssignmentExpression(ExpressionSyntax binop, SyntaxToken operatorToken, ExpressionSyntax left, ExpressionSyntax right, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInBinaryOrAssignmentExpression(ExpressionSyntax binop, SyntaxToken operatorToken, ExpressionSyntax left, ExpressionSyntax right, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) { // If we got here through a token, then it must have actually been the binary // operator's token. @@ -860,7 +862,7 @@ private IEnumerable InferTypeInBinaryOrAssignmentExpression(Express if (onRightOfToken) { // x << Foo(), x >> Foo(), x <<= Foo(), x >>= Foo() - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } break; @@ -870,7 +872,7 @@ private IEnumerable InferTypeInBinaryOrAssignmentExpression(Express if (operatorToken.Kind() == SyntaxKind.AmpersandAmpersandToken || operatorToken.Kind() == SyntaxKind.BarBarToken) { - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } // Try to figure out what's on the other side of the binop. If we can, then just that @@ -909,9 +911,9 @@ private IEnumerable InferTypeInBinaryOrAssignmentExpression(Express // is the case where the other side was also unknown. So we walk one higher and if // we get a delegate or a string type, then use that type here. var parentTypes = InferTypes(binop); - if (parentTypes.Any(parentType => parentType.SpecialType == SpecialType.System_String || parentType.TypeKind == TypeKind.Delegate)) + if (parentTypes.Any(parentType => parentType.InferredType.SpecialType == SpecialType.System_String || parentType.InferredType.TypeKind == TypeKind.Delegate)) { - return parentTypes.Where(parentType => parentType.SpecialType == SpecialType.System_String || parentType.TypeKind == TypeKind.Delegate); + return parentTypes.Where(parentType => parentType.InferredType.SpecialType == SpecialType.System_String || parentType.InferredType.TypeKind == TypeKind.Delegate); } } @@ -940,58 +942,58 @@ private IEnumerable InferTypeInBinaryOrAssignmentExpression(Express case SyntaxKind.GreaterThanGreaterThanToken: case SyntaxKind.LessThanLessThanEqualsToken: case SyntaxKind.GreaterThanGreaterThanEqualsToken: - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); case SyntaxKind.BarEqualsToken: case SyntaxKind.AmpersandEqualsToken: // NOTE(cyrusn): |= and &= can be used for both ints and bools However, in the // case where there isn't enough information to determine which the user wanted, // I'm just defaulting to bool based on personal preference. - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInCastExpression(CastExpressionSyntax castExpression, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInCastExpression(CastExpressionSyntax castExpression, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) { if (expressionOpt != null && castExpression.Expression != expressionOpt) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } // If we have a position, then it has to be after the close paren. if (previousToken.HasValue && previousToken.Value != castExpression.CloseParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } return this.GetTypes(castExpression.Type); } - private IEnumerable InferTypeInCatchDeclaration(CatchDeclarationSyntax catchDeclaration, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInCatchDeclaration(CatchDeclarationSyntax catchDeclaration, SyntaxToken? previousToken = null) { // If we have a position, it has to be after "catch(" if (previousToken.HasValue && previousToken.Value != catchDeclaration.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.ExceptionType()); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.ExceptionType())); } - private IEnumerable InferTypeInCatchFilterClause(CatchFilterClauseSyntax catchFilterClause, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInCatchFilterClause(CatchFilterClauseSyntax catchFilterClause, SyntaxToken? previousToken = null) { // If we have a position, it has to be after "if (" if (previousToken.HasValue && previousToken.Value != catchFilterClause.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - private IEnumerable InferTypeInCoalesceExpression( + private IEnumerable InferTypeInCoalesceExpression( BinaryExpressionSyntax coalesceExpression, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) @@ -1005,34 +1007,34 @@ private IEnumerable InferTypeInCatchFilterClause(CatchFilterClauseS { var leftTypes = GetTypes(coalesceExpression.Left); return leftTypes - .Select(x => x.IsNullable() - ? ((INamedTypeSymbol)x).TypeArguments[0] // nullableExpr ?? Foo() + .Select(x => x.InferredType.IsNullable() + ? new TypeInferenceInfo(((INamedTypeSymbol)x.InferredType).TypeArguments[0]) // nullableExpr ?? Foo() : x); // normalExpr ?? Foo() } var rightTypes = GetTypes(coalesceExpression.Right); if (!rightTypes.Any()) { - return SpecializedCollections.SingletonEnumerable(Compilation.GetSpecialType(SpecialType.System_Object)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(Compilation.GetSpecialType(SpecialType.System_Object))); } return rightTypes - .Select(x => x.IsValueType - ? this.Compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(x) // Foo() ?? 0 + .Select(x => x.InferredType.IsValueType + ? new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(x.InferredType)) // Foo() ?? 0 : x); // Foo() ?? "" } - private IEnumerable InferTypeInConditionalAccessExpression(ConditionalAccessExpressionSyntax expression) + private IEnumerable InferTypeInConditionalAccessExpression(ConditionalAccessExpressionSyntax expression) { return InferTypes(expression); } - private IEnumerable InferTypeInConditionalExpression(ConditionalExpressionSyntax conditional, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInConditionalExpression(ConditionalExpressionSyntax conditional, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) { if (expressionOpt != null && conditional.Condition == expressionOpt) { // Foo() ? a : b - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } // a ? Foo() : b @@ -1050,35 +1052,35 @@ private IEnumerable InferTypeInConditionalExpression(ConditionalExp ? GetTypes(conditional.WhenFalse) : inFalseClause ? GetTypes(conditional.WhenTrue) - : SpecializedCollections.EmptyEnumerable(); + : SpecializedCollections.EmptyEnumerable(); return otherTypes.IsEmpty() ? InferTypes(conditional) : otherTypes; } - private IEnumerable InferTypeInDefaultExpression(DefaultExpressionSyntax defaultExpression) + private IEnumerable InferTypeInDefaultExpression(DefaultExpressionSyntax defaultExpression) { return InferTypes(defaultExpression); } - private IEnumerable InferTypeInDoStatement(DoStatementSyntax doStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInDoStatement(DoStatementSyntax doStatement, SyntaxToken? previousToken = null) { // If we have a position, we need to be after "do { } while(" if (previousToken.HasValue && previousToken.Value != doStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - private IEnumerable InferTypeInEqualsValueClause(EqualsValueClauseSyntax equalsValue, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInEqualsValueClause(EqualsValueClauseSyntax equalsValue, SyntaxToken? previousToken = null) { // If we have a position, it has to be after the = if (previousToken.HasValue && previousToken.Value != equalsValue.EqualsToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (equalsValue.IsParentKind(SyntaxKind.VariableDeclarator)) @@ -1096,97 +1098,97 @@ private IEnumerable InferTypeInEqualsValueClause(EqualsValueClauseS var parameter = SemanticModel.GetDeclaredSymbol(equalsValue.Parent, CancellationToken) as IParameterSymbol; if (parameter != null) { - return SpecializedCollections.SingletonEnumerable(parameter.Type); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(parameter.Type)); } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInPropertyDeclaration(PropertyDeclarationSyntax propertyDeclaration) + private IEnumerable InferTypeInPropertyDeclaration(PropertyDeclarationSyntax propertyDeclaration) { Contract.Assert(propertyDeclaration?.Type != null, "Property type should never be null"); var typeInfo = SemanticModel.GetTypeInfo(propertyDeclaration.Type); return typeInfo.Type != null - ? SpecializedCollections.SingletonEnumerable(typeInfo.Type) - : SpecializedCollections.EmptyEnumerable(); + ? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(typeInfo.Type)) + : SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInBaseMethodDeclaration(BaseMethodDeclarationSyntax declaration) + private IEnumerable InferTypeInBaseMethodDeclaration(BaseMethodDeclarationSyntax declaration) { var methodSymbol = SemanticModel.GetDeclaredSymbol(declaration); return methodSymbol?.ReturnType != null - ? SpecializedCollections.SingletonEnumerable(methodSymbol.ReturnType) - : SpecializedCollections.EmptyEnumerable(); + ? SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(methodSymbol.ReturnType)) + : SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInExpressionStatement(ExpressionStatementSyntax expressionStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInExpressionStatement(ExpressionStatementSyntax expressionStatement, SyntaxToken? previousToken = null) { // If we're position based, then that means we're after the semicolon. In this case // we don't have any sort of type to infer. if (previousToken.HasValue) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Void)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Void))); } - private IEnumerable InferTypeInForEachStatement(ForEachStatementSyntax forEachStatementSyntax, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInForEachStatement(ForEachStatementSyntax forEachStatementSyntax, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) { // If we have a position, then we have to be after "foreach(... in" if (previousToken.HasValue && previousToken.Value != forEachStatementSyntax.InKeyword) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (expressionOpt != null && expressionOpt != forEachStatementSyntax.Expression) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } // foreach (int v = Foo()) var variableTypes = GetTypes(forEachStatementSyntax.Type); if (!variableTypes.Any()) { - return SpecializedCollections.SingletonEnumerable( + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo( this.Compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T) - .Construct(Compilation.GetSpecialType(SpecialType.System_Object))); + .Construct(Compilation.GetSpecialType(SpecialType.System_Object)))); } var type = this.Compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T); - return variableTypes.Select(v => type.Construct(v)); + return variableTypes.Select(v => new TypeInferenceInfo(type.Construct(v.InferredType))); } - private IEnumerable InferTypeInForStatement(ForStatementSyntax forStatement, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInForStatement(ForStatementSyntax forStatement, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) { // If we have a position, it has to be after "for(...;" if (previousToken.HasValue && previousToken.Value != forStatement.FirstSemicolonToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (expressionOpt != null && forStatement.Condition != expressionOpt) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStatement, SyntaxToken? previousToken = null) { // If we have a position, we have to be after the "if(" if (previousToken.HasValue && previousToken.Value != ifStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - private IEnumerable InferTypeInInitializerExpression( + private IEnumerable InferTypeInInitializerExpression( InitializerExpressionSyntax initializerExpression, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) @@ -1203,8 +1205,7 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat var addMethodParameterTypes = addMethodSymbols .Cast() .Where(a => a.Parameters.Length == initializerExpression.Expressions.Count) - .Select(a => a.Parameters.ElementAtOrDefault(parameterIndex)?.Type) - .WhereNotNull(); + .Select(a => new TypeInferenceInfo(a.Parameters.ElementAtOrDefault(parameterIndex)?.Type)); if (addMethodParameterTypes.Any()) { @@ -1221,7 +1222,8 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat var addMethodParameterTypes = addMethodSymbols .Cast() .Where(a => a.Parameters.Length == 1) - .Select(a => a.Parameters[0].Type).WhereNotNull(); + .Select(a => new TypeInferenceInfo(a.Parameters[0].Type)); + if (addMethodParameterTypes.Any()) { return addMethodParameterTypes; @@ -1252,7 +1254,7 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat // look at the siblings of this expression and use their type instead. var arrayTypes = this.InferTypes((ExpressionSyntax)initializerExpression.Parent); - var elementTypes = arrayTypes.OfType().Select(a => a.ElementType).Where(IsUsableTypeFunc); + var elementTypes = arrayTypes.OfType().Select(a => new TypeInferenceInfo(a.ElementType)).Where(IsUsableTypeFunc); if (elementTypes.Any()) { @@ -1275,22 +1277,22 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat { // = { Foo() } var equalsValueClause = (EqualsValueClauseSyntax)initializerExpression.Parent; - IEnumerable types = InferTypeInEqualsValueClause(equalsValueClause); + IEnumerable types = InferTypeInEqualsValueClause(equalsValueClause); - if (types.Any(t => t is IArrayTypeSymbol)) + if (types.Any(t => t.InferredType is IArrayTypeSymbol)) { - return types.OfType().Select(t => t.ElementType); + return types.Select(t => t.InferredType).OfType().Select(t => new TypeInferenceInfo(t.ElementType)); } } else if (initializerExpression.IsParentKind(SyntaxKind.ArrayCreationExpression)) { // new int[] { Foo() } var arrayCreation = (ArrayCreationExpressionSyntax)initializerExpression.Parent; - IEnumerable types = GetTypes(arrayCreation); + IEnumerable types = GetTypes(arrayCreation); - if (types.Any(t => t is IArrayTypeSymbol)) + if (types.Any(t => t.InferredType is IArrayTypeSymbol)) { - return types.OfType().Select(t => t.ElementType); + return types.Select(t => t.InferredType).OfType().Select(t => new TypeInferenceInfo(t.ElementType)); } } else if (initializerExpression.IsParentKind(SyntaxKind.ObjectCreationExpression)) @@ -1299,10 +1301,10 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat var objectCreation = (ObjectCreationExpressionSyntax)initializerExpression.Parent; - IEnumerable types = GetTypes(objectCreation); - if (types.Any(t => t is INamedTypeSymbol)) + IEnumerable types = GetTypes(objectCreation); + if (types.Any(t => t.InferredType is INamedTypeSymbol)) { - return types.OfType().SelectMany(t => + return types.Select(t => t.InferredType).OfType().SelectMany(t => GetCollectionElementType(t, parameterIndex: 0)); } } @@ -1313,7 +1315,7 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat if (expressionOpt != null) { var addMethodSymbols = SemanticModel.GetCollectionInitializerSymbolInfo(expressionOpt).GetAllSymbols(); - var addMethodParameterTypes = addMethodSymbols.Select(a => ((IMethodSymbol)a).Parameters[0].Type).WhereNotNull(); + var addMethodParameterTypes = addMethodSymbols.Select(a => new TypeInferenceInfo(((IMethodSymbol)a).Parameters[0].Type)); if (addMethodParameterTypes.Any()) { return addMethodParameterTypes; @@ -1321,24 +1323,24 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat } var assignExpression = (AssignmentExpressionSyntax)initializerExpression.Parent; - IEnumerable types = GetTypes(assignExpression.Left); + IEnumerable types = GetTypes(assignExpression.Left); - if (types.Any(t => t is INamedTypeSymbol)) + if (types.Any(t => t.InferredType is INamedTypeSymbol)) { // new Foo { a = { Foo() } } var parameterIndex = previousToken.HasValue ? initializerExpression.Expressions.GetSeparators().ToList().IndexOf(previousToken.Value) + 1 : initializerExpression.Expressions.IndexOf(expressionOpt); - return types.OfType().SelectMany(t => + return types.Select(t => t.InferredType).OfType().SelectMany(t => GetCollectionElementType(t, 0)); } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInIsPatternExpression( + private IEnumerable InferTypeInIsPatternExpression( IsPatternExpressionSyntax isPatternExpression, ExpressionSyntax expression) { @@ -1350,91 +1352,91 @@ private IEnumerable InferTypeInIfStatement(IfStatementSyntax ifStat return null; } - private IEnumerable GetPatternTypes(PatternSyntax pattern) + private IEnumerable GetPatternTypes(PatternSyntax pattern) { return pattern.TypeSwitch( (DeclarationPatternSyntax declarationPattern) => GetTypes(declarationPattern.Type), (ConstantPatternSyntax constantPattern) => GetTypes(constantPattern.Expression)); } - private IEnumerable InferTypeInLockStatement(LockStatementSyntax lockStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInLockStatement(LockStatementSyntax lockStatement, SyntaxToken? previousToken = null) { // If we're position based, then we have to be after the "lock(" if (previousToken.HasValue && previousToken.Value != lockStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Object)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Object))); } - private IEnumerable InferTypeInParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax lambdaExpression, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax lambdaExpression, SyntaxToken? previousToken = null) { // If we have a position, it has to be after the lambda arrow. if (previousToken.HasValue && previousToken.Value != lambdaExpression.ArrowToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } return InferTypeInLambdaExpression(lambdaExpression); } - private IEnumerable InferTypeInSimpleLambdaExpression(SimpleLambdaExpressionSyntax lambdaExpression, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInSimpleLambdaExpression(SimpleLambdaExpressionSyntax lambdaExpression, SyntaxToken? previousToken = null) { // If we have a position, it has to be after the lambda arrow. if (previousToken.HasValue && previousToken.Value != lambdaExpression.ArrowToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } return InferTypeInLambdaExpression(lambdaExpression); } - private IEnumerable InferTypeInLambdaExpression(ExpressionSyntax lambdaExpression) + private IEnumerable InferTypeInLambdaExpression(ExpressionSyntax lambdaExpression) { // Func = i => Foo(); var types = InferTypes(lambdaExpression); - var type = types.FirstOrDefault().GetDelegateType(this.Compilation); + var type = types.FirstOrDefault().InferredType.GetDelegateType(this.Compilation); if (type != null) { var invoke = type.DelegateInvokeMethod; if (invoke != null) { - return SpecializedCollections.SingletonEnumerable(invoke.ReturnType); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(invoke.ReturnType)); } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax memberDeclarator, SyntaxToken? previousTokenOpt = null) + private IEnumerable InferTypeInMemberDeclarator(AnonymousObjectMemberDeclaratorSyntax memberDeclarator, SyntaxToken? previousTokenOpt = null) { if (memberDeclarator.NameEquals != null && memberDeclarator.Parent is AnonymousObjectCreationExpressionSyntax) { // If we're position based, then we have to be after the = if (previousTokenOpt.HasValue && previousTokenOpt.Value != memberDeclarator.NameEquals.EqualsToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var types = InferTypes((AnonymousObjectCreationExpressionSyntax)memberDeclarator.Parent); - return types.Where(t => t.IsAnonymousType()) - .SelectMany(t => t.GetValidAnonymousTypeProperties() + return types.Where(t => t.InferredType.IsAnonymousType()) + .SelectMany(t => t.InferredType.GetValidAnonymousTypeProperties() .Where(p => p.Name == memberDeclarator.NameEquals.Name.Identifier.ValueText) - .Select(p => p.Type)); + .Select(p => new TypeInferenceInfo(p.Type))); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, SyntaxToken previousToken) + private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, SyntaxToken previousToken) { if (previousToken != nameColon.ColonToken) { // Must follow the colon token. - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var argumentSyntax = nameColon.Parent as ArgumentSyntax; @@ -1443,10 +1445,10 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, return InferTypeInArgument(argumentSyntax); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInMemberAccessExpression( + private IEnumerable InferTypeInMemberAccessExpression( MemberAccessExpressionSyntax memberAccessExpression, ExpressionSyntax expressionOpt = null, SyntaxToken? previousToken = null) @@ -1460,7 +1462,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, { if (previousToken.Value != memberAccessExpression.OperatorToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } // We're right after the dot in "Foo.Bar". The type for "Bar" should be @@ -1481,7 +1483,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, } } - private IEnumerable InferTypeForExpressionOfMemberAccessExpression( + private IEnumerable InferTypeForExpressionOfMemberAccessExpression( MemberAccessExpressionSyntax memberAccessExpression) { // If we're on the left side of a dot, it's possible in a few cases @@ -1508,7 +1510,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, if (taskOfT != null) { return SpecializedCollections.SingletonEnumerable( - taskOfT.Construct(this.Compilation.ObjectType)); + new TypeInferenceInfo(taskOfT.Construct(this.Compilation.ObjectType))); } } else if (name.Equals(nameof(Enumerable.Select)) || @@ -1529,7 +1531,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, if (argumentExpression != null) { var argumentTypes = GetTypes(argumentExpression); - var delegateType = argumentTypes.FirstOrDefault().GetDelegateType(this.Compilation); + var delegateType = argumentTypes.FirstOrDefault().InferredType.GetDelegateType(this.Compilation); var typeArg = delegateType?.TypeArguments.Length > 0 ? delegateType.TypeArguments[0] : this.Compilation.ObjectType; @@ -1541,13 +1543,13 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, } return SpecializedCollections.SingletonEnumerable( - ienumerableType.Construct(typeArg)); + new TypeInferenceInfo(ienumerableType.Construct(typeArg))); } } } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } private ITypeSymbol InferTypeForFirstParameterOfLambda( @@ -1600,7 +1602,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, if (identifierName.Identifier.ValueText.Equals(parameterName) && SemanticModel.GetSymbolInfo(identifierName.Identifier).Symbol?.Kind == SymbolKind.Parameter) { - return InferTypes(identifierName).FirstOrDefault(); + return InferTypes(identifierName).FirstOrDefault().InferredType; } } else @@ -1621,7 +1623,7 @@ private IEnumerable InferTypeInNameColon(NameColonSyntax nameColon, return null; } - private IEnumerable InferTypeInNameEquals(NameEqualsSyntax nameEquals, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInNameEquals(NameEqualsSyntax nameEquals, SyntaxToken? previousToken = null) { if (previousToken == nameEquals.EqualsToken) { @@ -1637,28 +1639,28 @@ private IEnumerable InferTypeInNameEquals(NameEqualsSyntax nameEqua return this.GetTypes(argumentExpression); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInPostfixUnaryExpression(PostfixUnaryExpressionSyntax postfixUnaryExpressionSyntax, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInPostfixUnaryExpression(PostfixUnaryExpressionSyntax postfixUnaryExpressionSyntax, SyntaxToken? previousToken = null) { // If we're after a postfix ++ or -- then we can't infer anything. if (previousToken.HasValue) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } switch (postfixUnaryExpressionSyntax.Kind()) { case SyntaxKind.PostDecrementExpression: case SyntaxKind.PostIncrementExpression: - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInPrefixUnaryExpression(PrefixUnaryExpressionSyntax prefixUnaryExpression, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInPrefixUnaryExpression(PrefixUnaryExpressionSyntax prefixUnaryExpression, SyntaxToken? previousToken = null) { // If we have a position, then we must be after the prefix token. Contract.ThrowIfTrue(previousToken.HasValue && previousToken.Value != prefixUnaryExpression.OperatorToken); @@ -1670,14 +1672,14 @@ private IEnumerable InferTypeInPrefixUnaryExpression(PrefixUnaryExp case SyntaxKind.UnaryPlusExpression: case SyntaxKind.UnaryMinusExpression: // ++, --, +Foo(), -Foo(); - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); case SyntaxKind.BitwiseNotExpression: // ~Foo() - var types = InferTypes(prefixUnaryExpression).WhereNotNull(); + var types = InferTypes(prefixUnaryExpression); if (!types.Any()) { - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } else { @@ -1686,13 +1688,13 @@ private IEnumerable InferTypeInPrefixUnaryExpression(PrefixUnaryExp case SyntaxKind.LogicalNotExpression: // !Foo() - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeInAwaitExpression(AwaitExpressionSyntax awaitExpression, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInAwaitExpression(AwaitExpressionSyntax awaitExpression, SyntaxToken? previousToken = null) { // If we have a position, then we must be after the prefix token. Contract.ThrowIfTrue(previousToken.HasValue && previousToken.Value != awaitExpression.AwaitKeyword); @@ -1705,23 +1707,23 @@ private IEnumerable InferTypeInAwaitExpression(AwaitExpressionSynta if (task == null || taskOfT == null) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } if (!types.Any()) { - return SpecializedCollections.SingletonEnumerable(task); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(task)); } - return types.Select(t => t.SpecialType == SpecialType.System_Void ? task : taskOfT.Construct(t)); + return types.Select(t => t.InferredType.SpecialType == SpecialType.System_Void ? new TypeInferenceInfo(task) : new TypeInferenceInfo(taskOfT.Construct(t.InferredType))); } - private IEnumerable InferTypeInYieldStatement(YieldStatementSyntax yieldStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInYieldStatement(YieldStatementSyntax yieldStatement, SyntaxToken? previousToken = null) { // If we are position based, then we have to be after the return keyword if (previousToken.HasValue && (previousToken.Value != yieldStatement.ReturnOrBreakKeyword || yieldStatement.ReturnOrBreakKeyword.IsKind(SyntaxKind.BreakKeyword))) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel, yieldStatement.GetAncestorOrThis()); @@ -1735,17 +1737,17 @@ private IEnumerable InferTypeInYieldStatement(YieldStatementSyntax if (memberType.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T || memberType.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerator_T) { - return SpecializedCollections.SingletonEnumerable(((INamedTypeSymbol)memberType).TypeArguments[0]); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(((INamedTypeSymbol)memberType).TypeArguments[0])); } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable InferTypeForReturnStatement(ReturnStatementSyntax returnStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeForReturnStatement(ReturnStatementSyntax returnStatement, SyntaxToken? previousToken = null) { bool isAsync; - IEnumerable types; + IEnumerable types; InferTypeForReturnStatement(returnStatement, previousToken, out isAsync, out types); @@ -1757,21 +1759,21 @@ private IEnumerable InferTypeForReturnStatement(ReturnStatementSynt var taskOfT = this.Compilation.TaskOfTType(); if (taskOfT == null || types == null) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } return from t in types - where t != null && t.OriginalDefinition.Equals(taskOfT) - let nt = (INamedTypeSymbol)t + where t.InferredType != null && t.InferredType.OriginalDefinition.Equals(taskOfT) + let nt = (INamedTypeSymbol)t.InferredType where nt.TypeArguments.Length == 1 - select nt.TypeArguments[0]; + select new TypeInferenceInfo(nt.TypeArguments[0]); } private void InferTypeForReturnStatement( - ReturnStatementSyntax returnStatement, SyntaxToken? previousToken, out bool isAsync, out IEnumerable types) + ReturnStatementSyntax returnStatement, SyntaxToken? previousToken, out bool isAsync, out IEnumerable types) { isAsync = false; - types = SpecializedCollections.EmptyEnumerable(); + types = SpecializedCollections.EmptyEnumerable(); // If we are position based, then we have to be after the return statement. if (previousToken.HasValue && previousToken.Value != returnStatement.ReturnKeyword) @@ -1795,13 +1797,13 @@ private IEnumerable InferTypeForReturnStatement(ReturnStatementSynt var delegateExpression = (AnonymousMethodExpressionSyntax)ancestorExpressions.FirstOrDefault(e => e.IsKind(SyntaxKind.AnonymousMethodExpression)); if (delegateExpression != null) { - var delegateType = InferTypes(delegateExpression).FirstOrDefault(); + var delegateType = InferTypes(delegateExpression).FirstOrDefault().InferredType; if (delegateType != null && delegateType.IsDelegateType()) { var delegateInvokeMethod = delegateType.GetDelegateType(this.Compilation).DelegateInvokeMethod; if (delegateInvokeMethod != null) { - types = SpecializedCollections.SingletonEnumerable(delegateInvokeMethod.ReturnType); + types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(delegateInvokeMethod.ReturnType)); isAsync = delegateExpression.AsyncKeyword.Kind() != SyntaxKind.None; return; } @@ -1815,17 +1817,17 @@ private IEnumerable InferTypeForReturnStatement(ReturnStatementSynt var method = memberSymbol as IMethodSymbol; isAsync = method.IsAsync; - types = SpecializedCollections.SingletonEnumerable(method.ReturnType); + types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(method.ReturnType)); return; } else if (memberSymbol.IsKind(SymbolKind.Property)) { - types = SpecializedCollections.SingletonEnumerable((memberSymbol as IPropertySymbol).Type); + types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo((memberSymbol as IPropertySymbol).Type)); return; } else if (memberSymbol.IsKind(SymbolKind.Field)) { - types = SpecializedCollections.SingletonEnumerable((memberSymbol as IFieldSymbol).Type); + types = SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo((memberSymbol as IFieldSymbol).Type)); return; } } @@ -1848,7 +1850,7 @@ private ISymbol GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel c return originalSemanticModel.GetDeclaredSymbol(declaration, CancellationToken); } - private IEnumerable InferTypeInSwitchLabel( + private IEnumerable InferTypeInSwitchLabel( SwitchLabelSyntax switchLabel, SyntaxToken? previousToken = null) { if (previousToken.HasValue) @@ -1856,7 +1858,7 @@ private ISymbol GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel c if (previousToken.Value != switchLabel.Keyword || switchLabel.Kind() != SyntaxKind.CaseSwitchLabel) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } } @@ -1864,13 +1866,13 @@ private ISymbol GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel c return GetTypes(switchStatement.Expression); } - private IEnumerable InferTypeInSwitchStatement( + private IEnumerable InferTypeInSwitchStatement( SwitchStatementSyntax switchStatement, SyntaxToken? previousToken = null) { // If we have a position, then it has to be after "switch(" if (previousToken.HasValue && previousToken.Value != switchStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } // Use the first case label to determine the return type. @@ -1887,37 +1889,37 @@ private ISymbol GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel c } } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } - private IEnumerable InferTypeInThrowStatement(ThrowStatementSyntax throwStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInThrowStatement(ThrowStatementSyntax throwStatement, SyntaxToken? previousToken = null) { // If we have a position, it has to be after the 'throw' keyword. if (previousToken.HasValue && previousToken.Value != throwStatement.ThrowKeyword) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.ExceptionType()); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.ExceptionType())); } - private IEnumerable InferTypeInUsingStatement(UsingStatementSyntax usingStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInUsingStatement(UsingStatementSyntax usingStatement, SyntaxToken? previousToken = null) { // If we have a position, it has to be after "using(" if (previousToken.HasValue && previousToken.Value != usingStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_IDisposable)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_IDisposable))); } - private IEnumerable InferTypeInVariableDeclarator(VariableDeclaratorSyntax variableDeclarator) + private IEnumerable InferTypeInVariableDeclarator(VariableDeclaratorSyntax variableDeclarator) { var variableType = variableDeclarator.GetVariableType(); if (variableType == null) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } var types = GetTypes(variableType).Where(IsUsableTypeFunc); @@ -1930,35 +1932,35 @@ private IEnumerable InferTypeInVariableDeclarator(VariableDeclarato if (variableDeclaration.IsParentKind(SyntaxKind.UsingStatement)) { // using (var v = Foo()) - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_IDisposable)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_IDisposable))); } if (variableDeclaration.IsParentKind(SyntaxKind.ForStatement)) { // for (var v = Foo(); .. - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Int32)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Int32))); } // Return the types here if they actually bound to a type called 'var'. - return types.Where(t => t.Name == "var"); + return types.Where(t => t.InferredType.Name == "var"); } } return types; } - private IEnumerable InferTypeInWhileStatement(WhileStatementSyntax whileStatement, SyntaxToken? previousToken = null) + private IEnumerable InferTypeInWhileStatement(WhileStatementSyntax whileStatement, SyntaxToken? previousToken = null) { // If we're position based, then we have to be after the "while(" if (previousToken.HasValue && previousToken.Value != whileStatement.OpenParenToken) { - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - return SpecializedCollections.SingletonEnumerable(this.Compilation.GetSpecialType(SpecialType.System_Boolean)); + return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo(this.Compilation.GetSpecialType(SpecialType.System_Boolean))); } - private IEnumerable GetCollectionElementType(INamedTypeSymbol type, int parameterIndex) + private IEnumerable GetCollectionElementType(INamedTypeSymbol type, int parameterIndex) { if (type != null) { @@ -1967,11 +1969,11 @@ private IEnumerable GetCollectionElementType(INamedTypeSymbol type, var elementType = parameters.ElementAtOrDefault(parameterIndex); if (elementType != null) { - return SpecializedCollections.SingletonCollection(elementType); + return SpecializedCollections.SingletonCollection(new TypeInferenceInfo(elementType)); } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } } } diff --git a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs index 0d07b2f32e1..7e84cdb5030 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs @@ -13,36 +13,37 @@ internal abstract class AbstractTypeInferenceService : ITypeI { protected abstract class AbstractTypeInferrer { + protected readonly CancellationToken CancellationToken; protected readonly SemanticModel SemanticModel; - protected readonly Func IsUsableTypeFunc; + protected readonly Func IsUsableTypeFunc; private readonly HashSet _seenExpressionInferType = new HashSet(); private readonly HashSet _seenExpressionGetType = new HashSet(); - private static readonly Func s_isNotNull = t => t != null; + private static readonly Func 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 InferTypesWorker_DoNotCallDirectly(int position); - protected abstract IEnumerable InferTypesWorker_DoNotCallDirectly(TExpressionSyntax expression); - protected abstract IEnumerable GetTypes_DoNotCallDirectly(TExpressionSyntax expression, bool objectAsDefault); + protected abstract IEnumerable InferTypesWorker_DoNotCallDirectly(int position); + protected abstract IEnumerable InferTypesWorker_DoNotCallDirectly(TExpressionSyntax expression); + protected abstract IEnumerable GetTypes_DoNotCallDirectly(TExpressionSyntax expression, bool objectAsDefault); protected abstract bool IsUnusableType(ITypeSymbol arg); protected Compilation Compilation => SemanticModel.Compilation; - public IEnumerable InferTypes(int position) + public IEnumerable InferTypes(int position) { var types = InferTypesWorker_DoNotCallDirectly(position); return Filter(types); } - public IEnumerable InferTypes(TExpressionSyntax expression, bool filterUnusable = true) + public IEnumerable InferTypes(TExpressionSyntax expression, bool filterUnusable = true) { if (expression != null) { @@ -53,20 +54,20 @@ public IEnumerable InferTypes(TExpressionSyntax expression, bool fi } } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - protected IEnumerable GetTypes(TExpressionSyntax expression, bool objectAsDefault = false) + protected IEnumerable GetTypes(TExpressionSyntax expression, bool objectAsDefault = false) { if (_seenExpressionGetType.Add(expression)) { return GetTypes_DoNotCallDirectly(expression, objectAsDefault); } - return SpecializedCollections.EmptyEnumerable(); + return SpecializedCollections.EmptyEnumerable(); } - private IEnumerable Filter(IEnumerable types, bool filterUnusable = true) + private IEnumerable Filter(IEnumerable types, bool filterUnusable = true) { return types.Where(filterUnusable ? IsUsableTypeFunc : s_isNotNull) .Distinct() @@ -95,10 +96,20 @@ protected IEnumerable ExpandParamsParameter(IParameterSymbol parame public IEnumerable 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 InferTypes(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken) + { + return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(expression as TExpressionSyntax).Select(t => t.InferredType); + } + + public IEnumerable GetTypeInferenceInfo(SemanticModel semanticModel, int position, CancellationToken cancellationToken) + { + return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(position); + } + + public IEnumerable GetTypeInferenceInfo(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken) { return CreateTypeInferrer(semanticModel, cancellationToken).InferTypes(expression as TExpressionSyntax); } diff --git a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/ITypeInferenceService.cs b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/ITypeInferenceService.cs index cad2684d8e2..1b4a8dacc24 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/ITypeInferenceService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/ITypeInferenceService.cs @@ -24,5 +24,28 @@ internal interface ITypeInferenceService : ILanguageService { IEnumerable InferTypes(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken); IEnumerable InferTypes(SemanticModel semanticModel, int position, CancellationToken cancellationToken); + + IEnumerable GetTypeInferenceInfo(SemanticModel semanticModel, int position, CancellationToken cancellationToken); + + IEnumerable 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; } } } diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb index afd74097e21..10e98e3da4a 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb @@ -1,9 +1,10 @@ -' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +'Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Collections.Immutable Imports System.Threading Imports System.Threading.Tasks Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -22,15 +23,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic otherSideType.Name = String.Empty End Function - Protected Overrides Function GetTypes_DoNotCallDirectly(expression As ExpressionSyntax, objectAsDefault As Boolean) As IEnumerable(Of ITypeSymbol) + Protected Overrides Function GetTypes_DoNotCallDirectly(expression As ExpressionSyntax, objectAsDefault As Boolean) As IEnumerable(Of TypeInferenceInfo) If expression IsNot Nothing Then Dim info = SemanticModel.GetTypeInfo(expression) If info.Type IsNot Nothing AndAlso info.Type.TypeKind <> TypeKind.Error Then - Return SpecializedCollections.SingletonEnumerable(info.Type) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(info.Type)) End If If info.ConvertedType IsNot Nothing AndAlso info.ConvertedType.TypeKind <> TypeKind.Error Then - Return SpecializedCollections.SingletonEnumerable(info.ConvertedType) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(info.ConvertedType)) End If If expression.Kind = SyntaxKind.AddressOfExpression Then @@ -38,15 +39,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim symbol = SemanticModel.GetSymbolInfo(unaryExpression.Operand, CancellationToken).GetAnySymbol() Dim type = symbol.ConvertToType(Me.Compilation) If type IsNot Nothing Then - Return SpecializedCollections.SingletonEnumerable(type) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(type)) End If End If End If - Return If(objectAsDefault, SpecializedCollections.SingletonEnumerable(Me.Compilation.ObjectType), SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()) + Return If(objectAsDefault, SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.ObjectType)), SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)()) End Function - Protected Overrides Function InferTypesWorker_DoNotCallDirectly(expression As ExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Protected Overrides Function InferTypesWorker_DoNotCallDirectly(expression As ExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) expression = expression.WalkUpParentheses() Dim parent = expression.Parent @@ -89,33 +90,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Function(whileStatement As WhileOrUntilClauseSyntax) InferTypeInWhileOrUntilClause(), Function(whileStatement As WhileStatementSyntax) InferTypeInWhileStatement(), Function(yieldStatement As YieldStatementSyntax) InferTypeInYieldStatement(yieldStatement), - Function(x) SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()) + Function(x) SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)()) End Function - Private Function InferTypeInTypeOfExpressionSyntax(typeOfExpression As TypeOfExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInTypeOfExpressionSyntax(typeOfExpression As TypeOfExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) Dim expressionType = typeOfExpression.Type If expressionType Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Dim typeSymbol = SemanticModel.GetTypeInfo(expressionType).Type If TypeOf typeSymbol IsNot INamedTypeSymbol Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If - Return SpecializedCollections.SingletonEnumerable(typeSymbol) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(typeSymbol)) End Function Private Function InferTypeInAddRemoveHandlerStatementSyntax(addRemoveHandlerStatement As AddRemoveHandlerStatementSyntax, - expression As ExpressionSyntax) As IEnumerable(Of ITypeSymbol) + expression As ExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) If expression Is addRemoveHandlerStatement.DelegateExpression Then Return GetTypes(addRemoveHandlerStatement.EventExpression) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Protected Overrides Function InferTypesWorker_DoNotCallDirectly(position As Integer) As IEnumerable(Of ITypeSymbol) + Protected Overrides Function InferTypesWorker_DoNotCallDirectly(position As Integer) As IEnumerable(Of TypeInferenceInfo) Dim tree = TryCast(Me.SemanticModel.SyntaxTree, SyntaxTree) Dim token = tree.FindTokenOnLeftOfPosition(position, CancellationToken) token = token.GetPreviousTokenIfTouchingWord(position) @@ -161,24 +162,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Function(whileStatement As WhileOrUntilClauseSyntax) InferTypeInWhileOrUntilClause(), Function(whileStatement As WhileStatementSyntax) InferTypeInWhileStatement(), Function(yieldStatement As YieldStatementSyntax) InferTypeInYieldStatement(yieldStatement, token), - Function(x) SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()) + Function(x) SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)()) End Function - Private Function InferTypeInParameterList(parameterList As ParameterListSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInParameterList(parameterList As ParameterListSyntax) As IEnumerable(Of TypeInferenceInfo) Return If(parameterList.Parent IsNot Nothing, InferTypeInLambda(TryCast(parameterList.Parent.Parent, LambdaExpressionSyntax)), - SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()) + SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)()) End Function Private Function InferTypeInArgumentList(argumentList As ArgumentListSyntax, - Optional argumentOpt As ArgumentSyntax = Nothing, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional argumentOpt As ArgumentSyntax = Nothing, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If argumentList Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If If argumentList.Parent IsNot Nothing Then If argumentList.IsParentKind(SyntaxKind.ArrayCreationExpression) Then - Return SpecializedCollections.SingletonEnumerable(Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Compilation.GetSpecialType(SpecialType.System_Int32))) ElseIf argumentList.IsParentKind(SyntaxKind.InvocationExpression) Then Dim invocation = TryCast(argumentList.Parent, InvocationExpressionSyntax) @@ -190,7 +191,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If If index < 0 Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Dim info = SemanticModel.GetSymbolInfo(invocation) @@ -212,7 +213,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If targetExpression IsNot Nothing Then Dim expressionType = SemanticModel.GetTypeInfo(targetExpression) If TypeOf expressionType.Type Is IArrayTypeSymbol Then - Return SpecializedCollections.SingletonEnumerable(Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Compilation.GetSpecialType(SpecialType.System_Int32))) End If End If End If @@ -227,7 +228,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim namedType = TryCast(info.Symbol, INamedTypeSymbol) If namedType IsNot Nothing Then If namedType.TypeKind = TypeKind.Delegate Then - Return SpecializedCollections.SingletonEnumerable(namedType) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(namedType)) Else Dim index As Integer = 0 If argumentOpt IsNot Nothing Then @@ -237,7 +238,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If If index < 0 Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Dim constructors = namedType.InstanceConstructors.Where(Function(m) m.Parameters.Length > index) @@ -261,7 +262,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If If index < 0 Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Dim info = SemanticModel.GetSymbolInfo(attribute) @@ -294,10 +295,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInArgument(argument As ArgumentSyntax, index As Integer, symbols As IEnumerable(Of ISymbol)) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInArgument(argument As ArgumentSyntax, index As Integer, symbols As IEnumerable(Of ISymbol)) As IEnumerable(Of TypeInferenceInfo) Dim methods = symbols.OfType(Of IMethodSymbol)() If methods.Any() Then Dim parameters = methods.Select(Function(m) m.Parameters) @@ -310,13 +311,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return InferTypeInArgument(argument, index, parameters) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function InferTypeInArgument( argument As ArgumentSyntax, index As Integer, - parameterizedSymbols As IEnumerable(Of ImmutableArray(Of IParameterSymbol))) As IEnumerable(Of ITypeSymbol) + parameterizedSymbols As IEnumerable(Of ImmutableArray(Of IParameterSymbol))) As IEnumerable(Of TypeInferenceInfo) Dim simpleArgument = TryCast(argument, SimpleArgumentSyntax) @@ -325,32 +326,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic .SelectMany(Function(m) m) _ .Where(Function(p) p.Name = simpleArgument.NameColonEquals.Name.Identifier.ValueText) - Return parameters.Select(Function(p) p.Type) + Return parameters.Select(Function(p) New TypeInferenceInfo(p.Type, p.IsParams)) Else ' Otherwise, just take the first overload and pick what type this parameter is ' based on index. - Return parameterizedSymbols.Where(Function(a) index < a.Length).Select(Function(a) a(index).Type) + Return parameterizedSymbols.Where(Function(a) index < a.Length).Select(Function(a) New TypeInferenceInfo(a(index).Type, a(index).IsParams)) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInArrayCreationExpression(arrayCreationExpression As ArrayCreationExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInArrayCreationExpression(arrayCreationExpression As ArrayCreationExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) Dim outerTypes = InferTypes(arrayCreationExpression) - Return outerTypes.OfType(Of IArrayTypeSymbol).Select(Function(a) a.ElementType) + Return outerTypes.OfType(Of IArrayTypeSymbol).Select(Function(a) New TypeInferenceInfo(a.ElementType)) End Function - Private Function InferTypeInArrayRankSpecifier() As IEnumerable(Of INamedTypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Private Function InferTypeInArrayRankSpecifier() As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) End Function - Private Function InferTypeInArrayType(arrayType As ArrayTypeSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInArrayType(arrayType As ArrayTypeSyntax) As IEnumerable(Of TypeInferenceInfo) ' Bind the array type, then unwrap whatever we get back based on the number of rank ' specifiers we see. Dim currentTypes = InferTypes(arrayType) Dim i = 0 While i < arrayType.RankSpecifiers.Count - currentTypes = currentTypes.OfType(Of IArrayTypeSymbol)().Select(Function(c) c.ElementType) + currentTypes = currentTypes.OfType(Of IArrayTypeSymbol)().Select(Function(c) New TypeInferenceInfo(c.ElementType)) i = i + 1 End While @@ -360,27 +361,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Function InferTypeInAsClause(asClause As AsClauseSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If previousToken <> Nothing AndAlso previousToken.Kind <> SyntaxKind.AsKeyword Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If If asClause.IsParentKind(SyntaxKind.CatchStatement) Then If expressionOpt Is asClause.Type OrElse previousToken.Kind = SyntaxKind.AsKeyword Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.ExceptionType) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.ExceptionType)) End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function InferTypeInAssignmentStatement(assignmentStatement As AssignmentStatementSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If assignmentStatement.IsKind(SyntaxKind.LeftShiftAssignmentStatement) OrElse assignmentStatement.IsKind(SyntaxKind.RightShiftAssignmentStatement) Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) End If If expressionOpt Is assignmentStatement.Right OrElse previousToken = assignmentStatement.OperatorToken Then @@ -391,14 +392,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return GetTypes(assignmentStatement.Right) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInAttribute(attribute As AttributeSyntax) As IEnumerable(Of ITypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.AttributeType) + Private Function InferTypeInAttribute(attribute As AttributeSyntax) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.AttributeType)) End Function - Private Function InferTypeInAwaitExpression(awaitExpression As AwaitExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInAwaitExpression(awaitExpression As AwaitExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) ' await Dim types = InferTypes(awaitExpression, filterUnusable:=False) @@ -407,38 +408,40 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim taskOfT = Me.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1") If task Is Nothing OrElse taskOfT Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If If Not types.Any() Then - Return SpecializedCollections.SingletonEnumerable(task) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(task)) End If - Return types.Select(Function(t) If(t.SpecialType = SpecialType.System_Void, task, taskOfT.Construct(t))) + Return types.Select(Function(t) New TypeInferenceInfo(If(t.InferredType.SpecialType = SpecialType.System_Void, task, taskOfT.Construct(t.InferredType)))) End Function - Private Function InferTypeInConditionalAccessExpression(conditional As ConditionalAccessExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInConditionalAccessExpression(conditional As ConditionalAccessExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) Return InferTypes(conditional) End Function Private Function InferTypeInBinaryConditionalExpression(conditional As BinaryConditionalExpressionSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If previousToken <> Nothing AndAlso previousToken <> conditional.OpenParenToken AndAlso previousToken <> conditional.CommaToken Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If If conditional.FirstExpression Is expressionOpt OrElse previousToken = conditional.OpenParenToken Then Dim rightTypes = GetTypes(conditional.SecondExpression, objectAsDefault:=True) ' value type : If (Foo(), 0) ' otherwise : If (Foo(), "") - Return rightTypes.Select(Function(t) If(t.IsValueType, Me.Compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(t), t)) + Return rightTypes.Select(Function(t) If(t.InferredType.IsValueType, + New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(t.InferredType)), + t)) Else Dim leftTypes = GetTypes(conditional.FirstExpression) Return leftTypes.Select(Function(t) - If t.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T Then - Return DirectCast(t, INamedTypeSymbol).TypeArguments(0) + If t.InferredType.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T Then + Return New TypeInferenceInfo(DirectCast(t.InferredType, INamedTypeSymbol).TypeArguments(0)) Else Return t End If @@ -448,7 +451,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Function InferTypeInBinaryExpression(binop As BinaryExpressionSyntax, Optional expression As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' If we got a token, it must be the operator in the binary expression Contract.ThrowIfTrue(previousToken <> Nothing AndAlso binop.OperatorToken <> previousToken) @@ -460,7 +463,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic SyntaxKind.LessThanLessThanEqualsToken, SyntaxKind.GreaterThanGreaterThanEqualsToken If rightSide Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) End If End Select @@ -470,7 +473,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' But the gain is pretty marginal IMO. Dim otherSide = If(rightSide, binop.Left, binop.Right) Dim otherSideTypes = GetTypes(otherSide) - If otherSideTypes.Any(Function(t) t.SpecialType <> SpecialType.System_Object AndAlso Not t.IsErrorType()) Then + If otherSideTypes.Any(Function(t) t.InferredType.SpecialType <> SpecialType.System_Object AndAlso Not t.InferredType.IsErrorType()) Then Return otherSideTypes End If @@ -494,44 +497,44 @@ Namespace Microsoft.CodeAnalysis.VisualBasic SyntaxKind.GreaterThanGreaterThanToken, SyntaxKind.LessThanLessThanEqualsToken, SyntaxKind.GreaterThanGreaterThanEqualsToken - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) Case SyntaxKind.AndKeyword, SyntaxKind.AndAlsoKeyword, SyntaxKind.OrKeyword, SyntaxKind.OrElseKeyword - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Select - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function InferTypeInCastExpression(castExpression As CastExpressionSyntax, - Optional expressionOpt As ExpressionSyntax = Nothing) As IEnumerable(Of ITypeSymbol) + Optional expressionOpt As ExpressionSyntax = Nothing) As IEnumerable(Of TypeInferenceInfo) If castExpression.Expression Is expressionOpt Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Return GetTypes(castExpression.Type) End Function - Private Function InferTypeInCatchFilterClause(catchFilterClause As CatchFilterClauseSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInCatchFilterClause(catchFilterClause As CatchFilterClauseSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If previousToken <> Nothing AndAlso previousToken <> catchFilterClause.WhenKeyword Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Function - Private Function InferTypeInDoStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of INamedTypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Private Function InferTypeInDoStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Function - Private Function InferTypeInEqualsValue(equalsValue As EqualsValueSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInEqualsValue(equalsValue As EqualsValueSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If equalsValue.IsParentKind(SyntaxKind.VariableDeclarator) Then Dim variableDeclarator = DirectCast(equalsValue.Parent, VariableDeclaratorSyntax) If variableDeclarator.AsClause Is Nothing AndAlso variableDeclarator.IsParentKind(SyntaxKind.UsingStatement) Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_IDisposable)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_IDisposable))) End If If variableDeclarator.Names.Count >= 1 Then @@ -541,9 +544,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If symbol IsNot Nothing Then Select Case symbol.Kind Case SymbolKind.Field - Return SpecializedCollections.SingletonEnumerable(DirectCast(symbol, IFieldSymbol).Type) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(DirectCast(symbol, IFieldSymbol).Type)) Case SymbolKind.Local - Return SpecializedCollections.SingletonEnumerable(DirectCast(symbol, ILocalSymbol).Type) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(DirectCast(symbol, ILocalSymbol).Type)) End Select End If End If @@ -556,30 +559,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim propertySyntax = CType(equalsValue.Parent, PropertyStatementSyntax) Dim propertySymbol = SemanticModel.GetDeclaredSymbol(propertySyntax) If propertySymbol Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Return If(propertySymbol.Type IsNot Nothing, - SpecializedCollections.SingletonEnumerable(propertySymbol.Type), - SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()) + SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(propertySymbol.Type)), + SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)()) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInExpressionStatement(expressionStatement As ExpressionStatementSyntax) As IEnumerable(Of INamedTypeSymbol) + Private Function InferTypeInExpressionStatement(expressionStatement As ExpressionStatementSyntax) As IEnumerable(Of TypeInferenceInfo) If expressionStatement.Expression.IsKind(SyntaxKind.InvocationExpression) Then Return InferTypeInCallStatement() End If - Return SpecializedCollections.EmptyEnumerable(Of INamedTypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInCallStatement() As IEnumerable(Of INamedTypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Void)) + Private Function InferTypeInCallStatement() As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Void))) End Function Private Function InferTypeInForEachStatement(forEachStatement As ForEachStatementSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If expressionOpt Is forEachStatement.Expression OrElse previousToken = forEachStatement.InKeyword Then If TypeOf forEachStatement.ControlVariable Is VariableDeclaratorSyntax Then Dim declarator = DirectCast(forEachStatement.ControlVariable, VariableDeclaratorSyntax) @@ -587,20 +590,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim variableTypes = GetTypes(DirectCast(declarator.AsClause, SimpleAsClauseSyntax).Type, objectAsDefault:=True) Dim type = Me.Compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T) - Return variableTypes.Select(Function(t) type.Construct(t)) + Return variableTypes.Select(Function(t) New TypeInferenceInfo(type.Construct(t.InferredType))) End If ElseIf TypeOf forEachStatement.ControlVariable Is SimpleNameSyntax Then Dim type = Me.Compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T) - Return SpecializedCollections.SingletonEnumerable(type.Construct(Compilation.GetSpecialType(SpecialType.System_Object))) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(type.Construct(Compilation.GetSpecialType(SpecialType.System_Object)))) End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function InferTypeInForStatement(forStatement As ForStatementSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If (expressionOpt IsNot Nothing AndAlso expressionOpt IsNot forStatement.ControlVariable) OrElse previousToken = forStatement.ToKeyword OrElse previousToken = forStatement.EqualsToken Then @@ -612,22 +615,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInForStepClause(forStepClause As ForStepClauseSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInForStepClause(forStepClause As ForStepClauseSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' TODO(cyrusn): Potentially infer a different type based on the type of the variable ' being foreach-ed over. - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) End Function - Private Function InferTypeInIfOrElseIfStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of INamedTypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Private Function InferTypeInIfOrElseIfStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Function - Private Function InferTypeInLambda(lambda As ExpressionSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInLambda(lambda As ExpressionSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If lambda Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If ' Func = i => Foo(); @@ -636,15 +639,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic lambdaTypes = InferTypes(lambda) End If - Return lambdaTypes.Where(Function(t) t.TypeKind = TypeKind.Delegate).SelectMany(Function(t) t.GetMembers(WellKnownMemberNames.DelegateInvokeName).OfType(Of IMethodSymbol)().Select(Function(m) m.ReturnType)) + Return lambdaTypes.Where(Function(t) t.InferredType.TypeKind = TypeKind.Delegate).SelectMany(Function(t) t.InferredType.GetMembers(WellKnownMemberNames.DelegateInvokeName).OfType(Of IMethodSymbol)().Select(Function(m) New TypeInferenceInfo(m.ReturnType))) - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeForReturnStatement(returnStatement As ReturnStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeForReturnStatement(returnStatement As ReturnStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' If we're position based, we must have gotten the Return token If previousToken <> Nothing AndAlso previousToken.Kind <> SyntaxKind.ReturnKeyword Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If ' If we're in a lambda, then use the return type of the lambda to figure out what to @@ -657,7 +660,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If If returnStatement.GetAncestorOrThis(Of MethodBlockBaseSyntax) Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End If Dim memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel, returnStatement.GetAncestor(Of MethodBlockBaseSyntax).BlockStatement) @@ -671,24 +674,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return If( taskOfT IsNot Nothing AndAlso memberMethod.ReturnType.OriginalDefinition Is taskOfT AndAlso typeArguments.Any(), - SpecializedCollections.SingletonEnumerable(typeArguments.First()), - SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)) + SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(typeArguments.First())), + SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)) Else - Return SpecializedCollections.SingletonEnumerable(memberMethod.ReturnType) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(memberMethod.ReturnType)) End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInYieldStatement(yieldStatement As YieldStatementSyntax, Optional previoustoken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInYieldStatement(yieldStatement As YieldStatementSyntax, Optional previoustoken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' If we're position based, we must be after the Yield token If previoustoken <> Nothing AndAlso Not previoustoken.IsKind(SyntaxKind.YieldKeyword) Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End If If yieldStatement.GetAncestorOrThis(Of MethodBlockBaseSyntax) Is Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End If Dim memberSymbol = GetDeclaredMemberSymbolFromOriginalSemanticModel(SemanticModel, yieldStatement.GetAncestor(Of MethodBlockBaseSyntax).BlockStatement) @@ -701,11 +704,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If memberType.OriginalDefinition.SpecialType = SpecialType.System_Collections_Generic_IEnumerable_T OrElse memberType.OriginalDefinition.SpecialType = SpecialType.System_Collections_Generic_IEnumerator_T Then - Return SpecializedCollections.SingletonEnumerable(DirectCast(memberType, INamedTypeSymbol).TypeArguments(0)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(DirectCast(memberType, INamedTypeSymbol).TypeArguments(0))) End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End Function Private Function GetDeclaredMemberSymbolFromOriginalSemanticModel(currentSemanticModel As SemanticModel, declarationInCurrentTree As DeclarationStatementSyntax) As ISymbol @@ -722,7 +725,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return originalSemanticModel.GetDeclaredSymbol(declaration, CancellationToken) End Function - Private Function InferTypeInSelectStatement(switchStatementSyntax As SelectStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInSelectStatement(switchStatementSyntax As SelectStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' Use the first case label to determine the return type. If TypeOf switchStatementSyntax.Parent Is SelectBlockSyntax Then Dim firstCase = DirectCast(switchStatementSyntax.Parent, SelectBlockSyntax).CaseBlocks.SelectMany(Function(c) c.CaseStatement.Cases).OfType(Of SimpleCaseClauseSyntax).FirstOrDefault() @@ -731,16 +734,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If End If - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) End Function Private Function InferTypeInTernaryConditionalExpression(conditional As TernaryConditionalExpressionSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If previousToken <> Nothing AndAlso previousToken.Kind <> SyntaxKind.OpenParenToken AndAlso previousToken.Kind <> SyntaxKind.CommaToken Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() ElseIf previousToken = conditional.OpenParenToken Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) ElseIf previousToken = conditional.FirstCommaToken Then Return GetTypes(conditional.WhenTrue) ElseIf previousToken = conditional.SecondCommaToken Then @@ -748,65 +751,65 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If If conditional.Condition Is expressionOpt Then - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) Else Return If(conditional.WhenTrue Is expressionOpt, GetTypes(conditional.WhenFalse), GetTypes(conditional.WhenTrue)) End If End Function - Private Function InferTypeInThrowStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInThrowStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) ' If we're not the Throw token, there's nothing to do If previousToken <> Nothing AndAlso previousToken.Kind <> SyntaxKind.ThrowKeyword Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.ExceptionType) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.ExceptionType)) End Function - Private Function InferTypeInUnaryExpression(unaryExpressionSyntax As UnaryExpressionSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInUnaryExpression(unaryExpressionSyntax As UnaryExpressionSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) Select Case unaryExpressionSyntax.Kind Case SyntaxKind.UnaryPlusExpression, SyntaxKind.UnaryMinusExpression - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Int32)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Int32))) Case SyntaxKind.NotExpression Dim types = InferTypes(unaryExpressionSyntax) - If types.Any(Function(t) t.IsNumericType) Then - Return types.Where(Function(t) t.IsNumericType) + If types.Any(Function(t) t.InferredType.IsNumericType) Then + Return types.Where(Function(t) t.InferredType.IsNumericType) End If - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) Case SyntaxKind.AddressOfExpression Return InferTypes(unaryExpressionSyntax) End Select - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function - Private Function InferTypeInUsingStatement(usingStatement As UsingStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_IDisposable)) + Private Function InferTypeInUsingStatement(usingStatement As UsingStatementSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_IDisposable))) End Function Private Function InferTypeInVariableDeclarator(expression As ExpressionSyntax, variableDeclarator As VariableDeclaratorSyntax, - Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) If variableDeclarator.AsClause IsNot Nothing Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End If Return GetTypes(variableDeclarator.AsClause.Type) End Function - Private Function InferTypeInWhileStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Private Function InferTypeInWhileStatement(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Function - Private Function InferTypeInWhileOrUntilClause(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) - Return SpecializedCollections.SingletonEnumerable(Me.Compilation.GetSpecialType(SpecialType.System_Boolean)) + Private Function InferTypeInWhileOrUntilClause(Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(Me.Compilation.GetSpecialType(SpecialType.System_Boolean))) End Function Private Function InferTypeInMemberAccessExpression( memberAccessExpression As MemberAccessExpressionSyntax, Optional expressionOpt As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken? = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken? = Nothing) As IEnumerable(Of TypeInferenceInfo) ' We need to be on the right of the dot to infer an appropriate type for ' the member access expression. i.e. if we have "Foo.Bar" then we can @@ -815,7 +818,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' out anything about its type. If previousToken <> Nothing Then If previousToken.Value <> memberAccessExpression.OperatorToken Then - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End If Return InferTypes(memberAccessExpression) @@ -835,7 +838,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If End Function - Private Function InferTypeForExpressionOfMemberAccessExpression(memberAccessExpression As MemberAccessExpressionSyntax) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeForExpressionOfMemberAccessExpression(memberAccessExpression As MemberAccessExpressionSyntax) As IEnumerable(Of TypeInferenceInfo) Dim name = memberAccessExpression.Name.Identifier.Value If name.Equals(NameOf(Task(Of Integer).ConfigureAwait)) AndAlso @@ -850,7 +853,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim taskOfT = Me.Compilation.TaskOfTType() If taskOfT IsNot Nothing Then Return SpecializedCollections.SingletonEnumerable( - taskOfT.Construct(Me.Compilation.ObjectType)) + New TypeInferenceInfo(taskOfT.Construct(Me.Compilation.ObjectType))) End If ElseIf name.Equals(NameOf(Enumerable.Select)) OrElse name.Equals(NameOf(Enumerable.Where)) Then @@ -866,7 +869,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic TypeOf invocation.ArgumentList.Arguments(0) Is SimpleArgumentSyntax Then Dim argumentExpression = DirectCast(invocation.ArgumentList.Arguments(0), SimpleArgumentSyntax).Expression Dim argumentTypes = GetTypes(argumentExpression) - Dim delegateType = argumentTypes.FirstOrDefault().GetDelegateType(Me.Compilation) + Dim delegateType = argumentTypes.FirstOrDefault().InferredType.GetDelegateType(Me.Compilation) Dim typeArg = If(delegateType?.TypeArguments.Length > 0, delegateType.TypeArguments(0), Me.Compilation.ObjectType) @@ -879,12 +882,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If Return SpecializedCollections.SingletonEnumerable( - ienumerableType.Construct(typeArg)) + New TypeInferenceInfo(ienumerableType.Construct(typeArg))) End If End If End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function InferTypeForFirstParameterOfLambda( @@ -916,7 +919,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim identifier = DirectCast(node, IdentifierNameSyntax) If CaseInsensitiveComparison.Equals(parameterName, identifier.Identifier.ValueText) AndAlso SemanticModel.GetSymbolInfo(identifier.Identifier).Symbol?.Kind = SymbolKind.Parameter Then - Return InferTypes(identifier).FirstOrDefault() + Return InferTypes(identifier).FirstOrDefault().InferredType End If Else For Each child In node.ChildNodesAndTokens() @@ -932,22 +935,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return Nothing End Function - Private Function InferTypeInNamedFieldInitializer(initializer As NamedFieldInitializerSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of ITypeSymbol) + Private Function InferTypeInNamedFieldInitializer(initializer As NamedFieldInitializerSyntax, Optional previousToken As SyntaxToken = Nothing) As IEnumerable(Of TypeInferenceInfo) Dim right = SemanticModel.GetTypeInfo(initializer.Name).Type If right IsNot Nothing AndAlso TypeOf right IsNot IErrorTypeSymbol Then - Return SpecializedCollections.SingletonEnumerable(right) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(right)) End If - Return SpecializedCollections.SingletonEnumerable(SemanticModel.GetTypeInfo(initializer.Expression).Type) + Return SpecializedCollections.SingletonEnumerable(New TypeInferenceInfo(SemanticModel.GetTypeInfo(initializer.Expression).Type)) End Function - Public Function InferTypeInCaseStatement(caseStatement As CaseStatementSyntax) As IEnumerable(Of ITypeSymbol) + Public Function InferTypeInCaseStatement(caseStatement As CaseStatementSyntax) As IEnumerable(Of TypeInferenceInfo) Dim selectBlock = caseStatement.GetAncestor(Of SelectBlockSyntax)() If selectBlock IsNot Nothing Then Return GetTypes(selectBlock.SelectStatement.Expression) End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)() + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo)() End Function Private Function GetArgumentListIndex(argumentList As ArgumentListSyntax, previousToken As SyntaxToken) As Integer @@ -962,14 +965,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Function InferTypeInCollectionInitializerExpression( collectionInitializer As CollectionInitializerSyntax, Optional expression As ExpressionSyntax = Nothing, - Optional previousToken As SyntaxToken? = Nothing) As IEnumerable(Of ITypeSymbol) + Optional previousToken As SyntaxToken? = Nothing) As IEnumerable(Of TypeInferenceInfo) ' New List(Of T) From { x } If expression IsNot Nothing Then Dim expressionAddMethodSymbols = SemanticModel.GetCollectionInitializerSymbolInfo(expression).GetAllSymbols() Dim expressionAddMethodParameterTypes = expressionAddMethodSymbols _ .Where(Function(a) DirectCast(a, IMethodSymbol).Parameters.Count() = 1) _ - .Select(Function(a) DirectCast(a, IMethodSymbol).Parameters(0).Type).WhereNotNull() + .Select(Function(a) New TypeInferenceInfo(DirectCast(a, IMethodSymbol).Parameters(0).Type)) If expressionAddMethodParameterTypes.Any() Then Return expressionAddMethodParameterTypes @@ -984,13 +987,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim initializerAddMethodSymbols = SemanticModel.GetCollectionInitializerSymbolInfo(collectionInitializer).GetAllSymbols() Dim initializerAddMethodParameterTypes = initializerAddMethodSymbols _ .Where(Function(a) DirectCast(a, IMethodSymbol).Parameters.Count() = collectionInitializer.Initializers.Count) _ - .Select(Function(a) DirectCast(a, IMethodSymbol).Parameters.ElementAtOrDefault(parameterIndex)?.Type).WhereNotNull() + .Select(Function(a) DirectCast(a, IMethodSymbol).Parameters.ElementAtOrDefault(parameterIndex)?.Type) _ + .WhereNotNull() _ + .Select(Function(a) New TypeInferenceInfo(a)) + If initializerAddMethodParameterTypes.Any() Then Return initializerAddMethodParameterTypes End If - Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol) + Return SpecializedCollections.EmptyEnumerable(Of TypeInferenceInfo) End Function End Class End Class -- GitLab