public void InferFromMethodReturnType() { // static void M<T>(Func<T> f) {} // M(Console.ReadKey); // type inference produces ConsoleKeyInfo var T = new DefaultTypeParameter(compilation, SymbolKind.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); }
public void CannotInferFromMethodParameterTypes() { // static void M<A, B>(Func<A, B> f) {} // M(int.Parse); // type inference fails var A = new DefaultTypeParameter(compilation, SymbolKind.Method, 0, "A"); var B = new DefaultTypeParameter(compilation, SymbolKind.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); }
/// <summary> /// Looks up the indexers on the target type. /// </summary> public IList<MethodListWithDeclaringType> LookupIndexers(IType targetType) { bool allowProtectedAccess = IsProtectedAccessAllowed(targetType); Predicate<IProperty> filter = delegate(IProperty property) { return property.IsIndexer && IsAccessible(property, allowProtectedAccess); }; List<LookupGroup> lookupGroups = new List<LookupGroup>(); foreach (IType type in targetType.GetNonInterfaceBaseTypes(context)) { List<IParameterizedMember> newMethods = null; IMember newNonMethod = null; IEnumerable<IType> typeBaseTypes = null; var members = type.GetProperties(context, filter, GetMemberOptions.IgnoreInheritedMembers); AddMembers(type, members, lookupGroups, true, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newMethods != null || newNonMethod != null) lookupGroups.Add(new LookupGroup(type, null, newMethods, newNonMethod)); } // Remove interface members hidden by class members. if (targetType.Kind == TypeKind.TypeParameter) { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } // Remove all hidden groups lookupGroups.RemoveAll(g => g.MethodsAreHidden || g.Methods.Count == 0); MethodListWithDeclaringType[] methodLists = new MethodListWithDeclaringType[lookupGroups.Count]; for (int i = 0; i < methodLists.Length; i++) { methodLists[i] = new MethodListWithDeclaringType(lookupGroups[i].DeclaringType, lookupGroups[i].Methods); } return methodLists; }
ResolveResult CreateResult(ResolveResult targetResolveResult, List<LookupGroup> lookupGroups, string name, IList<IType> typeArguments) { // Remove all hidden groups lookupGroups.RemoveAll(g => g.AllHidden); if (lookupGroups.Count == 0) { // No members found return new UnknownMemberResolveResult(targetResolveResult.Type, name, typeArguments); } if (lookupGroups.Any(g => !g.MethodsAreHidden && g.Methods.Count > 0)) { // If there are methods, make a MethodGroupResolveResult. // Note that a conflict between a member and a method (possible with multiple interface inheritance) // is only a warning, not an error, and the C# compiler will prefer the method group. List<MethodListWithDeclaringType> methodLists = new List<MethodListWithDeclaringType>(); foreach (var lookupGroup in lookupGroups) { if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0) { var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType); foreach (var method in lookupGroup.Methods) { methodListWithDeclType.Add((IMethod)method); } methodLists.Add(methodListWithDeclType); } } return new MethodGroupResolveResult(targetResolveResult, name, methodLists, typeArguments); } // If there are ambiguities, report the most-derived result (last group) LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1]; if (resultGroup.NestedTypes != null && resultGroup.NestedTypes.Count > 0) { if (resultGroup.NestedTypes.Count > 1 || !resultGroup.NonMethodIsHidden || lookupGroups.Count > 1) return new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0]); else return new TypeResolveResult(resultGroup.NestedTypes[0]); } if (lookupGroups.Count > 1) { return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod, resultGroup.NonMethod.ReturnType.Resolve(context)); } else { return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod, context); } }
/// <summary> /// Looks up the indexers on the target type. /// </summary> public IList<MethodListWithDeclaringType> LookupIndexers(ResolveResult targetResolveResult) { if (targetResolveResult == null) throw new ArgumentNullException("targetResolveResult"); IType targetType = targetResolveResult.Type; bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult); Predicate<IUnresolvedProperty> filter = p => p.IsIndexer; List<LookupGroup> lookupGroups = new List<LookupGroup>(); foreach (IType type in targetType.GetNonInterfaceBaseTypes()) { List<IParameterizedMember> newMethods = null; IMember newNonMethod = null; IEnumerable<IType> typeBaseTypes = null; var members = type.GetProperties(filter, GetMemberOptions.IgnoreInheritedMembers); AddMembers(type, members, allowProtectedAccess, lookupGroups, true, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newMethods != null || newNonMethod != null) lookupGroups.Add(new LookupGroup(type, null, newMethods, newNonMethod)); } // Remove interface members hidden by class members. if (targetType.Kind == TypeKind.TypeParameter) { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } // Remove all hidden groups lookupGroups.RemoveAll(g => g.MethodsAreHidden || g.Methods.Count == 0); MethodListWithDeclaringType[] methodLists = new MethodListWithDeclaringType[lookupGroups.Count]; for (int i = 0; i < methodLists.Length; i++) { methodLists[i] = new MethodListWithDeclaringType(lookupGroups[i].DeclaringType, lookupGroups[i].Methods); } return methodLists; }