public static BoundCall ErrorCall( CSharpSyntaxNode node, BoundExpression receiverOpt, MethodSymbol method, ImmutableArray <BoundExpression> arguments, ImmutableArray <string> namedArguments, ImmutableArray <RefKind> refKinds, bool isDelegateCall, bool invokedAsExtensionMethod, ImmutableArray <MethodSymbol> originalMethods, LookupResultKind resultKind) { if (!originalMethods.IsEmpty) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } Debug.Assert(arguments.IsDefaultOrEmpty || (object)receiverOpt != (object)arguments[0]); var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments, refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray <int>), resultKind: resultKind, type: method.ReturnType, hasErrors: true); call.OriginalMethodsOpt = originalMethods; return(call); }
public static BoundCall ErrorCall( SyntaxNode node, BoundExpression receiverOpt, MethodSymbol method, ImmutableArray <BoundExpression> arguments, ImmutableArray <string> namedArguments, ImmutableArray <RefKind> refKinds, bool isDelegateCall, bool invokedAsExtensionMethod, ImmutableArray <MethodSymbol> originalMethods, LookupResultKind resultKind, Binder binder ) { if (!originalMethods.IsEmpty) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } Debug.Assert(arguments.IsDefaultOrEmpty || (object)receiverOpt != (object)arguments[0]); return(new BoundCall( syntax: node, receiverOpt: binder.BindToTypeForErrorRecovery(receiverOpt), method: method, arguments: arguments.SelectAsArray( (e, binder) => binder.BindToTypeForErrorRecovery(e), binder ), argumentNamesOpt: namedArguments, argumentRefKindsOpt: refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray <int>), defaultArguments: default(BitVector), resultKind: resultKind, originalMethodsOpt: originalMethods, type: method.ReturnType, hasErrors: true )); }
public static BoundCall ErrorCall( CSharpSyntaxNode node, BoundExpression receiverOpt, MethodSymbol method, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> namedArguments, ImmutableArray<RefKind> refKinds, bool isDelegateCall, bool invokedAsExtensionMethod, ImmutableArray<MethodSymbol> originalMethods, LookupResultKind resultKind) { if (!originalMethods.IsEmpty) resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); var call = new BoundCall(node, receiverOpt, method, arguments, namedArguments, refKinds, isDelegateCall: isDelegateCall, expanded: false, invokedAsExtensionMethod: invokedAsExtensionMethod, argsToParamsOpt: default(ImmutableArray<int>), resultKind: resultKind, type: method.ReturnType, hasErrors: true); call.OriginalMethodsOpt = originalMethods; return call; }
protected virtual MethodSymbol BindAttributeConstructor( AttributeSyntax node, NamedTypeSymbol attributeType, AnalyzedArguments boundConstructorArguments, DiagnosticBag diagnostics, ref LookupResultKind resultKind, bool suppressErrors, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { MemberResolutionResult<MethodSymbol> memberResolutionResult; ImmutableArray<MethodSymbol> candidateConstructors; if (!TryPerformConstructorOverloadResolution( attributeType, boundConstructorArguments, attributeType.Name, node.Location, suppressErrors, //don't cascade in these cases diagnostics, out memberResolutionResult, out candidateConstructors, allowProtectedConstructorsOfBaseType: true)) { resultKind = resultKind.WorseResultKind( memberResolutionResult.IsValid && !IsConstructorAccessible(memberResolutionResult.Member, ref useSiteDiagnostics) ? LookupResultKind.Inaccessible : LookupResultKind.OverloadResolutionFailure); } return memberResolutionResult.Member; }
// Get the symbols and possible method group associated with a method group bound node, as // they should be exposed through GetSemanticInfo. // NB: It is not safe to pass a null binderOpt during speculative binding. // // If the parent node of the method group syntax node provides information (such as arguments) // that allows us to return more specific symbols (a specific overload or applicable candidates) // we return these. The complete set of symbols of the method group is then returned in methodGroup parameter. private ImmutableArray<Symbol> GetMethodGroupSemanticSymbols( BoundMethodGroup boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, out LookupResultKind resultKind, out bool isDynamic, out ImmutableArray<Symbol> methodGroup) { Debug.Assert(binderOpt != null || IsInTree(boundNode.Syntax)); ImmutableArray<Symbol> symbols = ImmutableArray<Symbol>.Empty; resultKind = boundNode.ResultKind; if (resultKind == LookupResultKind.Empty) { resultKind = LookupResultKind.Viable; } isDynamic = false; // The method group needs filtering. Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(boundNode.Syntax)); methodGroup = GetReducedAndFilteredMethodGroupSymbols(binder, boundNode).Cast<MethodSymbol, Symbol>(); // We want to get the actual node chosen by overload resolution, if possible. if (boundNodeForSyntacticParent != null) { switch (boundNodeForSyntacticParent.Kind) { case BoundKind.Call: // If we are looking for info on M in M(args), we want the symbol that overload resolution // chose for M. var call = (BoundCall)boundNodeForSyntacticParent; InvocationExpressionSyntax invocation = call.Syntax as InvocationExpressionSyntax; if (invocation != null && invocation.Expression.SkipParens() == boundNode.Syntax.SkipParens() && (object)call.Method != null) { if (call.OriginalMethodsOpt.IsDefault) { // Overload resolution succeeded. symbols = CreateReducedExtensionMethodIfPossible(call); resultKind = LookupResultKind.Viable; } else { resultKind = call.ResultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); symbols = StaticCast<Symbol>.From(CreateReducedExtensionMethodsFromOriginalsIfNecessary(call)); } } break; case BoundKind.DelegateCreationExpression: // If we are looking for info on "M" in "new Action(M)" // we want to get the symbol that overload resolution chose for M, not the whole method group M. var delegateCreation = (BoundDelegateCreationExpression)boundNodeForSyntacticParent; if (delegateCreation.Argument == boundNode && (object)delegateCreation.MethodOpt != null) { symbols = CreateReducedExtensionMethodIfPossible(delegateCreation, boundNode.ReceiverOpt); } break; case BoundKind.Conversion: // If we are looking for info on "M" in "(Action)M" // we want to get the symbol that overload resolution chose for M, not the whole method group M. var conversion = (BoundConversion)boundNodeForSyntacticParent; var method = conversion.SymbolOpt; if ((object)method != null) { Debug.Assert(conversion.ConversionKind == ConversionKind.MethodGroup); if (conversion.IsExtensionMethod) { method = ReducedExtensionMethodSymbol.Create(method); } symbols = ImmutableArray.Create((Symbol)method); resultKind = conversion.ResultKind; } else { goto default; } break; case BoundKind.DynamicInvocation: var dynamicInvocation = (BoundDynamicInvocation)boundNodeForSyntacticParent; symbols = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>(); isDynamic = true; break; case BoundKind.BadExpression: // If the bad expression has symbol(s) from this method group, it better indicates any problems. ImmutableArray<Symbol> myMethodGroup = methodGroup; symbols = ((BoundBadExpression)boundNodeForSyntacticParent).Symbols.WhereAsArray(sym => myMethodGroup.Contains(sym)); if (symbols.Any()) { resultKind = ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind; } break; case BoundKind.NameOfOperator: symbols = methodGroup; resultKind = resultKind.WorseResultKind(LookupResultKind.MemberGroup); break; default: symbols = methodGroup; if (symbols.Length > 0) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } break; } } else if (methodGroup.Length == 1 && !boundNode.HasAnyErrors) { // During speculative binding, there won't be a parent bound node. The parent bound // node may also be absent if the syntactic parent has errors or if one is simply // not specified (see SemanticModel.GetSymbolInfoForNode). However, if there's exactly // one candidate, then we should probably succeed. symbols = methodGroup; if (symbols.Length > 0) { resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } } if (!symbols.Any()) { // If we didn't find a better set of symbols, then assume this is a method group that didn't // get resolved. Return all members of the method group, with a resultKind of OverloadResolutionFailure // (unless the method group already has a worse result kind). symbols = methodGroup; if (!isDynamic && resultKind > LookupResultKind.OverloadResolutionFailure) { resultKind = LookupResultKind.OverloadResolutionFailure; } } return symbols; }
private void AdjustSymbolsForObjectCreation( BoundNode lowestBoundNode, NamedTypeSymbol typeSymbolOpt, MethodSymbol constructorOpt, Binder binderOpt, ref LookupResultKind resultKind, ref ImmutableArray<Symbol> symbols, ref ImmutableArray<Symbol> memberGroup) { Debug.Assert(lowestBoundNode != null); Debug.Assert(binderOpt != null || IsInTree(lowestBoundNode.Syntax)); if ((object)typeSymbolOpt != null) { Debug.Assert(lowestBoundNode.Syntax != null); // Filter typeSymbol's instance constructors by accessibility. // If all the instance constructors are inaccessible, we retain // all of them for correct semantic info. Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(lowestBoundNode.Syntax)); ImmutableArray<MethodSymbol> candidateConstructors; if (binder != null) { var instanceConstructors = typeSymbolOpt.IsInterfaceType() && (object)typeSymbolOpt.ComImportCoClass != null ? typeSymbolOpt.ComImportCoClass.InstanceConstructors : typeSymbolOpt.InstanceConstructors; HashSet<DiagnosticInfo> useSiteDiagnostics = null; candidateConstructors = binder.FilterInaccessibleConstructors(instanceConstructors, allowProtectedConstructorsOfBaseType: false, useSiteDiagnostics: ref useSiteDiagnostics); if ((object)constructorOpt == null ? !candidateConstructors.Any() : !candidateConstructors.Contains(constructorOpt)) { // All instance constructors are inaccessible or if the specified constructor // isn't a candidate, then we retain all of them for correct semantic info. Debug.Assert(resultKind != LookupResultKind.Viable); candidateConstructors = instanceConstructors; } } else { candidateConstructors = ImmutableArray<MethodSymbol>.Empty; } if ((object)constructorOpt != null) { Debug.Assert(candidateConstructors.Contains(constructorOpt)); symbols = ImmutableArray.Create<Symbol>(constructorOpt); } else if (candidateConstructors.Length > 0) { symbols = StaticCast<Symbol>.From(candidateConstructors); Debug.Assert(resultKind != LookupResultKind.Viable); resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } memberGroup = candidateConstructors.Cast<MethodSymbol, Symbol>(); } }
// In cases where we are binding C in "[C(...)]", the bound nodes return the symbol for the type. However, we've // decided that we want this case to return the constructor of the type instead. This affects attributes. // This method checks for this situation and adjusts the syntax and method or property group. private void AdjustSymbolsForObjectCreation(BoundExpression boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, ref LookupResultKind resultKind, ref ImmutableArray<Symbol> symbols, ref ImmutableArray<Symbol> memberGroup) { NamedTypeSymbol typeSymbol = null; MethodSymbol constructor = null; // Check if boundNode.Syntax is the type-name child of an Attribute. CSharpSyntaxNode parentSyntax = boundNodeForSyntacticParent.Syntax; if (parentSyntax != null && parentSyntax == boundNode.Syntax.Parent && parentSyntax.Kind() == SyntaxKind.Attribute && ((AttributeSyntax)parentSyntax).Name == boundNode.Syntax) { var unwrappedSymbols = UnwrapAliases(symbols); switch (boundNodeForSyntacticParent.Kind) { case BoundKind.Attribute: BoundAttribute boundAttribute = (BoundAttribute)boundNodeForSyntacticParent; if (unwrappedSymbols.Length == 1 && unwrappedSymbols[0].Kind == SymbolKind.NamedType) { Debug.Assert(resultKind != LookupResultKind.Viable || unwrappedSymbols[0] == boundAttribute.Type.GetNonErrorGuess()); typeSymbol = (NamedTypeSymbol)unwrappedSymbols[0]; constructor = boundAttribute.Constructor; resultKind = resultKind.WorseResultKind(boundAttribute.ResultKind); } break; case BoundKind.BadExpression: BoundBadExpression boundBadExpression = (BoundBadExpression)boundNodeForSyntacticParent; if (unwrappedSymbols.Length == 1) { resultKind = resultKind.WorseResultKind(boundBadExpression.ResultKind); typeSymbol = unwrappedSymbols[0] as NamedTypeSymbol; } break; default: throw ExceptionUtilities.UnexpectedValue(boundNodeForSyntacticParent.Kind); } AdjustSymbolsForObjectCreation(boundNode, typeSymbol, constructor, binderOpt, ref resultKind, ref symbols, ref memberGroup); } }
// Get the symbols and possible method or property group associated with a bound node, as // they should be exposed through GetSemanticInfo. // NB: It is not safe to pass a null binderOpt during speculative binding. private ImmutableArray<Symbol> GetSemanticSymbols(BoundExpression boundNode, BoundNode boundNodeForSyntacticParent, Binder binderOpt, SymbolInfoOptions options, out bool isDynamic, out LookupResultKind resultKind, out ImmutableArray<Symbol> memberGroup) { memberGroup = ImmutableArray<Symbol>.Empty; ImmutableArray<Symbol> symbols = ImmutableArray<Symbol>.Empty; resultKind = LookupResultKind.Viable; isDynamic = false; switch (boundNode.Kind) { case BoundKind.MethodGroup: symbols = GetMethodGroupSemanticSymbols((BoundMethodGroup)boundNode, boundNodeForSyntacticParent, binderOpt, out resultKind, out isDynamic, out memberGroup); break; case BoundKind.PropertyGroup: symbols = GetPropertyGroupSemanticSymbols((BoundPropertyGroup)boundNode, boundNodeForSyntacticParent, binderOpt, out resultKind, out memberGroup); break; case BoundKind.BadExpression: { var expr = (BoundBadExpression)boundNode; resultKind = expr.ResultKind; if (expr.Syntax.Kind() == SyntaxKind.ObjectCreationExpression) { if (resultKind == LookupResultKind.NotCreatable) { return expr.Symbols; } else if (expr.Type.IsDelegateType()) { resultKind = LookupResultKind.Empty; return symbols; } memberGroup = expr.Symbols; } return expr.Symbols; } case BoundKind.DelegateCreationExpression: break; case BoundKind.TypeExpression: { var boundType = (BoundTypeExpression)boundNode; // Watch out for not creatable types within object creation syntax if (boundNodeForSyntacticParent != null && boundNodeForSyntacticParent.Syntax.Kind() == SyntaxKind.ObjectCreationExpression && ((ObjectCreationExpressionSyntax)boundNodeForSyntacticParent.Syntax).Type == boundType.Syntax && boundNodeForSyntacticParent.Kind == BoundKind.BadExpression && ((BoundBadExpression)boundNodeForSyntacticParent).ResultKind == LookupResultKind.NotCreatable) { resultKind = LookupResultKind.NotCreatable; } // could be a type or alias. var typeSymbol = boundType.AliasOpt ?? (Symbol)boundType.Type; var originalErrorType = typeSymbol.OriginalDefinition as ErrorTypeSymbol; if ((object)originalErrorType != null) { resultKind = originalErrorType.ResultKind; symbols = originalErrorType.CandidateSymbols; } else { symbols = ImmutableArray.Create<Symbol>(typeSymbol); } } break; case BoundKind.TypeOrValueExpression: { // If we're seeing a node of this kind, then we failed to resolve the member access // as either a type or a property/field/event/local/parameter. In such cases, // the second interpretation applies so just visit the node for that. BoundExpression valueExpression = ((BoundTypeOrValueExpression)boundNode).Data.ValueExpression; return GetSemanticSymbols(valueExpression, boundNodeForSyntacticParent, binderOpt, options, out isDynamic, out resultKind, out memberGroup); } case BoundKind.Call: { // Either overload resolution succeeded for this call or it did not. If it // did not succeed then we've stashed the original method symbols from the // method group, and we should use those as the symbols displayed for the // call. If it did succeed then we did not stash any symbols; just fall // through to the default case. var call = (BoundCall)boundNode; if (call.OriginalMethodsOpt.IsDefault) { if ((object)call.Method != null) { symbols = CreateReducedExtensionMethodIfPossible(call); resultKind = call.ResultKind; } } else { symbols = StaticCast<Symbol>.From(CreateReducedExtensionMethodsFromOriginalsIfNecessary(call)); resultKind = call.ResultKind; } } break; case BoundKind.IndexerAccess: { // As for BoundCall, pull out stashed candidates if overload resolution failed. BoundIndexerAccess indexerAccess = (BoundIndexerAccess)boundNode; Debug.Assert((object)indexerAccess.Indexer != null); resultKind = indexerAccess.ResultKind; ImmutableArray<PropertySymbol> originalIndexersOpt = indexerAccess.OriginalIndexersOpt; symbols = originalIndexersOpt.IsDefault ? ImmutableArray.Create<Symbol>(indexerAccess.Indexer) : StaticCast<Symbol>.From(originalIndexersOpt); } break; case BoundKind.EventAssignmentOperator: var eventAssignment = (BoundEventAssignmentOperator)boundNode; isDynamic = eventAssignment.IsDynamic; var eventSymbol = eventAssignment.Event; var methodSymbol = eventAssignment.IsAddition ? eventSymbol.AddMethod : eventSymbol.RemoveMethod; if ((object)methodSymbol == null) { symbols = ImmutableArray<Symbol>.Empty; resultKind = LookupResultKind.Empty; } else { symbols = ImmutableArray.Create<Symbol>(methodSymbol); resultKind = eventAssignment.ResultKind; } break; case BoundKind.Conversion: var conversion = (BoundConversion)boundNode; isDynamic = conversion.ConversionKind.IsDynamic(); if (!isDynamic) { if ((conversion.ConversionKind == ConversionKind.MethodGroup) && conversion.IsExtensionMethod) { var symbol = conversion.SymbolOpt; Debug.Assert((object)symbol != null); symbols = ImmutableArray.Create<Symbol>(ReducedExtensionMethodSymbol.Create(symbol)); resultKind = conversion.ResultKind; } else if (conversion.ConversionKind.IsUserDefinedConversion()) { GetSymbolsAndResultKind(conversion, conversion.SymbolOpt, conversion.OriginalUserDefinedConversionsOpt, out symbols, out resultKind); } else { goto default; } } break; case BoundKind.BinaryOperator: GetSymbolsAndResultKind((BoundBinaryOperator)boundNode, out isDynamic, ref resultKind, ref symbols); break; case BoundKind.UnaryOperator: GetSymbolsAndResultKind((BoundUnaryOperator)boundNode, out isDynamic, ref resultKind, ref symbols); break; case BoundKind.UserDefinedConditionalLogicalOperator: var @operator = (BoundUserDefinedConditionalLogicalOperator)boundNode; isDynamic = false; GetSymbolsAndResultKind(@operator, @operator.LogicalOperator, @operator.OriginalUserDefinedOperatorsOpt, out symbols, out resultKind); break; case BoundKind.CompoundAssignmentOperator: GetSymbolsAndResultKind((BoundCompoundAssignmentOperator)boundNode, out isDynamic, ref resultKind, ref symbols); break; case BoundKind.IncrementOperator: GetSymbolsAndResultKind((BoundIncrementOperator)boundNode, out isDynamic, ref resultKind, ref symbols); break; case BoundKind.AwaitExpression: var await = (BoundAwaitExpression)boundNode; isDynamic = await.IsDynamic; // TODO: goto default; case BoundKind.ConditionalOperator: Debug.Assert((object)boundNode.ExpressionSymbol == null); var conditional = (BoundConditionalOperator)boundNode; isDynamic = conditional.IsDynamic; goto default; case BoundKind.Attribute: { Debug.Assert(boundNodeForSyntacticParent == null); var attribute = (BoundAttribute)boundNode; resultKind = attribute.ResultKind; // If attribute name bound to a single named type or an error type // with a single named type candidate symbol, we will return constructors // of the named type in the semantic info. // Otherwise, we will return the error type candidate symbols. var namedType = (NamedTypeSymbol)attribute.Type; if (namedType.IsErrorType()) { Debug.Assert(resultKind != LookupResultKind.Viable); var errorType = (ErrorTypeSymbol)namedType; var candidateSymbols = errorType.CandidateSymbols; // If error type has a single named type candidate symbol, we want to // use that type for symbol info. if (candidateSymbols.Length == 1 && candidateSymbols[0] is NamedTypeSymbol) { namedType = (NamedTypeSymbol)candidateSymbols[0]; } else { symbols = candidateSymbols; break; } } AdjustSymbolsForObjectCreation(attribute, namedType, attribute.Constructor, binderOpt, ref resultKind, ref symbols, ref memberGroup); } break; case BoundKind.QueryClause: { var query = (BoundQueryClause)boundNode; var builder = ArrayBuilder<Symbol>.GetInstance(); if (query.Operation != null && (object)query.Operation.ExpressionSymbol != null) builder.Add(query.Operation.ExpressionSymbol); if ((object)query.DefinedSymbol != null) builder.Add(query.DefinedSymbol); if (query.Cast != null && (object)query.Cast.ExpressionSymbol != null) builder.Add(query.Cast.ExpressionSymbol); symbols = builder.ToImmutableAndFree(); } break; case BoundKind.DynamicInvocation: Debug.Assert((object)boundNode.ExpressionSymbol == null); var dynamicInvocation = (BoundDynamicInvocation)boundNode; symbols = memberGroup = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>(); isDynamic = true; break; case BoundKind.DynamicCollectionElementInitializer: Debug.Assert((object)boundNode.ExpressionSymbol == null); var collectionInit = (BoundDynamicCollectionElementInitializer)boundNode; symbols = memberGroup = collectionInit.ApplicableMethods.Cast<MethodSymbol, Symbol>(); isDynamic = true; break; case BoundKind.DynamicIndexerAccess: Debug.Assert((object)boundNode.ExpressionSymbol == null); var dynamicIndexer = (BoundDynamicIndexerAccess)boundNode; symbols = memberGroup = dynamicIndexer.ApplicableIndexers.Cast<PropertySymbol, Symbol>(); isDynamic = true; break; case BoundKind.DynamicMemberAccess: Debug.Assert((object)boundNode.ExpressionSymbol == null); isDynamic = true; break; case BoundKind.DynamicObjectCreationExpression: var objectCreation = (BoundDynamicObjectCreationExpression)boundNode; symbols = memberGroup = objectCreation.ApplicableMethods.Cast<MethodSymbol, Symbol>(); isDynamic = true; break; case BoundKind.ObjectCreationExpression: var boundObjectCreation = (BoundObjectCreationExpression)boundNode; if ((object)boundObjectCreation.Constructor != null) { Debug.Assert(boundObjectCreation.ConstructorsGroup.Contains(boundObjectCreation.Constructor)); symbols = ImmutableArray.Create<Symbol>(boundObjectCreation.Constructor); } else if (boundObjectCreation.ConstructorsGroup.Length > 0) { symbols = StaticCast<Symbol>.From(boundObjectCreation.ConstructorsGroup); resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure); } memberGroup = boundObjectCreation.ConstructorsGroup.Cast<MethodSymbol, Symbol>(); break; case BoundKind.ThisReference: case BoundKind.BaseReference: { Binder binder = binderOpt ?? GetEnclosingBinder(GetAdjustedNodePosition(boundNode.Syntax)); NamedTypeSymbol containingType = binder.ContainingType; var containingMember = binder.ContainingMember(); var thisParam = GetThisParameter(boundNode.Type, containingType, containingMember, out resultKind); symbols = ImmutableArray.Create<Symbol>(thisParam); } break; default: { var symbol = boundNode.ExpressionSymbol; if ((object)symbol != null) { symbols = ImmutableArray.Create(symbol); resultKind = boundNode.ResultKind; } } break; } if (boundNodeForSyntacticParent != null && (options & SymbolInfoOptions.PreferConstructorsToType) != 0) { // Adjust symbols to get the constructors if we're T in a "new T(...)". AdjustSymbolsForObjectCreation(boundNode, boundNodeForSyntacticParent, binderOpt, ref resultKind, ref symbols, ref memberGroup); } return symbols; }