Improved exception messages of builders (#3092)

* Fixed type reader/converter parsing exception

* Added the provided value to exceptions of some builders and, used more the Preconditions class.

* Removed unused `System.Xml.Linq` usings
This commit is contained in:
Suiram1701
2025-04-14 23:19:03 +02:00
committed by GitHub
parent 649f52b491
commit cce62747c9
11 changed files with 74 additions and 99 deletions

View File

@@ -1,5 +1,4 @@
using System;
using System.Xml.Linq;
namespace Discord;

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
@@ -147,29 +146,20 @@ namespace Discord
private static void EnsureValidOptionName(string name)
{
if (name == null)
throw new ArgumentNullException(nameof(name), $"{nameof(Name)} cannot be null.");
if (name.Length > 32)
throw new ArgumentOutOfRangeException(nameof(name), "Name length must be less than or equal to 32.");
Preconditions.NotNull(name, nameof(Name));
Preconditions.AtMost(name.Length, 32, nameof(Name));
if (!Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
if (name.Any(char.IsUpper))
throw new FormatException("Name cannot contain any uppercase characters.");
throw new FormatException($"Name cannot contain any uppercase characters. Value: \"{name}\"");
}
private static void EnsureValidOptionDescription(string description)
{
switch (description.Length)
{
case > 100:
throw new ArgumentOutOfRangeException(nameof(description),
"Description length must be less than or equal to 100.");
case 0:
throw new ArgumentOutOfRangeException(nameof(description), "Description length must at least 1.");
}
Preconditions.AtLeast(description.Length, 1, nameof(Description));
Preconditions.AtMost(description.Length, 100, nameof(Description));
}
}
}

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Discord
@@ -21,12 +19,12 @@ namespace Discord
public string Name
{
get => _name;
set => _name = value?.Length switch
set
{
> 100 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be less than or equal to 100."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Name));
Preconditions.AtMost(value.Length, 100, nameof(Name));
_name = value;
}
}
/// <summary>
@@ -41,7 +39,7 @@ namespace Discord
set
{
if (value != null && value is not string && !value.IsNumericType())
throw new ArgumentException("The value of a choice must be a string or a numeric type!");
throw new ArgumentException($"The value of a choice must be a string or a numeric type! Value: \"{value}\"");
_value = value;
}
}
@@ -60,16 +58,10 @@ namespace Discord
foreach (var (locale, name) in value)
{
if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$"))
throw new ArgumentException("Key values of the dictionary must be valid language codes.");
throw new ArgumentException($"Key values of the dictionary must be valid language codes. Locale: \"{locale}\"");
switch (name.Length)
{
case > 100:
throw new ArgumentOutOfRangeException(nameof(value),
"Name length must be less than or equal to 100.");
case 0:
throw new ArgumentOutOfRangeException(nameof(value), "Name length must at least 1.");
}
Preconditions.AtLeast(name.Length, 1, nameof(name), msg: $"Name value of locale {locale} cannot be empty.");
Preconditions.AtMost(name.Length, 100, nameof(name), msg: $"Name value of locale {locale} have to contains 100 chars at most.");
}
}

View File

@@ -46,7 +46,7 @@ namespace Discord
Preconditions.AtMost(name.Length, SlashCommandBuilder.MaxNameLength, nameof(name));
if (Type == ApplicationCommandType.Slash && !Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
}
}

View File

@@ -23,14 +23,10 @@ namespace Discord
get => _name;
set
{
if (value == null)
throw new ArgumentNullException(nameof(value), $"{nameof(Name)} cannot be null.");
_name = value.Length switch
{
> 100 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be less than or equal to 100."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Name length must be at least 1."),
_ => value
};
Preconditions.NotNull(value, nameof(Name));
Preconditions.AtLeast(value.Length, 1, nameof(Name));
Preconditions.AtMost(value.Length, 100, nameof(Name));
_name = value;
}
}
@@ -48,7 +44,7 @@ namespace Discord
set
{
if (value is not string && !value.IsNumericType())
throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!");
throw new ArgumentException($"{nameof(value)} must be a numeric type or a string! Value: \"{value}\"");
_value = value;
}

View File

@@ -22,12 +22,12 @@ public class ButtonBuilder
public string Label
{
get => _label;
set => _label = value?.Length switch
set
{
> MaxButtonLabelLength => throw new ArgumentOutOfRangeException(nameof(value), $"Label length must be less or equal to {MaxButtonLabelLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Label length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Label));
Preconditions.AtMost(value.Length, MaxButtonLabelLength, nameof(Label));
_label = value;
}
}
/// <summary>
@@ -38,12 +38,12 @@ public class ButtonBuilder
public string CustomId
{
get => _customId;
set => _customId = value?.Length switch
set
{
> ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom Id length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom Id length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(CustomId));
Preconditions.AtMost(value.Length, ComponentBuilder.MaxCustomIdLength, nameof(CustomId));
_customId = value;
}
}
/// <summary>
@@ -294,7 +294,6 @@ public class ButtonBuilder
throw new InvalidOperationException("A button must have an Emote or a label!");
if (string.IsNullOrWhiteSpace(CustomId))
throw new InvalidOperationException("Non-link and non-premium buttons must have a custom id associated with them");
}
break;

View File

