void ConvertConstraints(NRefactoryAST.TemplateDefinition template, DefaultTypeParameter typeParameter)
 {
     foreach (NRefactoryAST.TypeReference typeRef in template.Bases)
     {
         if (typeRef == NRefactoryAST.TypeReference.NewConstraint)
         {
             typeParameter.HasConstructableConstraint = true;
         }
         else if (typeRef == NRefactoryAST.TypeReference.ClassConstraint)
         {
             typeParameter.HasReferenceTypeConstraint = true;
         }
         else if (typeRef == NRefactoryAST.TypeReference.StructConstraint)
         {
             typeParameter.HasValueTypeConstraint = true;
         }
         else
         {
             IReturnType rt = CreateReturnType(typeRef, typeParameter.Method, TypeVisitor.ReturnTypeOptions.None);
             if (rt != null)
             {
                 typeParameter.Constraints.Add(rt);
             }
         }
     }
 }
예제 #2
0
 DefaultTypeParameter ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter)
 {
     foreach (AST.TypeReference typeRef in template.Bases)
     {
         if (typeRef == AST.TypeReference.NewConstraint)
         {
             typeParameter.HasConstructableConstraint = true;
         }
         else if (typeRef == AST.TypeReference.ClassConstraint)
         {
             typeParameter.HasReferenceTypeConstraint = true;
         }
         else if (typeRef == AST.TypeReference.StructConstraint)
         {
             typeParameter.HasValueTypeConstraint = true;
         }
         else
         {
             IReturnType rt = CreateReturnType(typeRef);
             if (rt != null)
             {
                 typeParameter.Constraints.Add(rt);
             }
         }
     }
     return(typeParameter);
 }
예제 #3
0
        public void TypeParameterWithValueTypeConstraint()
        {
            ITypeParameter t = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T", hasValueTypeConstraint: true);

            Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t));
            Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)));
            Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic));
            Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))));
        }
예제 #4
0
        public void TypeParameterWithValueTypeConstraint()
        {
            DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");

            t.HasValueTypeConstraint = true;

            Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t));
            Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
            Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
            Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
        }
예제 #5
0
        public void TypeParameterWithReferenceTypeConstraint()
        {
            DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");

            t.HasReferenceTypeConstraint = true;

            Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SharedTypes.Null, t));
            Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
            Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
        }
예제 #6
0
        public void TypeParameterWithClassConstraint()
        {
            DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");

            t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer)));

            Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t));
            Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
            Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
            Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
            Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer))));
            Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer))));
            Assert.IsFalse(conversions.ImplicitConversion(t, typeof(IComparer <int>).ToTypeReference().Resolve(ctx)));
            Assert.IsTrue(conversions.ImplicitConversion(t, typeof(IComparer <string>).ToTypeReference().Resolve(ctx)));
        }
예제 #7
0
        public void InferFromObjectAndFromNullLiteral()
        {
            // M<T>(T a, T b);
            ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");

            // M(new object(), null);
            bool success;

            Assert.AreEqual(
                new [] { compilation.FindType(KnownTypeCode.Object) },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(compilation.FindType(KnownTypeCode.Object)), new ResolveResult(SpecialType.NullType) },
                                      new [] { tp, tp },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #8
0
        public void ArrayToEnumerable()
        {
            ITypeParameter  tp             = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            IType           stringType     = compilation.FindType(KnownTypeCode.String);
            ITypeDefinition enumerableType = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition();

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(new ArrayType(compilation, stringType)) },
                                      new [] { new ParameterizedType(enumerableType, new [] { tp }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #9
0
        public void ArrayToEnumerable()
        {
            ITypeParameter  tp             = new DefaultTypeParameter(EntityType.Method, 0, "T");
            IType           stringType     = KnownTypeReference.String.Resolve(ctx);
            ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable <>));

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(new ArrayType(stringType)) },
                                      new [] { new ParameterizedType(enumerableType, new [] { tp }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #10
0
        public void UnconstrainedTypeParameter()
        {
            ITypeParameter t  = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T");
            ITypeParameter t2 = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 1, "T2");
            ITypeParameter tm = new DefaultTypeParameter(compilation, EntityType.Method, 0, "TM");

            Assert.AreEqual(C.None, conversions.ImplicitConversion(SpecialType.NullType, t));
            Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)));
            Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SpecialType.Dynamic));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))));

            Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(t, t));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t2, t));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, t2));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, tm));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(tm, t));
        }
