예제 #1
0
        public SpecializedMethod(IMethod methodDefinition, TypeParameterSubstitution substitution)
            : base(methodDefinition)
        {
            SpecializedMethod specializedMethodDefinition = methodDefinition as SpecializedMethod;

            if (specializedMethodDefinition != null)
            {
                this.genericMethodIsSpecialized = specializedMethodDefinition.genericMethodIsSpecialized;
            }

            // The base ctor might have unpacked a SpecializedMember
            // (in case we are specializing an already-specialized method)
            methodDefinition      = (IMethod)base.baseMember;
            this.methodDefinition = methodDefinition;
            if (methodDefinition.TypeParameters.Count > 0)
            {
                // The method is generic, so we need to specialize the type parameters
                // (for specializing the constraints, and also to set the correct Owner)
                specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count];
                for (int i = 0; i < specializedTypeParameters.Length; i++)
                {
                    specializedTypeParameters[i] = new SpecializedTypeParameter(methodDefinition.TypeParameters[i], this);
                }
                if (!genericMethodIsSpecialized)
                {
                    // Add substitution that replaces the base method's type parameters with our specialized version
                    // but do this only if the type parameters on the baseMember have not already been substituted
                    substitutionWithoutSpecializedTypeParameters = this.Substitution;
                    AddSubstitution(new TypeParameterSubstitution(null, specializedTypeParameters));
                }
            }
            // Add the main substitution after the method type parameter specialization.
            AddSubstitution(substitution);
            if (substitutionWithoutSpecializedTypeParameters != null)
            {
                // If we already have a substitution without specialized type parameters, update that:
                substitutionWithoutSpecializedTypeParameters = TypeParameterSubstitution.Compose(substitution, substitutionWithoutSpecializedTypeParameters);
            }
            else
            {
                // Otherwise just use the whole substitution, as that doesn't contain specialized type parameters
                // in this case.
                substitutionWithoutSpecializedTypeParameters = this.Substitution;
            }
            if (substitution != null && substitution.MethodTypeArguments != null && methodDefinition.TypeParameters.Count > 0)
            {
                this.genericMethodIsSpecialized = true;
            }
            if (specializedTypeParameters != null)
            {
                // Set the substitution on the type parameters to the final composed substitution
                foreach (var tp in specializedTypeParameters.OfType <SpecializedTypeParameter>())
                {
                    if (tp.Owner == this)
                    {
                        tp.substitution = base.Substitution;
                    }
                }
            }
        }
예제 #2
0
        public override bool Equals(object obj)
        {
            SpecializedMethod other = obj as SpecializedMethod;

            if (other == null)
            {
                return(false);
            }
            return(object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType));
        }
예제 #3
0
        public override bool Equals(object obj)
        {
            SpecializedMethod other = obj as SpecializedMethod;

            if (other == null)
            {
                return(false);
            }
            return(this.baseMember.Equals(other.baseMember) && this.substitutionWithoutSpecializedTypeParameters.Equals(other.substitutionWithoutSpecializedTypeParameters));
        }
        internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition)
        {
            if (accessorDefinition == null)
            {
                return(null);
            }
            var result = LazyInit.VolatileRead(ref cachingField);

            if (result != null)
            {
                return(result);
            }
            else
            {
                var sm = new SpecializedMethod(accessorDefinition, substitution);
                //sm.AccessorOwner = this;
                return(LazyInit.GetOrSet(ref cachingField, sm));
            }
        }
예제 #5
0
 public IEnumerable <IMethod> GetConstructors(Predicate <IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
 {
     if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
     {
         if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint)
         {
             if (filter == null || filter(dummyConstructor))
             {
                 var     resolvedCtor = (IMethod)dummyConstructor.CreateResolved(compilation.TypeResolveContext);
                 IMethod m            = new SpecializedMethod(this, resolvedCtor, EmptyList <IType> .Instance);
                 return(new [] { m });
             }
         }
         return(EmptyList <IMethod> .Instance);
     }
     else
     {
         return(GetMembersHelper.GetConstructors(this, filter, options));
     }
 }
