예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
            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>());
            }
예제 #5
0
        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;
                }
예제 #6
0
        /// <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());
        }
예제 #7
0
 internal ReadOnlyArray <TypeSymbol> ArgumentTypes(MethodSymbol method)
 {
     return(new TypeMap(
                IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(),
                method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteTypes(declaredParameterTypes));
 }
예제 #8
0
 internal TypeSymbol ReturnType(MethodSymbol method)
 {
     return(new TypeMap(
                IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(),
                method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteType(declaredReturnType));
 }