예제 #11
0
        public void TypeParameterWithInterfaceConstraint()
        {
            DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");

            t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList)));

            Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t));
            Assert.AreEqual(C.BoxingConversion,
                            conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
            Assert.AreEqual(C.BoxingConversion,
                            conversions.ImplicitConversion(t, SharedTypes.Dynamic));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));
            Assert.AreEqual(C.BoxingConversion,
                            conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList))));
            Assert.AreEqual(C.BoxingConversion,
                            conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable))));
        }
예제 #12
0
        public void UnconstrainedTypeParameter()
        {
            DefaultTypeParameter t  = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T");
            DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2");
            DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM");

            Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t));
            Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx)));
            Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic));
            Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType))));

            Assert.IsTrue(conversions.ImplicitConversion(t, t));
            Assert.IsFalse(conversions.ImplicitConversion(t2, t));
            Assert.IsFalse(conversions.ImplicitConversion(t, t2));
            Assert.IsFalse(conversions.ImplicitConversion(t, tm));
            Assert.IsFalse(conversions.ImplicitConversion(tm, t));
        }
예제 #13
0
        public void CannotInferFromMethodParameterTypes()
        {
            // static void M<A, B>(Func<A, B> f) {}
            // M(int.Parse); // type inference fails
            var A = new DefaultTypeParameter(compilation, EntityType.Method, 0, "A");
            var B = new DefaultTypeParameter(compilation, EntityType.Method, 1, "B");

            IType declType = compilation.FindType(typeof(int));
            var   methods  = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "Parse"));
            var   argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", new[] { methods }, new IType[0]);

            bool success;

            ti.InferTypeArguments(new [] { A, B }, new [] { argument },
                                  new [] { new ParameterizedType(compilation.FindType(typeof(Func <,>)).GetDefinition(), new[] { A, B }) },
                                  out success);
            Assert.IsFalse(success);
        }
예제 #14
0
        public void EnumerableToArrayInContravariantType()
        {
            ITypeParameter  tp             = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            IType           stringType     = compilation.FindType(KnownTypeCode.String);
            ITypeDefinition enumerableType = compilation.FindType(typeof(IEnumerable <>)).GetDefinition();
            ITypeDefinition comparerType   = compilation.FindType(typeof(IComparer <>)).GetDefinition();

            var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType }) });
            var comparerOfTpArray             = new ParameterizedType(comparerType, new [] { new ArrayType(compilation, tp) });

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(comparerOfIEnumerableOfString) },
                                      new [] { comparerOfTpArray },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #15
0
        public void TypeParameterWithClassConstraint()
        {
            ITypeParameter t = new DefaultTypeParameter(compilation, EntityType.TypeDefinition, 0, "T",
                                                        constraints: new[] { compilation.FindType(typeof(StringComparer)) });

            Assert.AreEqual(C.NullLiteralConversion,
                            conversions.ImplicitConversion(SpecialType.NullType, t));
            Assert.AreEqual(C.ImplicitReferenceConversion,
                            conversions.ImplicitConversion(t, compilation.FindType(KnownTypeCode.Object)));
            Assert.AreEqual(C.ImplicitReferenceConversion,
                            conversions.ImplicitConversion(t, SpecialType.Dynamic));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(ValueType))));
            Assert.AreEqual(C.ImplicitReferenceConversion,
                            conversions.ImplicitConversion(t, compilation.FindType(typeof(StringComparer))));
            Assert.AreEqual(C.ImplicitReferenceConversion,
                            conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer))));
            Assert.AreEqual(C.None, conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer <int>))));
            Assert.AreEqual(C.ImplicitReferenceConversion,
                            conversions.ImplicitConversion(t, compilation.FindType(typeof(IComparer <string>))));
        }