예제 #6
0
        public override bool Equals(object obj)
        {
            SpecializedMethod other = obj as SpecializedMethod;

            if (!base.Equals(other))
            {
                return(false);
            }
            if (typeArguments.Count != other.typeArguments.Count)
            {
                return(false);
            }
            for (int i = 0; i < typeArguments.Count; i++)
            {
                if (!typeArguments[i].Equals(other.typeArguments[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #7
0
 public IEnumerable <IMethod> GetConstructors(Predicate <IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
 {
     if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
     {
         if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint)
         {
             if (filter == null || filter(dummyConstructor))
             {
                 var     resolvedCtor = GetDummyConstructor(compilation);
                 IMethod m            = new SpecializedMethod(resolvedCtor, TypeParameterSubstitution.Identity)
                 {
                     DeclaringType = this
                 };
                 return(new [] { m });
             }
         }
         return(EmptyList <IMethod> .Instance);
     }
     else
     {
         return(GetMembersHelper.GetConstructors(this, filter, options));
     }
 }
예제 #8
0
        /// <summary>
        /// Gets the extension methods that are called 'name'
        /// and are applicable with a first argument type of 'targetType'.
        /// </summary>
        /// <param name="targetType">Type of the 'this' argument</param>
        /// <param name="name">Name of the extension method</param>
        /// <param name="typeArguments">Explicitly provided type arguments.
        /// An empty list will return all matching extension method definitions;
        /// a non-empty list will return <see cref="SpecializedMethod"/>s for all extension methods
        /// with the matching number of type parameters.</param>
        /// <remarks>
        /// The results are stored in nested lists because they are grouped by using scope.
        /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }",
        /// the return value will be
        /// new List {
        ///    new List { all extensions from MoreExtensions },
        ///    new List { all extensions from SomeExtensions }
        /// }
        /// </remarks>
        public List<List<IMethod>> GetExtensionMethods(IType targetType, string name, IList<IType> typeArguments = null)
        {
            List<List<IMethod>> extensionMethodGroups = new List<List<IMethod>>();
            foreach (var inputGroup in GetAllExtensionMethods()) {
                List<IMethod> outputGroup = new List<IMethod>();
                foreach (var method in inputGroup) {
                    if (method.Name != name)
                        continue;

                    if (typeArguments != null && typeArguments.Count > 0) {
                        if (method.TypeParameters.Count != typeArguments.Count)
                            continue;
                        SpecializedMethod sm = new SpecializedMethod(method.DeclaringType, method, typeArguments);
                        // TODO: verify targetType
                        outputGroup.Add(sm);
                    } else {
                        // TODO: verify targetType
                        outputGroup.Add(method);
                    }
                }
                if (outputGroup.Count > 0)
                    extensionMethodGroups.Add(outputGroup);
            }
            return extensionMethodGroups;
        }
예제 #9
0
		public void GetIndexDoubleSpecialization()
		{
			var testClass = GetTypeDefinition(typeof(GenericClass<,>));
			// GenericClass<A, B>.GetIndex<T>
			var methodDef = testClass.Methods.Single(me => me.Name == "GetIndex");
			
			// GenericClass<B, A>.GetIndex<A>
			var m1 = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
				new[] { testClass.TypeParameters[1], testClass.TypeParameters[0] },
				new[] { testClass.TypeParameters[0] }
			));
			// GenericClass<string, int>.GetIndex<int>
			var m2 = new SpecializedMethod(m1, new TypeParameterSubstitution(
				new[] { compilation.FindType(KnownTypeCode.Int32), compilation.FindType(KnownTypeCode.String) },
				null
			));
			
			// GenericClass<string, int>.GetIndex<int>
			var m12 = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
				new[] { compilation.FindType(KnownTypeCode.String), compilation.FindType(KnownTypeCode.Int32) },
				new[] { compilation.FindType(KnownTypeCode.Int32) }
			));
			Assert.AreEqual(m12, m2);
		}
