internal static bool CanBeSeenByMockAssembly(this Assembly @this, bool isMemberPublic, bool isMemberPrivate, bool isMemberFamily, bool isMemberFamilyOrAssembly, NameGenerator generator) { return isMemberPublic || isMemberFamily || isMemberFamilyOrAssembly || (!isMemberPrivate && @this.GetCustomAttributes<InternalsVisibleToAttribute>() .Where(_ => _.AssemblyName == generator.AssemblyName).Any()); }
internal static bool CanBeSeenByMockAssembly(this MethodInfo @this, NameGenerator generator) { if([email protected] && (@this.IsPrivate || ([email protected] && [email protected](generator)))) { return false; } foreach(var parameter in @this.GetParameters()) { if(!parameter.ParameterType.CanBeSeenByMockAssembly(generator)) { return false; } } if(@this.ReturnType != typeof(void)) { if([email protected](generator)) { return false; } } return true; }
internal GetGeneratedEventsResults Generate(Type baseType, SortedSet<string> namespaces, NameGenerator generator, MethodInformationBuilder builder) { var requiresObsoleteSuppression = false; var generatedEvents = new List<string>(); foreach (var @event in baseType.GetMockableEvents(generator)) { var eventHandlerType = @event.EventHandlerType; namespaces.Add(eventHandlerType.Namespace); var eventMethod = @event.AddMethod; var methodInformation = builder.Build(new MockableResult<MethodInfo>( eventMethod, RequiresExplicitInterfaceImplementation.No)); var @override = methodInformation.DescriptionWithOverride.Contains("override") ? "override " : string.Empty; if (eventMethod.IsPublic) { if (eventHandlerType.IsGenericType) { var eventGenericType = eventHandlerType.GetGenericArguments()[0]; generatedEvents.Add(EventTemplates.GetEvent(@override, $"EventHandler<{eventGenericType.GetSafeName()}>", @event.Name)); namespaces.Add(eventGenericType.Namespace); } else { generatedEvents.Add(EventTemplates.GetEvent(@override, eventHandlerType.GetSafeName(), @event.Name)); } requiresObsoleteSuppression |= @event.GetCustomAttribute<ObsoleteAttribute>() != null; } else if (!eventMethod.IsPrivate && eventMethod.IsAbstract) { var visibility = CodeTemplates.GetVisibility(eventMethod.IsFamily, eventMethod.IsFamilyOrAssembly); if (eventHandlerType.IsGenericType) { var eventGenericType = eventHandlerType.GetGenericArguments()[0]; generatedEvents.Add(EventTemplates.GetNonPublicEvent(visibility, $"EventHandler<{eventGenericType.GetSafeName()}>", @event.Name)); namespaces.Add(eventGenericType.Namespace); } else { generatedEvents.Add(EventTemplates.GetNonPublicEvent(visibility, eventHandlerType.GetSafeName(), @event.Name)); } requiresObsoleteSuppression |= @event.GetCustomAttribute<ObsoleteAttribute>() != null; } } return new GetGeneratedEventsResults(generatedEvents.AsReadOnly(), requiresObsoleteSuppression); }
internal static ReadOnlyCollection<MockableResult<ConstructorInfo>> GetMockableConstructors(this Type @this, NameGenerator generator) { return new ReadOnlyCollection<MockableResult<ConstructorInfo>>( @this.GetConstructors(ReflectionValues.PublicNonPublicInstance) .Where(_ => !_.IsPrivate && (_.GetCustomAttribute<ObsoleteAttribute>() == null || !_.GetCustomAttribute<ObsoleteAttribute>().IsError) && _.DeclaringType.Assembly.CanBeSeenByMockAssembly(_.IsPublic, false, _.IsFamily, _.IsFamilyOrAssembly, generator) && !_.GetParameters().Where(p => !p.ParameterType.CanBeSeenByMockAssembly(generator)).Any()) .Select(_ => new MockableResult<ConstructorInfo>(_, RequiresExplicitInterfaceImplementation.No)).ToList()); }
internal static ReadOnlyCollection<MethodMockableResult> GetMockableMethods(this Type @this, NameGenerator generator) { var objectMethods = @this.IsInterface ? typeof(object).GetMethods().Where(_ => _.IsExtern() || _.IsVirtual).ToList() : new List<MethodInfo>(); var methods = new HashSet<MockableResult<MethodInfo>>(@this.GetMethods(ReflectionValues.PublicNonPublicInstance) .Where(_ => !_.IsSpecialName && _.IsVirtual && !_.IsFinal && !objectMethods.Where(om => om.Match(_) == MethodMatch.Exact).Any() && _.DeclaringType.Assembly.CanBeSeenByMockAssembly(_.IsPublic, _.IsPrivate, _.IsFamily, _.IsFamilyOrAssembly, generator)) .Select(_ => new MockableResult<MethodInfo>(_, RequiresExplicitInterfaceImplementation.No))); if (@this.IsInterface) { var namespaces = new SortedSet<string>(); foreach (var @interface in @this.GetInterfaces()) { var interfaceMethods = @interface.GetMethods() .Where(_ => !_.IsSpecialName && !objectMethods.Where(om => om.Match(_) == MethodMatch.Exact).Any()); foreach (var interfaceMethod in interfaceMethods) { if (interfaceMethod.CanBeSeenByMockAssembly(generator)) { var matchMethodGroups = methods.GroupBy(_ => interfaceMethod.Match(_.Value)).ToDictionary(_ => _.Key); if (!matchMethodGroups.ContainsKey(MethodMatch.Exact)) { methods.Add(new MockableResult<MethodInfo>( interfaceMethod, matchMethodGroups.ContainsKey(MethodMatch.DifferByReturnTypeOnly) ? RequiresExplicitInterfaceImplementation.Yes : RequiresExplicitInterfaceImplementation.No)); } } } } } var baseStaticMethods = @this.IsInterface ? typeof(object).GetMethods().Where(_ => _.IsStatic).ToList() : @this.GetMethods().Where(_ => _.IsStatic).ToList(); return methods.Select(_ => new MethodMockableResult( _.Value, _.RequiresExplicitInterfaceImplementation, baseStaticMethods.Where(osm => osm.Match(_.Value) == MethodMatch.Exact).Any() ? RequiresIsNewImplementation.Yes : RequiresIsNewImplementation.No)).ToList().AsReadOnly(); }
internal static bool CanBeSeenByMockAssembly(this Type @this, NameGenerator generator) { var root = @this.GetRootElementType(); return root.IsPublic || (root.Assembly.GetCustomAttributes<InternalsVisibleToAttribute>() .Where(_ => _.AssemblyName == generator.AssemblyName).Any()); }
internal static string Validate(this Type @this, SerializationOptions options, NameGenerator generator) { if (@this.IsSealed && [email protected]() .Where(_ => _.GetParameters().Length == 1 && typeof(ReadOnlyDictionary<int, ReadOnlyCollection<HandlerInformation>>).IsAssignableFrom(_.GetParameters()[0].ParameterType)).Any()) { return ErrorMessages.GetCannotMockSealedType(@this.GetSafeName()); } if (options == SerializationOptions.Supported && [email protected] && @this.GetConstructor(Type.EmptyTypes) == null) { return ErrorMessages.GetCannotMockTypeWithSerializationRequestedAndNoPublicNoArgumentConstructor(@this.GetSafeName()); } if (@this.IsAbstract && (@this.GetConstructors(ReflectionValues.NonPublicInstance).Where(_ => _.IsAssembly).Any() || @this.GetMethods(ReflectionValues.NonPublicInstance).Where(_ => _.IsAssembly && _.IsAbstract).Any() || @this.GetProperties(ReflectionValues.NonPublicInstance).Where(_ => _.GetDefaultMethod().IsAssembly && _.GetDefaultMethod().IsAbstract).Any() || @this.GetEvents(ReflectionValues.NonPublicInstance).Where(_ => _.AddMethod.IsAssembly && _.AddMethod.IsAbstract).Any())) { if ([email protected](false, false, false, false, generator)) { return ErrorMessages.GetCannotMockTypeWithInternalAbstractMembers(@this.GetSafeName()); } } if([email protected] && @this.GetMockableConstructors(generator).Count == 0) { return ErrorMessages.GetCannotMockTypeWithNoAccessibleConstructors(@this.GetSafeName()); } return string.Empty; }
internal static ReadOnlyCollection<EventInfo> GetMockableEvents(this Type @this, NameGenerator generator) { var events = new HashSet<EventInfo>(@this.GetEvents(ReflectionValues.PublicNonPublicInstance) .Where(_ => _.AddMethod.IsVirtual && !_.AddMethod.IsFinal && _.AddMethod.CanBeSeenByMockAssembly(generator))); if (@this.IsInterface) { foreach (var @interface in @this.GetInterfaces()) { events.UnionWith(@interface.GetMockableEvents(generator)); } } return events.ToList().AsReadOnly(); }
internal static ReadOnlyCollection<PropertyMockableResult> GetMockableProperties(this Type @this, NameGenerator generator) { var properties = new HashSet<PropertyMockableResult>( from property in @this.GetProperties(ReflectionValues.PublicNonPublicInstance) let canGet = property.CanRead && property.GetMethod.IsVirtual && !property.GetMethod.IsFinal && property.GetMethod.DeclaringType.Assembly.CanBeSeenByMockAssembly( property.GetMethod.IsPublic, property.GetMethod.IsPrivate, property.GetMethod.IsFamily, property.GetMethod.IsFamilyOrAssembly, generator) let canSet = property.CanWrite && property.SetMethod.IsVirtual && !property.SetMethod.IsFinal && property.SetMethod.DeclaringType.Assembly.CanBeSeenByMockAssembly( property.SetMethod.IsPublic, property.SetMethod.IsPrivate, property.SetMethod.IsFamily, property.SetMethod.IsFamilyOrAssembly, generator) where canGet || canSet select new PropertyMockableResult(property, RequiresExplicitInterfaceImplementation.No, (canGet && canSet ? PropertyAccessors.GetAndSet : (canGet ? PropertyAccessors.Get : PropertyAccessors.Set)))); if (@this.IsInterface) { var namespaces = new SortedSet<string>(); foreach (var @interface in @this.GetInterfaces()) { foreach (var interfaceProperty in @interface.GetMockableProperties(generator)) { if (interfaceProperty.Value.GetDefaultMethod().CanBeSeenByMockAssembly(generator)) { var matchMethodGroups = properties.GroupBy(_ => interfaceProperty.Value.GetDefaultMethod().Match(_.Value.GetDefaultMethod())).ToDictionary(_ => _.Key); if (!matchMethodGroups.ContainsKey(MethodMatch.Exact)) { properties.Add(new PropertyMockableResult(interfaceProperty.Value, matchMethodGroups.ContainsKey(MethodMatch.DifferByReturnTypeOnly) ? RequiresExplicitInterfaceImplementation.Yes : RequiresExplicitInterfaceImplementation.No, interfaceProperty.Accessors)); } } } } } return properties.ToList().AsReadOnly(); }