public void ImportOpenGenericType() { // class C<T, U> { void M<X>() {} } var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "T")); c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "U")); var m = new DefaultUnresolvedMethod(c, "M"); m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.Method, 0, "X")); c.Members.Add(m); var resolvedC1 = TypeSystemHelper.CreateCompilationAndResolve(c); var resolvedM1 = resolvedC1.Methods.Single(method => method.Name == "M"); var resolvedC2 = TypeSystemHelper.CreateCompilationAndResolve(c); var resolvedM2 = resolvedC2.Methods.Single(method => method.Name == "M"); // the types, methods and type parameters differ in the two compilations: Assert.AreNotEqual(resolvedC1, resolvedC2); Assert.AreNotEqual(resolvedM1, resolvedM2); Assert.AreNotEqual(resolvedC1.TypeParameters[1], resolvedC2.TypeParameters[1]); Assert.AreNotEqual(resolvedM1.TypeParameters[0], resolvedM2.TypeParameters[0]); // C<U, X> var pt1 = new ParameterizedType(resolvedC1, new[] { resolvedC1.TypeParameters[1], resolvedM1.TypeParameters[0] }); var pt2 = (ParameterizedType)resolvedC2.Compilation.Import(pt1); // importing resulted in C<U, X> in the new compilation: Assert.AreEqual(resolvedC2, pt2.GetDefinition()); Assert.AreEqual(resolvedC2.TypeParameters[1], pt2.TypeArguments[0]); Assert.AreEqual(resolvedM2.TypeParameters[0], pt2.TypeArguments[1]); }
/// <summary> /// Finds IList<T> or IEnumerable<T> base type. /// </summary> /// <param name="fullNamePrefix">Type code to search for (IList<T> or IEnumerable<T>)</param></param> /// <param name="implementation">Found implementation.</param> /// <param name="itemType">The only generic argument of <paramref name="implementation"/></param> /// <returns>True if found, false otherwise.</returns> private static bool ResolveKnownBaseType(this IType type, KnownTypeCode knownTypeCode, out ParameterizedType implementation, out IType itemType) { if (type == null) throw new ArgumentNullException("type"); implementation = null; itemType = null; ParameterizedType impl = type.GetAllBaseTypes().OfType<ParameterizedType>(). Where(t => t.IsKnownType(knownTypeCode) && t.TypeParameterCount == 1) .FirstOrDefault(); if (impl != null) { implementation = impl; itemType = impl.GetTypeArgument(0); return true; } return false; }
public IEnumerable <IType> GetNestedTypes(ITypeResolveContext context, Predicate <ITypeDefinition> filter = null) { /* * class Base<T> { * class Nested {} * } * class Derived<A, B> : Base<B> {} * * Derived<string,int>.GetNestedTypes() = { Base`1+Nested<int> } * Derived.GetNestedTypes() = { Base`1+Nested<B> } * Base<B>.GetNestedTypes() = { Base`1+Nested<B> } * Base.GetNestedTypes() = { Base`1+Nested<T2> } where T2 = copy of T in Base`1+Nested */ Substitution substitution = new Substitution(typeArguments); List <IType> types = genericType.GetNestedTypes(context, filter).ToList(); for (int i = 0; i < types.Count; i++) { ITypeDefinition def = types[i] as ITypeDefinition; if (def != null && def.TypeParameterCount > 0) { // (partially) parameterize the nested type definition IType[] newTypeArgs = new IType[def.TypeParameterCount]; for (int j = 0; j < newTypeArgs.Length; j++) { if (j < typeArguments.Length) { newTypeArgs[j] = typeArguments[i]; } else { newTypeArgs[j] = def.TypeParameters[j]; } } types[i] = new ParameterizedType(def, newTypeArgs); } else { types[i] = types[i].AcceptVisitor(substitution); } } return(types); }
public void EnumerableToArrayInContravariantType() { ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); IType stringType = KnownTypeReference.String.Resolve(ctx); ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>)); ITypeDefinition comparerType = ctx.GetTypeDefinition(typeof(IComparer<>)); var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType} ) }); var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(tp) }); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(comparerOfIEnumerableOfString) }, new [] { comparerOfTpArray }, out success)); Assert.IsTrue(success); }
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]); }
public void GetGenericNestedTypeOfBoundGenericClass() { // class A<X> { class B<Y> { } } DefaultTypeDefinition a = new DefaultTypeDefinition(mscorlib, string.Empty, "A"); a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X")); DefaultTypeDefinition b = new DefaultTypeDefinition(a, "B"); b.TypeParameters.Add(a.TypeParameters[0]); b.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 1, "Y")); a.NestedTypes.Add(b); // A<> gets self-parameterized, B<> stays unbound Assert.AreEqual("A`1+B`1[[`0],[]]", a.GetNestedTypes(mscorlib).Single().ReflectionName); ParameterizedType pt = new ParameterizedType(a, new [] { KnownTypeReference.String.Resolve(mscorlib) }); Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes(mscorlib).Single().ReflectionName); }
public void AssemblyAttribute() { var attributes = testCasePC.AssemblyAttributes; var typeTest = attributes.First(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName); Assert.AreEqual(3, typeTest.PositionalArguments.Count); // first argument is (int)42 Assert.AreEqual(42, (int)typeTest.PositionalArguments[0].GetValue(ctx)); // second argument is typeof(System.Action<>) IType rt = (IType)typeTest.PositionalArguments[1].GetValue(ctx); Assert.IsFalse(rt is ParameterizedType); // rt must not be constructed - it's just an unbound type Assert.AreEqual("System.Action", rt.FullName); Assert.AreEqual(1, rt.TypeParameterCount); // third argument is typeof(IDictionary<string, IList<TestAttribute>>) ParameterizedType crt = (ParameterizedType)typeTest.PositionalArguments[2].GetValue(ctx); Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); // ? for NUnit.TestAttribute (because that assembly isn't in ctx) Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName); }
public void GetGenericNestedTypeOfBoundGenericClass() { // class A<X> { class B<Y> { } } DefaultUnresolvedTypeDefinition a = new DefaultUnresolvedTypeDefinition(string.Empty, "A"); a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 0, "X")); DefaultUnresolvedTypeDefinition b = new DefaultUnresolvedTypeDefinition(a, "B"); b.TypeParameters.Add(a.TypeParameters[0]); b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 1, "Y")); a.NestedTypes.Add(b); var compilation = TypeSystemHelper.CreateCompilation(a, b); ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName); ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName); // A<> gets self-parameterized, B<> stays unbound Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName); ParameterizedType pt = new ParameterizedType(resolvedA, new [] { compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes().Single().ReflectionName); }
public void AssemblyAttribute() { var attributes = compilation.MainAssembly.AssemblyAttributes; var typeTest = attributes.Single(a => a.AttributeType.FullName == typeof(TypeTestAttribute).FullName); Assert.AreEqual(3, typeTest.PositionalArguments.Count); // first argument is (int)42 Assert.AreEqual(42, (int)typeTest.PositionalArguments[0].ConstantValue); // second argument is typeof(System.Action<>) TypeOfResolveResult rt = (TypeOfResolveResult)typeTest.PositionalArguments[1]; Assert.IsFalse(rt.ReferencedType is ParameterizedType); // rt must not be constructed - it's just an unbound type Assert.AreEqual("System.Action", rt.ReferencedType.FullName); Assert.AreEqual(1, rt.ReferencedType.TypeParameterCount); // third argument is typeof(IDictionary<string, IList<TestAttribute>>) rt = (TypeOfResolveResult)typeTest.PositionalArguments[2]; ParameterizedType crt = (ParameterizedType)rt.ReferencedType; Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); // ? for NUnit.TestAttribute (because that assembly isn't in ctx) Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName); }
public void GetGenericNestedTypeOfBoundGenericClass() { // class A<X> { class B<Y> { } } DefaultUnresolvedTypeDefinition a = new DefaultUnresolvedTypeDefinition(string.Empty, "A"); a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "X")); DefaultUnresolvedTypeDefinition b = new DefaultUnresolvedTypeDefinition(a, "B"); b.TypeParameters.Add(a.TypeParameters[0]); b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "Y")); a.NestedTypes.Add(b); ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a); ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b); // A<> gets self-parameterized, B<> stays unbound Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName); ParameterizedType pt = new ParameterizedType(resolvedA, new [] { compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes().Single().ReflectionName); }
IList<IType> FindTypesInBounds(IList<IType> lowerBounds, IList<IType> upperBounds) { // If there's only a single type; return that single type. // If both inputs are empty, return the empty list. if (lowerBounds.Count == 0 && upperBounds.Count <= 1) return upperBounds; if (upperBounds.Count == 0 && lowerBounds.Count <= 1) return lowerBounds; if (nestingLevel > maxNestingLevel) return EmptyList<IType>.Instance; // Finds a type X so that "LB <: X <: UB" Log.WriteCollection("FindTypesInBound, LowerBounds=", lowerBounds); Log.WriteCollection("FindTypesInBound, UpperBounds=", upperBounds); // First try the Fixing algorithm from the C# spec (§7.5.2.11) List<IType> candidateTypes = lowerBounds.Union(upperBounds) .Where(c => lowerBounds.All(b => conversions.ImplicitConversion(b, c).IsValid)) .Where(c => upperBounds.All(b => conversions.ImplicitConversion(c, b).IsValid)) .ToList(); // evaluate the query only once Log.WriteCollection("FindTypesInBound, Candidates=", candidateTypes); // According to the C# specification, we need to pick the most specific // of the candidate types. (the type which has conversions to all others) // However, csc actually seems to choose the least specific. candidateTypes = candidateTypes.Where( c => candidateTypes.All(o => conversions.ImplicitConversion(o, c).IsValid) ).ToList(); // If the specified algorithm produces a single candidate, we return // that candidate. // We also return the whole candidate list if we're not using the improved // algorithm. if (candidateTypes.Count == 1 || !(algorithm == TypeInferenceAlgorithm.Improved || algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults)) { return candidateTypes; } candidateTypes.Clear(); // Now try the improved algorithm Log.Indent(); List<ITypeDefinition> candidateTypeDefinitions; if (lowerBounds.Count > 0) { // Find candidates by using the lower bounds: var hashSet = new HashSet<ITypeDefinition>(lowerBounds[0].GetAllBaseTypeDefinitions()); for (int i = 1; i < lowerBounds.Count; i++) { hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions()); } candidateTypeDefinitions = hashSet.ToList(); } else { // Find candidates by looking at all classes in the project: candidateTypeDefinitions = compilation.GetAllTypeDefinitions().ToList(); } // Now filter out candidates that violate the upper bounds: foreach (IType ub in upperBounds) { ITypeDefinition ubDef = ub.GetDefinition(); if (ubDef != null) { candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef)); } } foreach (ITypeDefinition candidateDef in candidateTypeDefinitions) { // determine the type parameters for the candidate: IType candidate; if (candidateDef.TypeParameterCount == 0) { candidate = candidateDef; } else { Log.WriteLine("Inferring arguments for candidate type definition: " + candidateDef); bool success; IType[] result = InferTypeArgumentsFromBounds( candidateDef.TypeParameters, new ParameterizedType(candidateDef, candidateDef.TypeParameters), lowerBounds, upperBounds, out success); if (success) { candidate = new ParameterizedType(candidateDef, result); } else { Log.WriteLine("Inference failed; ignoring candidate"); continue; } } Log.WriteLine("Candidate type: " + candidate); if (upperBounds.Count == 0) { // if there were only lower bounds, we aim for the most specific candidate: // if this candidate isn't made redundant by an existing, more specific candidate: if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef))) { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition())); // add new candidate candidateTypes.Add(candidate); } } else { // if there were upper bounds, we aim for the least specific candidate: // if this candidate isn't made redundant by an existing, less specific candidate: if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition()))) { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef)); // add new candidate candidateTypes.Add(candidate); } } } Log.Unindent(); return candidateTypes; }
ResolveResult LookInCurrentUsingScope(string identifier, IList<IType> typeArguments, bool isInUsingDeclaration, bool parameterizeResultType) { // look in current namespace definitions ResolvedUsingScope currentUsingScope = this.CurrentUsingScope; for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent) { var resultInNamespace = LookInUsingScopeNamespace(u, u.Namespace, identifier, typeArguments, parameterizeResultType); if (resultInNamespace != null) return resultInNamespace; // then look for aliases: if (typeArguments.Count == 0) { if (u.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } if (!(isInUsingDeclaration && u == currentUsingScope)) { foreach (var pair in u.UsingAliases) { if (pair.Key == identifier) { return pair.Value; } } } } // finally, look in the imported namespaces: if (!(isInUsingDeclaration && u == currentUsingScope)) { IType firstResult = null; foreach (var importedNamespace in u.Usings) { ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, typeArguments.Count); if (def != null) { IType resultType; if (parameterizeResultType && typeArguments.Count > 0) resultType = new ParameterizedType(def, typeArguments); else resultType = def; if (firstResult == null || !TopLevelTypeDefinitionIsAccessible(firstResult.GetDefinition())) { firstResult = resultType; } else if (TopLevelTypeDefinitionIsAccessible(def)) { return new AmbiguousTypeResolveResult(firstResult); } } } if (firstResult != null) return new TypeResolveResult(firstResult); } // if we didn't find anything: repeat lookup with parent namespace } return null; }
public void NestedTypeInDerivedClass() { var type1 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) }); // short form "Nested<string>" cannot be used as it would refer to "Base<S>.Nested<string>" Assert.AreEqual("Base<T>.Nested<string>", TypeToString(type1, derivedClass)); var type2 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[1], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Nested<string>", TypeToString(type2, derivedClass)); }
static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) return false; switch (rt.GetDefinition().FullName) { case "System.Collections.Generic.IEnumerable": case "System.Collections.Generic.ICollection": case "System.Collections.Generic.IList": case "System.Collections.Generic.IReadOnlyList": return true; default: return false; } }
ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList<IType> typeArguments) { if (typeArguments.Count > 0) { // parameterize the type if necessary ITypeDefinition returnedTypeDef = returnedType as ITypeDefinition; if (returnedTypeDef != null) returnedType = new ParameterizedType(returnedTypeDef, typeArguments); } if (isAmbiguous) return new AmbiguousTypeResolveResult(returnedType); else return new TypeResolveResult(returnedType); }
public void IEnumerableCovarianceWithDynamic() { ITypeParameter tp = new DefaultTypeParameter(compilation, SymbolKind.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); }
ResolveResult LookInCurrentUsingScope(string identifier, IList<IType> typeArguments, bool isInUsingDeclaration, bool parameterizeResultType) { int k = typeArguments.Count; // look in current namespace definitions ResolvedUsingScope currentUsingScope = this.CurrentUsingScope; for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent) { INamespace n = u.Namespace; // first look for a namespace if (k == 0 && n != null) { INamespace childNamespace = n.GetChildNamespace(identifier); if (childNamespace != null) { if (u.HasAlias(identifier)) return new AmbiguousTypeResolveResult(new UnknownType(null, identifier)); return new NamespaceResolveResult(childNamespace); } } // then look for a type if (n != null) { ITypeDefinition def = n.GetTypeDefinition(identifier, k); if (def != null) { IType result = def; if (parameterizeResultType) { result = new ParameterizedType(def, typeArguments); } if (u.HasAlias(identifier)) return new AmbiguousTypeResolveResult(result); else return new TypeResolveResult(result); } } // then look for aliases: if (k == 0) { if (u.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } if (!(isInUsingDeclaration && u == currentUsingScope)) { foreach (var pair in u.UsingAliases) { if (pair.Key == identifier) { return pair.Value; } } } } // finally, look in the imported namespaces: if (!(isInUsingDeclaration && u == currentUsingScope)) { IType firstResult = null; foreach (var importedNamespace in u.Usings) { ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, k); if (def != null) { if (firstResult == null) { if (parameterizeResultType && k > 0) firstResult = new ParameterizedType(def, typeArguments); else firstResult = def; } else { return new AmbiguousTypeResolveResult(firstResult); } } } if (firstResult != null) return new TypeResolveResult(firstResult); } // if we didn't find anything: repeat lookup with parent namespace } return null; }
public virtual IType VisitParameterizedType(ParameterizedType type) { return type.VisitChildren(this); }
public void NestedType() { var type = new ParameterizedType(nestedClass, new[] { compilation.FindType(KnownTypeCode.Char), compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type)); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, baseClass)); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, nestedClass)); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, derivedClass)); }
public void AliasedTypeWrongTypeArgument() { var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { compilation.FindType(KnownTypeCode.Int32) }); Assert.AreEqual("List<int>", TypeToString(type, systemClass)); }
public void NestedType() { var type = new ParameterizedType(nestedClass, new[] { compilation.FindType(KnownTypeCode.Char), compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type)); // The short form "Nested<string>" refers to "Base<T>.Nested<string>", // so we need to use the long form to specify that T=char. Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, baseClass)); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, nestedClass)); Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, derivedClass)); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.TypeArguments[i]; if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType != true) ConstraintsValid = false; } if (tp.HasValueTypeConstraint) { if (typeArg.IsReferenceType != false) ConstraintsValid = false; if (NullableType.IsNullable(typeArg)) ConstraintsValid = false; } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) ConstraintsValid = false; ConstraintsValid &= typeArg.GetConstructors( overloadResolution.context, m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c); } } } } return newType; }
public virtual IType VisitParameterizedType(ParameterizedType type) { return(type.VisitChildren(this)); }
ResolveResult LookInUsingScopeNamespace(ResolvedUsingScope usingScope, INamespace n, string identifier, IList<IType> typeArguments, bool parameterizeResultType) { if (n == null) return null; // first look for a namespace int k = typeArguments.Count; if (k == 0) { INamespace childNamespace = n.GetChildNamespace(identifier); if (childNamespace != null) { if (usingScope != null && usingScope.HasAlias(identifier)) return new AmbiguousTypeResolveResult(new UnknownType(null, identifier)); return new NamespaceResolveResult(childNamespace); } } // then look for a type ITypeDefinition def = n.GetTypeDefinition(identifier, k); if (def != null) { IType result = def; if (parameterizeResultType && k > 0) { result = new ParameterizedType(def, typeArguments); } if (usingScope != null && usingScope.HasAlias(identifier)) return new AmbiguousTypeResolveResult(result); else return new TypeResolveResult(result); } return null; }
static bool IsIEnumerableCollectionOrList(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) return false; switch (rt.GetDefinition().FullName) { case "System.Collections.Generic.IList": case "System.Collections.Generic.ICollection": case "System.Collections.Generic.IEnumerable": return true; default: return false; } }
public void ExpansiveInheritance() { var a = new DefaultUnresolvedTypeDefinition(string.Empty, "A"); var b = new DefaultUnresolvedTypeDefinition(string.Empty, "B"); // interface A<in U> a.Kind = TypeKind.Interface; a.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); // interface B<X> : A<A<B<X>>> { } b.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "X")); b.BaseTypes.Add(new ParameterizedTypeReference( a, new[] { new ParameterizedTypeReference( a, new [] { new ParameterizedTypeReference( b, new [] { new TypeParameterReference(EntityType.TypeDefinition, 0) } ) } ) })); ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b); ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName); ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName); IType type1 = new ParameterizedType(resolvedB, new [] { compilation.FindType(KnownTypeCode.Double) }); IType type2 = new ParameterizedType(resolvedA, new [] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) }); Assert.IsFalse(conversions.ImplicitConversion(type1, type2).IsValid); }
public void ListOfNSSystem() { var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { systemClass }); Assert.AreEqual("List<NS.System>", TypeToString(type)); Assert.AreEqual("List<System>", TypeToString(type, systemClass)); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; var substitution = newParameterizedType.GetSubstitution(); for (int i = 0; i < typeParameters.Count; i++) { if (!ValidateConstraints(typeParameters[i], newParameterizedType.GetTypeArgument(i), substitution, conversions)) { ConstraintsValid = false; break; } } } } return newType; }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.GetTypeArgument(i); switch (typeArg.Kind) { // void, null, and pointers cannot be used as type arguments case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: ConstraintsValid = false; break; } if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType != true) ConstraintsValid = false; } if (tp.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArg)) ConstraintsValid = false; } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) ConstraintsValid = false; ConstraintsValid &= typeArg.GetConstructors( m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.DirectBaseTypes) { IType c = constraintType.AcceptVisitor(newParameterizedType.GetSubstitution()); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } } return newType; }
public void NestedClassInGenericClassTest() { ITypeDefinition dictionary = compilation.FindType(typeof(Dictionary<,>)).GetDefinition(); Assert.IsNotNull(dictionary); ITypeDefinition valueCollection = compilation.FindType(typeof(Dictionary<,>.ValueCollection)).GetDefinition(); Assert.IsNotNull(valueCollection); var dictionaryRT = new ParameterizedType(dictionary, new[] { compilation.FindType(typeof(string)).GetDefinition(), compilation.FindType(typeof(int)).GetDefinition() }); IProperty valueProperty = dictionaryRT.GetProperties(p => p.Name == "Values").Single(); IType parameterizedValueCollection = valueProperty.ReturnType; Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]", parameterizedValueCollection.ReflectionName); Assert.AreSame(valueCollection, parameterizedValueCollection.GetDefinition()); }
public override IType VisitParameterizedType(ParameterizedType type) { return NullableType.Create(compilation, type.AcceptVisitor(typeParameterSubstitution)); }
public void NestedTypeInCurrentClass() { var type = new ParameterizedType(nestedClass, new[] { baseClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Nested<string>", TypeToString(type, baseClass)); Assert.AreEqual("Nested<string>", TypeToString(type, nestedClass)); }
public void SiblingClass() { var type = new ParameterizedType(siblingClass, new[] { baseClass.TypeParameters[0] }); Assert.AreEqual("Sibling", TypeToString(type, nestedClass)); }
/// <summary> Evaluates 'new List<T>(iEnumerableValue)' in the debuggee. </summary> public static Value CreateListFromIEnumerable(ParameterizedType ienumerableType, Value iEnumerableValue) { var ilistDef = ienumerableType.Compilation.FindType(typeof(List<>)).GetDefinition(); var ilistType = new ParameterizedType(ilistDef, ienumerableType.TypeArguments); var ctors = ilistType.GetConstructors(m => m.Parameters.Count == 1); var ctor = ctors.Single(m => m.Parameters[0].Type.IsKnownType(KnownTypeCode.IEnumerableOfT)); return Eval.NewObject(WindowsDebugger.EvalThread, ctor, new Value[] { iEnumerableValue }); }
public void NestedTypeInDerivedClass() { var type1 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Base<T>.Nested<string>", TypeToString(type1, derivedClass)); var type2 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[1], compilation.FindType(KnownTypeCode.String) }); Assert.AreEqual("Nested<string>", TypeToString(type2, derivedClass)); }
public override IType VisitParameterizedType(ParameterizedType type) { return NullableType.Create(compilation, type); }
public void AliasedType() { var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { compilation.FindType(KnownTypeCode.Char) }); Assert.AreEqual("List<char>", TypeToString(type)); Assert.AreEqual("L", TypeToString(type, systemClass)); }