예제 #10
0
		public void GetIndexSpecializedTypeParameter()
		{
			var testClass = GetTypeDefinition(typeof(GenericClass<,>));
			var methodDef = testClass.Methods.Single(me => me.Name == "GetIndex");
			var m = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
				new[] { compilation.FindType(KnownTypeCode.Int16), compilation.FindType(KnownTypeCode.Int32) },
				null
			));
			
			Assert.AreEqual("T", m.TypeParameters[0].Name);
			Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType);
			Assert.AreSame(m, m.TypeParameters[0].Owner);
			
			ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First();
			Assert.AreEqual("IEquatable", constraint.Name);
			Assert.AreEqual(1, constraint.TypeParameterCount);
			Assert.AreEqual(1, constraint.TypeArguments.Count);
			Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]);
		}
예제 #11
0
		IMember Specialize(IMember member, Func<ITypeReference, ITypeReference> substitution)
		{
			IMethod method = member as IMethod;
			if (method != null) {
				SpecializedMethod m = new SpecializedMethod(method);
				m.SetDeclaringType(this);
				m.SubstituteTypes(substitution);
				return m;
			}
			IProperty property = member as IProperty;
			if (property != null) {
				SpecializedProperty p = new SpecializedProperty(property);
				p.SetDeclaringType(this);
				p.SubstituteTypes(substitution);
				return p;
			}
			IField field = member as IField;
			if (field != null) {
				SpecializedField f = new SpecializedField(field);
				f.SetDeclaringType(this);
				f.ReturnType = substitution(f.ReturnType);
				return f;
			}
			IEvent ev = member as IEvent;
			if (ev != null) {
				SpecializedEvent e = new SpecializedEvent(ev);
				e.SetDeclaringType(this);
				e.ReturnType = substitution(e.ReturnType);
				return e;
			}
			throw new ArgumentException("Unknown member");
		}
예제 #12
0
		/// <summary>
		/// Gets the extension methods that are called 'name'
		/// and are applicable with a first argument type of 'targetType'.
		/// </summary>
		/// <param name="targetType">Type of the 'this' argument</param>
		/// <param name="name">Name of the extension method. Pass null to retrieve all extension methods.</param>
		/// <param name="typeArguments">Explicitly provided type arguments.
		/// An empty list will return all matching extension method definitions;
		/// a non-empty list will return <see cref="SpecializedMethod"/>s for all extension methods
		/// with the matching number of type parameters.</param>
		/// <param name="substituteInferredTypes">
		/// Specifies whether to produce a <see cref="SpecializedMethod"/>
		/// when type arguments could be inferred from <paramref name="targetType"/>. This parameter
		/// is only used for inferred types and has no effect if <paramref name="typeArguments"/> is non-empty.
		/// </param>
		/// <remarks>
		/// The results are stored in nested lists because they are grouped by using scope.
		/// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }",
		/// the return value will be
		/// new List {
		///    new List { all extensions from MoreExtensions },
		///    new List { all extensions from SomeExtensions }
		/// }
		/// </remarks>
		public List<List<IMethod>> GetExtensionMethods(IType targetType, string name = null, IList<IType> typeArguments = null, bool substituteInferredTypes = false)
		{
			List<List<IMethod>> extensionMethodGroups = new List<List<IMethod>>();
			foreach (var inputGroup in GetAllExtensionMethods()) {
				List<IMethod> outputGroup = new List<IMethod>();
				foreach (var method in inputGroup) {
					if (name != null && method.Name != name)
						continue;
					
					IType[] inferredTypes;
					if (typeArguments != null && typeArguments.Count > 0) {
						if (method.TypeParameters.Count != typeArguments.Count)
							continue;
						SpecializedMethod sm = new SpecializedMethod(method.DeclaringType, method, typeArguments);
						if (IsEligibleExtensionMethod(targetType, method, false, out inferredTypes))
							outputGroup.Add(sm);
					} else {
						if (IsEligibleExtensionMethod(targetType, method, true, out inferredTypes)) {
							if (substituteInferredTypes && inferredTypes != null) {
								outputGroup.Add(new SpecializedMethod(method.DeclaringType, method, inferredTypes));
							} else {
								outputGroup.Add(method);
							}
						}
					}
				}
				if (outputGroup.Count > 0)
					extensionMethodGroups.Add(outputGroup);
			}
			return extensionMethodGroups;
		}
