private static bool MethodSymbolMatchesParamInfo(MethodSymbol candidateMethod, ParamInfo <TypeSymbol>[] targetParamInfo) { int numParams = targetParamInfo.Length - 1; //don't count return type if (candidateMethod.ParameterCount != numParams) { return(false); } // IndexedTypeParameterSymbol is not going to be exposed anywhere, // so we'll cheat and use it here for comparison purposes. TypeMap candidateMethodTypeMap = new TypeMap( candidateMethod.TypeParameters, IndexedTypeParameterSymbol.Take(candidateMethod.Arity), true); if (!ReturnTypesMatch(candidateMethod, candidateMethodTypeMap, ref targetParamInfo[0])) { return(false); } for (int i = 0; i < numParams; i++) { if (!ParametersMatch(candidateMethod.Parameters[i], candidateMethodTypeMap, ref targetParamInfo[i + 1 /*for return type*/])) { return(false); } } return(true); }
public void TestTake() { var zero = IndexedTypeParameterSymbol.Take(0); Assert.Equal(0, zero.Length); var five = IndexedTypeParameterSymbol.Take(5); Assert.Equal(5, five.Length); Assert.Equal(five[0], IndexedTypeParameterSymbol.GetTypeParameter(0)); Assert.Equal(five[1], IndexedTypeParameterSymbol.GetTypeParameter(1)); Assert.Equal(five[2], IndexedTypeParameterSymbol.GetTypeParameter(2)); Assert.Equal(five[3], IndexedTypeParameterSymbol.GetTypeParameter(3)); Assert.Equal(five[4], IndexedTypeParameterSymbol.GetTypeParameter(4)); var fifty = IndexedTypeParameterSymbol.Take(50); Assert.Equal(50, fifty.Length); // prove they are all unique var set = new HashSet <TypeParameterSymbol>(fifty); Assert.Equal(50, set.Count); var fiveHundred = IndexedTypeParameterSymbol.Take(500); Assert.Equal(500, fiveHundred.Length); }
private static bool MethodSymbolMatchesParamInfo(MethodSymbol candidateMethod, ParamInfo <TypeSymbol>[] targetParamInfo) { int numParams = targetParamInfo.Length - 1; //don't count return type if (candidateMethod.ParameterCount != numParams) { return(false); } // IndexedTypeParameterSymbol is not going to be exposed anywhere, // so we'll cheat and use it here for comparison purposes. TypeMap candidateMethodTypeMap = new TypeMap( nonNullTypesContext: NonNullTypesFalseContext.Instance, // The NonNullType context doesn't really matter here, because nullability of reference types is not considered for the purpose of the method. candidateMethod.TypeParameters, IndexedTypeParameterSymbol.Take(candidateMethod.Arity), true); if (!ReturnTypesMatch(candidateMethod, candidateMethodTypeMap, ref targetParamInfo[0])) { return(false); } for (int i = 0; i < numParams; i++) { if (!ParametersMatch(candidateMethod.Parameters[i], candidateMethodTypeMap, ref targetParamInfo[i + 1 /*for return type*/])) { return(false); } } return(true); }
private static MethodSymbol SubstituteTypeParameters(MethodSymbol method) { Debug.Assert(method.IsDefinition); var typeParameters = method.TypeParameters; int n = typeParameters.Length; if (n == 0) { return method; } return method.Construct(IndexedTypeParameterSymbol.Take(n).Cast<TypeParameterSymbol, TypeSymbol>()); }
private static ImmutableArray <Symbol> PerformCrefOverloadResolution(ArrayBuilder <Symbol> candidates, ImmutableArray <ParameterSymbol> parameterSymbols, int arity, MemberCrefSyntax memberSyntax, out Symbol?ambiguityWinner, DiagnosticBag diagnostics) { ArrayBuilder <Symbol>?viable = null; foreach (Symbol candidate in candidates) { // BREAK: In dev11, any candidate with the type "dynamic" anywhere in its parameter list would be skipped // (see XmlDocCommentBinder::bindXmlReference). Apparently, this was because "the params that the xml doc // comments produce never will." This does not appear to have made sense in dev11 (skipping dropping the // candidate doesn't cause anything to blow up and may cause resolution to start succeeding) and it almost // certainly does not in roslyn (the signature comparer ignores the object-dynamic distinction anyway). Symbol signatureMember; switch (candidate.Kind) { case SymbolKind.Method: { MethodSymbol candidateMethod = (MethodSymbol)candidate; MethodKind candidateMethodKind = candidateMethod.MethodKind; bool candidateMethodIsVararg = candidateMethod.IsVararg; // If the arity from the cref is zero, then we accept methods of any arity. int signatureMemberArity = candidateMethodKind == MethodKind.Constructor ? 0 : (arity == 0 ? candidateMethod.Arity : arity); // CONSIDER: we might want to reuse this method symbol (as long as the MethodKind and Vararg-ness match). signatureMember = new SignatureOnlyMethodSymbol( methodKind: candidateMethodKind, typeParameters: IndexedTypeParameterSymbol.Take(signatureMemberArity), parameters: parameterSymbols, // This specific comparer only looks for varargs. callingConvention: candidateMethodIsVararg ? Microsoft.Cci.CallingConvention.ExtraArguments : Microsoft.Cci.CallingConvention.HasThis, // These are ignored by this specific MemberSignatureComparer. containingType: null, name: null, refKind: RefKind.None, isInitOnly: false, returnType: default, refCustomModifiers: ImmutableArray <CustomModifier> .Empty, explicitInterfaceImplementations: ImmutableArray <MethodSymbol> .Empty); break; }
/// <summary> /// Given a list of method and/or property candidates, choose the first one (if any) with a signature /// that matches the parameter list in the cref. Return null if there isn't one. /// </summary> /// <remarks> /// Produces a diagnostic for ambiguous matches, but not for unresolved members - WRN_BadXMLRef is /// handled in BindMemberCref. /// </remarks> private static ImmutableArray <Symbol> PerformCrefOverloadResolution(ArrayBuilder <Symbol> candidates, ImmutableArray <ParameterSymbol> parameterSymbols, int arity, MemberCrefSyntax memberSyntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics) { ArrayBuilder <Symbol> viable = null; foreach (Symbol candidate in candidates) { // BREAK: In dev11, any candidate with the type "dynamic" anywhere in its parameter list would be skipped // (see XmlDocCommentBinder::bindXmlReference). Apparently, this was because "the params that the xml doc // comments produce never will." This does not appear to have made sense in dev11 (skipping dropping the // candidate doesn't cause anything to blow up and may cause resolution to start succeeding) and it almost // certainly does not in roslyn (the signature comparer ignores the object-dynamic distiction anyway). Symbol signatureMember; switch (candidate.Kind) { case SymbolKind.Method: { MethodSymbol candidateMethod = (MethodSymbol)candidate; MethodKind candidateMethodKind = candidateMethod.MethodKind; bool candidateMethodIsVararg = candidateMethod.IsVararg; // If the arity from the cref is zero, then we accept methods of any arity. int signatureMemberArity = candidateMethodKind == MethodKind.Constructor ? 0 : (arity == 0 ? candidateMethod.Arity : arity); // CONSIDER: we might want to reuse this method symbol (as long as the MethodKind and Vararg-ness match). signatureMember = new SignatureOnlyMethodSymbol( methodKind: candidateMethodKind, typeParameters: IndexedTypeParameterSymbol.Take(signatureMemberArity), parameters: parameterSymbols, // This specific comparer only looks for varargs. callingConvention: candidateMethodIsVararg ? Microsoft.Cci.CallingConvention.ExtraArguments : Microsoft.Cci.CallingConvention.HasThis, // These are ignored by this specific MemberSignatureComparer. containingType: null, name: null, returnType: null, returnTypeCustomModifiers: ImmutableArray <CustomModifier> .Empty, explicitInterfaceImplementations: ImmutableArray <MethodSymbol> .Empty); break; } case SymbolKind.Property: { // CONSIDER: we might want to reuse this property symbol. signatureMember = new SignatureOnlyPropertySymbol( parameters: parameterSymbols, // These are ignored by this specific MemberSignatureComparer. containingType: null, name: null, type: null, typeCustomModifiers: ImmutableArray <CustomModifier> .Empty, isStatic: false, explicitInterfaceImplementations: ImmutableArray <PropertySymbol> .Empty); break; } case SymbolKind.NamedType: // Because we replaced them with constructors when we built the candidate list. throw ExceptionUtilities.UnexpectedValue(candidate.Kind); default: continue; } if (MemberSignatureComparer.CrefComparer.Equals(signatureMember, candidate)) { Debug.Assert(candidate.GetMemberArity() != 0 || candidate.Name == WellKnownMemberNames.InstanceConstructorName || arity == 0, "Can only have a 0-arity, non-constructor candidate if the desired arity is 0."); if (viable == null) { viable = ArrayBuilder <Symbol> .GetInstance(); viable.Add(candidate); } else { bool oldArityIsZero = viable[0].GetMemberArity() == 0; bool newArityIsZero = candidate.GetMemberArity() == 0; // If the cref specified arity 0 and the current candidate has arity 0 but the previous // match did not, then the current candidate is the unambiguous winner (unless there's // another match with arity 0 in a subsequent iteration). if (!oldArityIsZero || newArityIsZero) { if (!oldArityIsZero && newArityIsZero) { viable.Clear(); } viable.Add(candidate); } } } } if (viable == null) { ambiguityWinner = null; return(ImmutableArray <Symbol> .Empty); } if (viable.Count > 1) { ambiguityWinner = viable[0]; CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax); diagnostics.Add(ErrorCode.WRN_AmbiguousXMLReference, crefSyntax.Location, crefSyntax.ToString(), ambiguityWinner, viable[1]); } else { ambiguityWinner = null; } return(viable.ToImmutableAndFree()); }
internal ReadOnlyArray <TypeSymbol> ArgumentTypes(MethodSymbol method) { return(new TypeMap( IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(), method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteTypes(declaredParameterTypes)); }
internal TypeSymbol ReturnType(MethodSymbol method) { return(new TypeMap( IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(), method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteType(declaredReturnType)); }