@@ -33,12 +33,12 @@ public class SelectMenuBuilder
public string CustomId
{
get => _customId;
set => _customId = value?.Length switch
set
{
> ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom Id length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom Id length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(CustomId));
Preconditions.AtMost(value.Length, ComponentBuilder.MaxCustomIdLength, nameof(CustomId));
_customId = value;
}
}
/// <summary>
@@ -61,12 +61,12 @@ public class SelectMenuBuilder
public string Placeholder
{
get => _placeholder;
set => _placeholder = value?.Length switch
set
{
> MaxPlaceholderLength => throw new ArgumentOutOfRangeException(nameof(value), $"Placeholder length must be less or equal to {MaxPlaceholderLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Placeholder length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Placeholder));
Preconditions.AtMost(value.Length, MaxPlaceholderLength, nameof(Placeholder));
_placeholder = value;
}
}
/// <summary>
@@ -109,7 +109,6 @@ public class SelectMenuBuilder
{
if (value != null)
Preconditions.AtMost(value.Count, MaxOptionCount, nameof(Options));
_options = value;
}
}

View File

@@ -30,12 +30,12 @@ public class SelectMenuOptionBuilder
public string Label
{
get => _label;
set => _label = value?.Length switch
set
{
> MaxSelectLabelLength => throw new ArgumentOutOfRangeException(nameof(value), $"Label length must be less or equal to {MaxSelectLabelLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Label length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Label));
Preconditions.AtMost(value.Length, MaxSelectLabelLength, nameof(Label));
_label = value;
}
}
/// <summary>
@@ -46,12 +46,12 @@ public class SelectMenuOptionBuilder
public string Value
{
get => _value;
set => _value = value?.Length switch
set
{
> MaxSelectValueLength => throw new ArgumentOutOfRangeException(nameof(value), $"Value length must be less or equal to {MaxSelectValueLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Value length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Value));
Preconditions.AtMost(value.Length, MaxSelectValueLength, nameof(Value));
_value = value;
}
}
/// <summary>
@@ -62,12 +62,12 @@ public class SelectMenuOptionBuilder
public string Description
{
get => _description;
set => _description = value?.Length switch
set
{
> MaxDescriptionLength => throw new ArgumentOutOfRangeException(nameof(value), $"Description length must be less or equal to {MaxDescriptionLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Description length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(Description));
Preconditions.AtMost(value.Length, MaxDescriptionLength, nameof(Description));
_description = value;
}
}
/// <summary>

View File

@@ -22,12 +22,12 @@ public class TextInputBuilder
public string CustomId
{
get => _customId;
set => _customId = value?.Length switch
set
{
> ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom Id length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom Id length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(CustomId));
Preconditions.AtMost(value.Length, ComponentBuilder.MaxCustomIdLength, nameof(CustomId));
_customId = value;
}
}
/// <summary>
@@ -49,7 +49,7 @@ public class TextInputBuilder
get => _placeholder;
set => _placeholder = (value?.Length ?? 0) <= MaxPlaceholderLength
? value
: throw new ArgumentException($"Placeholder cannot have more than {MaxPlaceholderLength} characters.");
: throw new ArgumentException($"Placeholder cannot have more than {MaxPlaceholderLength} characters. Value: \"{value}\"");
}
/// <summary>
@@ -115,9 +115,9 @@ public class TextInputBuilder
set
{
if (value?.Length > (MaxLength ?? LargestMaxLength))
throw new ArgumentOutOfRangeException(nameof(value), $"Value must not be longer than {MaxLength ?? LargestMaxLength}.");
throw new ArgumentOutOfRangeException(nameof(value), $"Value must not be longer than {MaxLength ?? LargestMaxLength}. Value: \"{value}\"");
if (value?.Length < (MinLength ?? 0))
throw new ArgumentOutOfRangeException(nameof(value), $"Value must not be shorter than {MinLength}");
throw new ArgumentOutOfRangeException(nameof(value), $"Value must not be shorter than {MinLength}. Value: \"{value}\"");
_value = value;
}

View File

@@ -38,12 +38,12 @@ namespace Discord
public string CustomId
{
get => _customId;
set => _customId = value?.Length switch
set
{
> ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom ID length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom ID length must be at least 1."),
_ => value
};
Preconditions.AtLeast(value.Length, 1, nameof(CustomId));
Preconditions.AtMost(value.Length, ComponentBuilder.MaxCustomIdLength, nameof(CustomId));
_customId = value;
}
}
/// <summary>

View File

@@ -272,7 +272,7 @@ namespace Discord
// https://discord.com/developers/docs/interactions/application-commands
if (!Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
// make sure theres only one option with default set to true
if (isDefault == true && Options?.Any(x => x.IsDefault == true) == true)
@@ -440,10 +440,10 @@ namespace Discord
// https://discord.com/developers/docs/interactions/application-commands
if (!Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L]}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
if (name.Any(char.IsUpper))
throw new FormatException("Name cannot contain any uppercase characters.");
throw new FormatException($"Name cannot contain any uppercase characters. Value: \"{name}\"");
}
internal static void EnsureValidCommandDescription(string description)
@@ -650,7 +650,7 @@ namespace Discord
// https://discord.com/developers/docs/interactions/application-commands
if (!Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
// make sure theres only one option with default set to true
if (isDefault && Options?.Any(x => x.IsDefault == true) == true)
@@ -1031,7 +1031,7 @@ namespace Discord
// https://discord.com/developers/docs/interactions/application-commands
if (!Regex.IsMatch(name, @"^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$"))
throw new ArgumentException(@"Name must match the regex ^[-_\p{L}\p{N}\p{IsDevanagari}\p{IsThai}]{1,32}$", nameof(name));
throw new ArgumentException(@$"Name must match the regex ^[-_\p{{L}}\p{{N}}\p{{IsDevanagari}}\p{{IsThai}}]{{1,32}}$. Value: ""{name}""", nameof(name));
}
private static void EnsureValidCommandOptionDescription(string description)