diff --git a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs
index c40a34336..c4085c00a 100644
--- a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs
+++ b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs
@@ -10,7 +10,7 @@ namespace Discord.Commands
{
internal static class ModuleClassBuilder
{
- private static readonly TypeInfo ModuleTypeInfo = typeof(IModuleBase).GetTypeInfo();
+ public static readonly TypeInfo ModuleTypeInfo = typeof(IModuleBase).GetTypeInfo();
///Value1 - ready types, Value2 - types dependant on Value1.
public static async Task, IReadOnlyList>> SearchAsync(Assembly assembly, CommandService service)
@@ -25,23 +25,25 @@ namespace Discord.Commands
if (badModules.Contains(typeInfo))
continue;
- //Find SubTypes outside of parent class.
- var groupAttr = typeInfo.GetCustomAttribute();
- if (groupAttr != null)
+ if(typeInfo.IsOuterSubTypeCandidate(out Type parentType))
{
- if (groupAttr.ParentModule != null)
+ bool subTypeIsValid = await typeInfo.IsValidOuterSubTypeAsync(
+ parentType,
+ autoLoadable: true,
+ logger: service._cmdLogger);
+
+ if (subTypeIsValid)
{
- var parentTypeInfo = groupAttr.ParentModule.GetTypeInfo();
- bool subTypeIsValid = await ConfirmOuterSubTypeInfoAsync(service, typeInfo, parentTypeInfo, badModules);
- if(subTypeIsValid)
- {
- queuedModules.Add(typeInfo);
- }
- continue;
+ queuedModules.Add(typeInfo);
+ }
+ else
+ {
+ badModules.Add(typeInfo);
}
+ continue;
}
- bool typeInfoIsValid = await ConfirmTypeInfoAsync(service, typeInfo);
+ bool typeInfoIsValid = await typeInfo.IsValidModuleType(autoLoadable: true, logger: service._cmdLogger);
if(typeInfoIsValid)
{
standardModules.Add(typeInfo);
@@ -51,61 +53,16 @@ namespace Discord.Commands
return Tuple.Create, IReadOnlyList>(standardModules, queuedModules);
}
- private static bool IsLoadableModule(TypeInfo info)
- {
- return info.DeclaredMethods.Any(
- x => x.GetCustomAttribute() != null) &&
- info.GetCustomAttribute() == null;
- }
+ public static Task> BuildAsync(CommandService service, IServiceProvider services, IDictionary moduleDefs, params TypeInfo[] validTypes) =>
+ BuildAsync(validTypes, service, services, moduleDefs);
- ///Checks whether is valid to be loaded.
- ///CommandService object.
- ///Target type to check against.
- ///Checks parent type validity. Used with outer group modules.
- private static async Task ConfirmTypeInfoAsync(CommandService service, TypeInfo typeInfo)
- {
- if (typeInfo.IsPublic || typeInfo.IsNestedPublic)
- {
- if (IsValidModuleDefinition(typeInfo) &&
- !typeInfo.IsDefined(typeof(DontAutoLoadAttribute)))
- {
- return true;
- }
- }
- else if (IsLoadableModule(typeInfo))
- {
- await service._cmdLogger.WarningAsync($"Class {typeInfo.FullName} is not public and cannot be loaded. To suppress this message, mark the class with {nameof(DontAutoLoadAttribute)}.").ConfigureAwait(false);
- }
-
- return false;
- }
-
- ///Checks whether is valid to be loaded.
- ///CommandService object.
- ///Target type to check against.
- private static async Task ConfirmOuterSubTypeInfoAsync(CommandService service, TypeInfo typeInfo, TypeInfo parentTypeInfo, List badModules)
- {
- bool targetValid = await ConfirmTypeInfoAsync(service, typeInfo);
- if(targetValid)
- {
- bool parentValid = await ConfirmTypeInfoAsync(service, parentTypeInfo);
- if (!parentValid)
- {
- await service._cmdLogger.WarningAsync($"Parent Class {parentTypeInfo.FullName} is not a module. Group module {typeInfo.FullName} was not loaded.").ConfigureAwait(false);
- badModules.Add(parentTypeInfo);
- return false;
- }
- }
- return targetValid;
- }
-
- public static Task> BuildAsync(CommandService service, IServiceProvider services, params TypeInfo[] validTypes) => BuildAsync(validTypes, service, services);
- public static async Task> BuildAsync(IEnumerable validTypes, CommandService service, IServiceProvider services, Dictionary moduleDefs = null)
+ public static async Task> BuildAsync(IEnumerable validTypes, CommandService service, IServiceProvider services, IDictionary moduleDefs = null)
{
/*if (!validTypes.Any())
throw new InvalidOperationException("Could not find any valid modules from the given selection");*/
- var topLevelGroups = validTypes.Where(x => x.DeclaringType == null || !IsValidModuleDefinition(x.DeclaringType.GetTypeInfo()));
+ var topLevelGroups = validTypes
+ .Where(x => x.DeclaringType == null || !x.DeclaringType.GetTypeInfo().IsValidModuleDefinition());
var builtTypes = new List();
@@ -123,6 +80,7 @@ namespace Discord.Commands
BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services, moduleDefs);
builtTypes.Add(typeInfo);
+ //dont build yet, return as a module dictonary?
result[typeInfo.AsType()] = module.Build(service, services);
}
@@ -132,11 +90,11 @@ namespace Discord.Commands
return result;
}
- private static void BuildSubTypes(ModuleBuilder builder, IEnumerable subTypes, List builtTypes, CommandService service, IServiceProvider services, Dictionary moduleDefs)
+ private static void BuildSubTypes(ModuleBuilder builder, IEnumerable subTypes, List builtTypes, CommandService service, IServiceProvider services, IDictionary moduleDefs)
{
foreach (var typeInfo in subTypes)
{
- if (!IsValidModuleDefinition(typeInfo))
+ if (!typeInfo.IsValidModuleDefinition())
continue;
if (builtTypes.Contains(typeInfo))
@@ -152,7 +110,7 @@ namespace Discord.Commands
}
}
- private static void BuildModule(ModuleBuilder builder, TypeInfo typeInfo, CommandService service, IServiceProvider services, Dictionary moduleDefs)
+ private static void BuildModule(ModuleBuilder builder, TypeInfo typeInfo, CommandService service, IServiceProvider services, IDictionary moduleDefs)
{
var attributes = typeInfo.GetCustomAttributes();
builder.TypeInfo = typeInfo;
@@ -178,9 +136,16 @@ namespace Discord.Commands
builder.Group = group.Prefix;
if(group.ParentModule != null)
{
- foreach (string parentAlias in moduleDefs[group.ParentModule].Aliases)
+ if(moduleDefs.ContainsKey(group.ParentModule))
+ {
+ foreach (string parentAlias in moduleDefs[group.ParentModule].Aliases)
+ {
+ builder.AddAliases(parentAlias);
+ }
+ }
+ else
{
- builder.AddAliases(parentAlias);
+ throw new ArgumentNullException($"Parent module was not defined for outer sub type: {typeInfo.FullName}.");
}
}
builder.AddAliases(group.Prefix);
@@ -362,13 +327,6 @@ namespace Discord.Commands
return reader;
}
- private static bool IsValidModuleDefinition(TypeInfo typeInfo)
- {
- return ModuleTypeInfo.IsAssignableFrom(typeInfo) &&
- !typeInfo.IsAbstract &&
- !typeInfo.ContainsGenericParameters;
- }
-
private static bool IsValidCommandDefinition(MethodInfo methodInfo)
{
return methodInfo.IsDefined(typeof(CommandAttribute)) &&