mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
211 lines
7.9 KiB
C#
211 lines
7.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
using Dalamud.Game.Command;
|
|
using Dalamud.Plugin.Internal.Types;
|
|
|
|
namespace Dalamud.Plugin.Internal;
|
|
|
|
/// <summary>
|
|
/// Class responsible for validating a dev plugin.
|
|
/// </summary>
|
|
internal static class PluginValidator
|
|
{
|
|
private static readonly char[] LineSeparator = new[] { ' ', '\n', '\r' };
|
|
|
|
/// <summary>
|
|
/// Represents the severity of a validation problem.
|
|
/// </summary>
|
|
public enum ValidationSeverity
|
|
{
|
|
/// <summary>
|
|
/// The problem is informational.
|
|
/// </summary>
|
|
Information,
|
|
|
|
/// <summary>
|
|
/// The problem is a warning.
|
|
/// </summary>
|
|
Warning,
|
|
|
|
/// <summary>
|
|
/// The problem is fatal.
|
|
/// </summary>
|
|
Fatal,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a validation problem.
|
|
/// </summary>
|
|
public interface IValidationProblem
|
|
{
|
|
/// <summary>
|
|
/// Gets the severity of the validation.
|
|
/// </summary>
|
|
public ValidationSeverity Severity { get; }
|
|
|
|
/// <summary>
|
|
/// Compute the localized description of the problem.
|
|
/// </summary>
|
|
/// <returns>Localized string to be shown to the developer.</returns>
|
|
public string GetLocalizedDescription();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check for problems in a plugin.
|
|
/// </summary>
|
|
/// <param name="plugin">The plugin to validate.</param>
|
|
/// <returns>An list of problems.</returns>
|
|
/// <exception cref="InvalidOperationException">Thrown when the plugin is not loaded. A plugin must be loaded to validate it.</exception>
|
|
public static IReadOnlyList<IValidationProblem> CheckForProblems(LocalDevPlugin plugin)
|
|
{
|
|
var problems = new List<IValidationProblem>();
|
|
|
|
if (!plugin.IsLoaded)
|
|
throw new InvalidOperationException("Plugin must be loaded to validate.");
|
|
|
|
if (!plugin.DalamudInterface!.LocalUiBuilder.HasConfigUi)
|
|
problems.Add(new NoConfigUiProblem());
|
|
|
|
if (!plugin.DalamudInterface.LocalUiBuilder.HasMainUi)
|
|
problems.Add(new NoMainUiProblem());
|
|
|
|
var cmdManager = Service<CommandManager>.Get();
|
|
|
|
foreach (var cmd in cmdManager.GetHandlersByAssemblyName(plugin.InternalName).Where(c => c.Key.CommandInfo.ShowInHelp))
|
|
{
|
|
if (string.IsNullOrEmpty(cmd.Key.CommandInfo.HelpMessage))
|
|
problems.Add(new CommandWithoutHelpTextProblem(cmd.Value));
|
|
}
|
|
|
|
if (plugin.Manifest.Tags == null || plugin.Manifest.Tags.Count == 0)
|
|
problems.Add(new NoTagsProblem());
|
|
|
|
if (string.IsNullOrEmpty(plugin.Manifest.Description) || plugin.Manifest.Description.Split(LineSeparator, StringSplitOptions.RemoveEmptyEntries).Length <= 1)
|
|
problems.Add(new NoDescriptionProblem());
|
|
|
|
if (string.IsNullOrEmpty(plugin.Manifest.Punchline))
|
|
problems.Add(new NoPunchlineProblem());
|
|
|
|
if (string.IsNullOrEmpty(plugin.Manifest.Name))
|
|
problems.Add(new NoNameProblem());
|
|
|
|
if (string.IsNullOrEmpty(plugin.Manifest.Author))
|
|
problems.Add(new NoAuthorProblem());
|
|
|
|
if (plugin.IsOutdated)
|
|
problems.Add(new WrongApiLevelProblem());
|
|
|
|
return problems;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where the plugin does not have a config UI callback.
|
|
/// </summary>
|
|
public class NoConfigUiProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Warning;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "The plugin does not register a config UI callback. If you have a settings window or section, please consider registering UiBuilder.OpenConfigUi to open it.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where the plugin does not have a main UI callback.
|
|
/// </summary>
|
|
public class NoMainUiProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Warning;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "The plugin does not register a main UI callback. If your plugin has a window that could be considered the main entrypoint to its features, please consider registering UiBuilder.OpenMainUi to open the plugin's main window.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a command does not have a help text.
|
|
/// </summary>
|
|
/// <param name="commandName">Name of the command.</param>
|
|
public class CommandWithoutHelpTextProblem(string commandName) : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Fatal;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => $"The plugin has a command ({commandName}) without a help message. Please consider adding a help message to the command when registering it.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin does not have any tags in its manifest.
|
|
/// </summary>
|
|
public class NoTagsProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Information;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin does not have any tags in its manifest. Please consider adding some to make it easier for users to find your plugin in the installer.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin does not have a description in its manifest.
|
|
/// </summary>
|
|
public class NoDescriptionProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Information;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin does not have a description in its manifest, or it is very terse. Please consider adding one to give users more information about your plugin.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin has no punchline in its manifest.
|
|
/// </summary>
|
|
public class NoPunchlineProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Information;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin does not have a punchline in its manifest. Please consider adding one to give users a quick overview of what your plugin does.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin has no name in its manifest.
|
|
/// </summary>
|
|
public class NoNameProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Fatal;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin does not have a name in its manifest.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin has no author in its manifest.
|
|
/// </summary>
|
|
public class NoAuthorProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Fatal;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin does not have an author in its manifest.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Representing a problem where a plugin has an outdated API level.
|
|
/// </summary>
|
|
public class WrongApiLevelProblem : IValidationProblem
|
|
{
|
|
/// <inheritdoc/>
|
|
public ValidationSeverity Severity => ValidationSeverity.Fatal;
|
|
|
|
/// <inheritdoc/>
|
|
public string GetLocalizedDescription() => "Your plugin specifies an outdated API level. " +
|
|
"Please update it by updating DalamudPackager or Dalamud.NET.Sdk.";
|
|
}
|
|
}
|