예제 #13
0
		public static IMethod CreateTypeCheckMethod(IType type, ICompilation compilation) {
			IMethod method = new DefaultResolvedMethod(new DefaultUnresolvedMethod(type.GetDefinition().Parts[0], "IsInstanceOfType"), compilation.TypeResolveContext.WithCurrentTypeDefinition(type.GetDefinition()));
			if (type is ParameterizedType)
				method = new SpecializedMethod(method, new TypeParameterSubstitution(classTypeArguments: ((ParameterizedType)type).TypeArguments, methodTypeArguments: null));
			return method;
		}
예제 #14
0
		public IEnumerable<IMethod> GetConstructors(ITypeResolveContext context, Predicate<IMethod> filter = null)
		{
			Substitution substitution = new Substitution(typeArguments);
			Func<ITypeReference, ITypeReference> substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution);
			List<IMethod> methods = genericType.GetConstructors(context, filter).ToList();
			for (int i = 0; i < methods.Count; i++) {
				SpecializedMethod m = new SpecializedMethod(methods[i]);
				m.SetDeclaringType(this);
				m.SubstituteTypes(substitutionFunc);
				methods[i] = m;
			}
			return methods;
		}
		public static IMethod CreateDummyMethodForFieldInitialization(IMember member, ICompilation compilation) {
			var unresolved = new DefaultUnresolvedMethod(member.DeclaringTypeDefinition.Parts[0], "initialization for " + member.Name) {
				Parameters = { new DefaultUnresolvedParameter(member.ReturnType.ToTypeReference(), "value") },
				IsStatic = member.IsStatic,
			};
			IMethod method = new DefaultResolvedMethod(unresolved, compilation.TypeResolveContext.WithCurrentTypeDefinition(member.DeclaringTypeDefinition));
			if (member.DeclaringType is ParameterizedType)
				method = new SpecializedMethod(method, new TypeParameterSubstitution(classTypeArguments: ((ParameterizedType)member.DeclaringType).TypeArguments, methodTypeArguments: null));
			return method;
		}
예제 #16
0
		public void Specialized_GetIndex_SpecializeWithIdentityHasNoEffect()
		{
			var genericClass = compilation.FindType(typeof(GenericClass<string, object>));
			IType[] methodTypeArguments = { DummyTypeParameter.GetMethodTypeParameter(0) };
			var method = (SpecializedMethod)genericClass.GetMethods(methodTypeArguments, m => m.Name == "GetIndex").Single();
			// GenericClass<string,object>.GetIndex<!!0>()
			Assert.AreSame(method, method.TypeParameters[0].Owner);
			Assert.AreNotEqual(method.TypeParameters[0], method.TypeArguments[0]);
			Assert.IsNull(((ITypeParameter)method.TypeArguments[0]).Owner);
			// Now apply identity substitution:
			var method2 = new SpecializedMethod(method, TypeParameterSubstitution.Identity);
			Assert.AreSame(method2, method2.TypeParameters[0].Owner);
			Assert.AreNotEqual(method2.TypeParameters[0], method2.TypeArguments[0]);
			Assert.IsNull(((ITypeParameter)method2.TypeArguments[0]).Owner);
			
			Assert.AreEqual(method, method2);
		}
예제 #17
0
		internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition)
		{
			if (accessorDefinition == null)
				return null;
			var result = LazyInit.VolatileRead(ref cachingField);
			if (result != null) {
				return result;
			} else {
				var sm = new SpecializedMethod(accessorDefinition, substitution);
				//sm.AccessorOwner = this;
				return LazyInit.GetOrSet(ref cachingField, sm);
			}
		}
예제 #18
0
 public IEnumerable<IMethod> GetMethods(ITypeResolveContext context, Predicate<IMethod> filter = null)
 {
     Substitution substitution = new Substitution(typeArguments);
     List<IMethod> methods = genericType.GetMethods(context, filter).ToList();
     for (int i = 0; i < methods.Count; i++) {
         SpecializedMethod m = new SpecializedMethod(methods[i]);
         m.SetDeclaringType(this);
         m.SubstituteTypes(context, substitution);
         methods[i] = m;
     }
     return methods;
 }