예제 #16
0
        public void InferFromMethodReturnType()
        {
            // static void M<T>(Func<T> f) {}
            // M(Console.ReadKey); // type inference produces ConsoleKeyInfo

            var T = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");

            IType declType = compilation.FindType(typeof(Console));
            var   methods  = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "ReadKey"));
            var   argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", new[] { methods }, new IType[0]);

            bool success;

            Assert.AreEqual(
                new [] { compilation.FindType(typeof(ConsoleKeyInfo)) },
                ti.InferTypeArguments(new [] { T }, new [] { argument },
                                      new [] { new ParameterizedType(compilation.FindType(typeof(Func <>)).GetDefinition(), new[] { T }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #17
0
        public void ArrayToReadOnlyList()
        {
            ITypeParameter  tp               = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            IType           stringType       = compilation.FindType(KnownTypeCode.String);
            ITypeDefinition readOnlyListType = compilation.FindType(KnownTypeCode.IReadOnlyListOfT).GetDefinition();

            if (readOnlyListType == null)
            {
                Assert.Ignore(".NET 4.5 IReadOnlyList not available");
            }

            bool success;

            Assert.AreEqual(
                new [] { stringType },
                ti.InferTypeArguments(new [] { tp },
                                      new [] { new ResolveResult(new ArrayType(compilation, stringType)) },
                                      new [] { new ParameterizedType(readOnlyListType, new [] { tp }) },
                                      out success));
            Assert.IsTrue(success);
        }
예제 #18
0
        public void ArrayToListWithArrayCovariance()
        {
            ITypeParameter  tp         = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            IType           objectType = compilation.FindType(KnownTypeCode.Object);
            IType           stringType = compilation.FindType(KnownTypeCode.String);
            ITypeDefinition listType   = compilation.FindType(KnownTypeCode.IListOfT).GetDefinition();

            // void M<T>(IList<T> a, T b);
            // M(new string[0], new object());

            bool success;

            Assert.AreEqual(
                new [] { objectType },
                ti.InferTypeArguments(
                    new [] { tp },
                    new [] { new ResolveResult(new ArrayType(compilation, stringType)), new ResolveResult(objectType) },
                    new [] { new ParameterizedType(listType, new [] { tp }), (IType)tp },
                    out success));
            Assert.IsTrue(success);
        }
예제 #19
0
        public ITypeParameter Register(GenericParameter parameter, IEntity owner, int index)
        {
            if (store.TryGetValue(parameter.Id, out var existingP))
            {
                if (!existingP.Owner.Equals(owner))
                {
                    throw new Exception($"There is collision in the usage of generic parameter {parameter}: both {existingP.Owner} and {owner} use it.");
                }
                if (existingP.Index != index)
                {
                    throw new Exception($"There is collision in the usage of generic parameter {parameter} on {existingP.Owner}. It is used at index {existingP.Index} and {index}.");
                }
                return(existingP);
            }

            var newP = new DefaultTypeParameter(owner, index, name: NameSanitizer.SanitizeCsharpName(parameter.Name, lowerCase: null));

            SymbolLoader.RegisterTypeParameter(newP, parameter);
            store.TryAdd(parameter.Id, newP);
            return(Register(parameter, owner, index));
        }
        void ConvertTemplates(DefaultClass outerClass, IList <AST.TemplateDefinition> templateList, DefaultClass c)
        {
            int outerClassTypeParameterCount = outerClass != null ? outerClass.TypeParameters.Count : 0;

            if (templateList.Count == 0 && outerClassTypeParameterCount == 0)
            {
                c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList;
            }
            else
            {
                Debug.Assert(c.TypeParameters.Count == 0);

                int index = 0;
                if (outerClassTypeParameterCount > 0)
                {
                    foreach (DefaultTypeParameter outerTypeParamter in outerClass.TypeParameters)
                    {
                        DefaultTypeParameter p = new DefaultTypeParameter(c, outerTypeParamter.Name, index++);
                        p.HasConstructableConstraint = outerTypeParamter.HasConstructableConstraint;
                        p.HasReferenceTypeConstraint = outerTypeParamter.HasReferenceTypeConstraint;
                        p.HasValueTypeConstraint     = outerTypeParamter.HasValueTypeConstraint;
                        p.Attributes.AddRange(outerTypeParamter.Attributes);
                        p.Constraints.AddRange(outerTypeParamter.Constraints);
                        c.TypeParameters.Add(p);
                    }
                }

                foreach (AST.TemplateDefinition template in templateList)
                {
                    c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++));
                }
                // converting the constraints requires that the type parameters are already present
                for (int i = 0; i < templateList.Count; i++)
                {
                    ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i + outerClassTypeParameterCount]);
                }
            }
        }
