Esempio n. 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(
                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 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.TakeSymbols(0);

            Assert.Equal(0, zero.Length);

            var five = IndexedTypeParameterSymbol.TakeSymbols(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.TakeSymbols(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.TakeSymbols(500);

            Assert.Equal(500, fiveHundred.Length);
        }
Esempio n. 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>());
            }
Esempio n. 5
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, BindingDiagnosticBag 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.TakeSymbols(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,
                        isStatic: false,
                        returnType: default,
                        refCustomModifiers: ImmutableArray <CustomModifier> .Empty,
                        explicitInterfaceImplementations: ImmutableArray <MethodSymbol> .Empty);
                    break;
                }
 /// <summary>
 /// We know that we'll never have a method context because that's what we're
 /// trying to find.  Instead, just return an indexed type parameter that will
 /// make comparison easier.
 /// </summary>
 /// <param name="position"></param>
 /// <returns></returns>
 protected override TypeSymbol GetGenericMethodTypeParamSymbol(int position)
 {
     // Note: technically this is a source symbol, but we only care about the position
     return(IndexedTypeParameterSymbol.GetTypeParameter(position));
 }
Esempio n. 7
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());
        }
Esempio n. 8
0
        private MethodMemberBuilder(NamedTypeSymbol container, Binder enclosing, MemberDeclarationSyntax syntax, DiagnosticBag diagnostics)
            : base(enclosing.Location(syntax) as SourceLocation, container, enclosing)
        {
            Debug.Assert(syntax != null);
            this.syntax = syntax;

            // Make a binder context in which each type parameter binds to a corresponding numbered type parameter
            Binder parametersContext = Enclosing;

            if (syntax.Kind == SyntaxKind.MethodDeclaration)
            {
                var methodSyntax = syntax as MethodDeclarationSyntax;
                int arity        = methodSyntax.Arity;
                if (arity != 0)
                {
                    var typeParamMap = new MultiDictionary <string, TypeParameterSymbol>();
                    var typeParams   = methodSyntax.TypeParameterListOpt.Parameters;

                    for (int iParam = 0; iParam < typeParams.Count; iParam++)
                    {
                        var arg    = typeParams[iParam];
                        var symbol = IndexedTypeParameterSymbol.GetTypeParameter(iParam);
                        typeParamMap.Add(arg.Identifier.ValueText, symbol);
                    }

                    parametersContext = new WithDummyTypeParametersBinder(typeParamMap, Enclosing);
                }

                if (methodSyntax.ExplicitInterfaceSpecifierOpt != null)
                {
                    this.explicitInterfaceType = enclosing.BindType(methodSyntax.ExplicitInterfaceSpecifierOpt.Name, diagnostics);
                }
            }

            // TODOngafter 1: recast this code using ReadOnlyArray.
            IEnumerable <ParameterSyntax> parameters = SyntaxParameters.HasValue ? SyntaxParameters.Value : SpecializedCollections.EmptyEnumerable <ParameterSyntax>();

            declaredParameterTypes = parameters.Select(p =>
            {
                if (p.TypeOpt == null)
                {
                    return(new CSErrorTypeSymbol(enclosing.Compilation.GlobalNamespace, "ErrorType", 0, diagnostics.Add(ErrorCode.ERR_NotYetImplementedInRoslyn, new SourceLocation(Tree, p))));
                }
                return(parametersContext.BindType(p.TypeOpt, diagnostics));
            }).ToList();

            var parameterRefs = parameters.Select(p => p.Modifiers.GetRefKind()).ToList();

            switch (syntax.Kind)
            {
            case SyntaxKind.ConstructorDeclaration:
                Binder original = parametersContext;     // TODOngafter 1: worry about diagnostic reporting and suppression here.
                declaredReturnType = Enclosing.GetSpecialType(SpecialType.System_Void, diagnostics, syntax);
                break;

            default:
                declaredReturnType = parametersContext.BindType(SyntaxReturnType, diagnostics);
                break;
            }

            TypeSymbol explType   = null;
            var        explSyntax = ExplicitInterface;

            if (explSyntax != null)
            {
                explType = parametersContext.BindType(explSyntax, diagnostics);
            }

            // TODOngafter 3: map dynamic->object for the signature
            this.signature = new MethodSignature(Name, SyntaxArity, declaredParameterTypes, parameterRefs, explType);
        }
Esempio n. 9
0
 internal ReadOnlyArray <TypeSymbol> ArgumentTypes(MethodSymbol method)
 {
     return(new TypeMap(
                IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(),
                method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteTypes(declaredParameterTypes));
 }
Esempio n. 10
0
 internal TypeSymbol ReturnType(MethodSymbol method)
 {
     return(new TypeMap(
                IndexedTypeParameterSymbol.Take(SyntaxArity).AsReadOnly <TypeSymbol>(),
                method.TypeParameters.Cast <TypeParameterSymbol, TypeSymbol>()).SubstituteType(declaredReturnType));
 }