예제 #21
0
        public void ExpansiveInheritance()
        {
            SimpleProjectContent  pc = new SimpleProjectContent();
            DefaultTypeDefinition a  = new DefaultTypeDefinition(pc, string.Empty, "A");
            DefaultTypeDefinition b  = new DefaultTypeDefinition(pc, string.Empty, "B");

            // interface A<in U>
            a.Kind = TypeKind.Interface;
            a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "U")
            {
                Variance = VarianceModifier.Contravariant
            });
            // interface B<X> : A<A<B<X>>> { }
            DefaultTypeParameter x = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X");

            b.TypeParameters.Add(x);
            b.BaseTypes.Add(new ParameterizedType(a, new[] { new ParameterizedType(a, new [] { new ParameterizedType(b, new [] { x }) }) }));

            IType type1 = new ParameterizedType(b, new[] { KnownTypeReference.Double.Resolve(ctx) });
            IType type2 = new ParameterizedType(a, new [] { new ParameterizedType(b, new[] { KnownTypeReference.String.Resolve(ctx) }) });

            Assert.IsFalse(conversions.ImplicitConversion(type1, type2));
        }
예제 #22
0
        public void IEnumerableCovarianceWithDynamic()
        {
            ITypeParameter tp                   = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
            var            ienumerableOfT       = new ParameterizedType(compilation.FindType(typeof(IEnumerable <>)).GetDefinition(), new[] { tp });
            var            ienumerableOfString  = compilation.FindType(typeof(IEnumerable <string>));
            var            ienumerableOfDynamic = compilation.FindType(typeof(IEnumerable <ReflectionHelper.Dynamic>));

            // static T M<T>(IEnumerable<T> x, IEnumerable<T> y) {}
            // M(IEnumerable<dynamic>, IEnumerable<string>); -> should infer T=dynamic, no ambiguity
            // See http://blogs.msdn.com/b/cburrows/archive/2010/04/01/errata-dynamic-conversions-and-overload-resolution.aspx
            // for details.

            bool success;

            Assert.AreEqual(
                new [] { SpecialType.Dynamic },
                ti.InferTypeArguments(
                    new [] { tp },
                    new [] { new ResolveResult(ienumerableOfDynamic), new ResolveResult(ienumerableOfString) },
                    new [] { ienumerableOfT, ienumerableOfT },
                    out success));
            Assert.IsTrue(success);
        }
예제 #23
0
        GenericReturnType CreateT()
        {
            ITypeParameter tp = new DefaultTypeParameter(methodForGenericCalls, "T", 0);

            return(new GenericReturnType(tp));
        }
		void ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter)
		{
			foreach (AST.TypeReference typeRef in template.Bases) {
				if (typeRef == AST.TypeReference.NewConstraint) {
					typeParameter.HasConstructableConstraint = true;
				} else if (typeRef == AST.TypeReference.ClassConstraint) {
					typeParameter.HasReferenceTypeConstraint = true;
				} else if (typeRef == AST.TypeReference.StructConstraint) {
					typeParameter.HasValueTypeConstraint = true;
				} else {
					IReturnType rt = CreateReturnType(typeRef, typeParameter.Method, TypeVisitor.ReturnTypeOptions.None);
					if (rt != null) {
						typeParameter.Constraints.Add(rt);
					}
				}
			}
		}
		void ConvertTemplates(DefaultClass outerClass, IList<AST.TemplateDefinition> templateList, DefaultClass c)
		{
			int outerClassTypeParameterCount = outerClass != null ? outerClass.TypeParameters.Count : 0;
			if (templateList.Count == 0 && outerClassTypeParameterCount == 0) {
				c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList;
			} else {
				Debug.Assert(c.TypeParameters.Count == 0);
				
				int index = 0;
				if (outerClassTypeParameterCount > 0) {
					foreach (DefaultTypeParameter outerTypeParamter in outerClass.TypeParameters) {
						DefaultTypeParameter p = new DefaultTypeParameter(c, outerTypeParamter.Name, index++);
						p.HasConstructableConstraint = outerTypeParamter.HasConstructableConstraint;
						p.HasReferenceTypeConstraint = outerTypeParamter.HasReferenceTypeConstraint;
						p.HasValueTypeConstraint = outerTypeParamter.HasValueTypeConstraint;
						p.Attributes.AddRange(outerTypeParamter.Attributes);
						p.Constraints.AddRange(outerTypeParamter.Constraints);
						c.TypeParameters.Add(p);
					}
				}
				
				foreach (AST.TemplateDefinition template in templateList) {
					c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++));
				}
				// converting the constraints requires that the type parameters are already present
				for (int i = 0; i < templateList.Count; i++) {
					ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i + outerClassTypeParameterCount]);
				}
			}
		}