Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
5ec96f0
Start command service implementation.
kevzhao2 Sep 30, 2019
29265ef
Add Pure contract to FindCommands.
kevzhao2 Sep 30, 2019
14e4b6e
Add JetBrains.Annotations.
kevzhao2 Sep 30, 2019
5e0e692
Add [MeansImplicitUse] to CommandHandlerAttribute.
kevzhao2 Sep 30, 2019
e2af163
Implement TShockCommandService and tests.
kevzhao2 Sep 30, 2019
9bf28b4
Add IArgumentParser interface and Int32Parser implementation.
kevzhao2 Sep 30, 2019
07ca5fe
Rename Parsing to Parsers.
kevzhao2 Sep 30, 2019
31ad6fe
Adjust Parsing to Parsers namespace.
kevzhao2 Sep 30, 2019
ebc683e
Add StringParser.
kevzhao2 Sep 30, 2019
bc99d33
Add non-generic IArgumentParser.
kevzhao2 Sep 30, 2019
3ea5469
Add RegisterParser to ICommandService interface.
kevzhao2 Sep 30, 2019
043befc
Add ParseOptionsAttribute.
kevzhao2 Sep 30, 2019
fd36f11
Add ParseOptions to parse a string to the end of the input.
kevzhao2 Sep 30, 2019
8fe4653
Add strongly-typed RegisterParser extension method.
kevzhao2 Sep 30, 2019
f7ea6c3
Add parsers in TShockCommandService constructor.
kevzhao2 Sep 30, 2019
4b99642
Remove [NotNull]s.
kevzhao2 Sep 30, 2019
ca8fbc2
Begin implementation of ICommand.Invoke.
kevzhao2 Sep 30, 2019
c04918e
Remove another instance of NotNull.
kevzhao2 Sep 30, 2019
aedc4a6
Bind ICommandService in TShockPlugin constructor.
kevzhao2 Sep 30, 2019
d49dffd
Add tests for TShockCommand.
kevzhao2 Sep 30, 2019
0d1da26
Add CommandException.
kevzhao2 Sep 30, 2019
da8b283
Add FlagAttribute.
kevzhao2 Sep 30, 2019
b9e7d9f
Add ScanFor extension method.
kevzhao2 Sep 30, 2019
be4566b
Add short flag parsing.
kevzhao2 Sep 30, 2019
6a4c3b7
Switch out nextInput in IArgumentParser for ref input.
kevzhao2 Sep 30, 2019
865e59e
Implement and test flags and optionals parsing.
kevzhao2 Oct 1, 2019
3f1f738
Rename ParseException to CommandParseException and inherit from Comma…
kevzhao2 Oct 1, 2019
ca06750
Add AllowEmpty option for StringParser.
kevzhao2 Oct 1, 2019
5210329
Add check for too many command arguments.
kevzhao2 Oct 1, 2019
2653690
Add Int32Parser restrictions on empty input.
kevzhao2 Oct 1, 2019
bca8dab
Change some Int32 exception messages.
kevzhao2 Oct 1, 2019
ab531e8
Change StringParser exception messages.
kevzhao2 Oct 1, 2019
8659dca
Restructure TShockCommand implementation.
kevzhao2 Oct 1, 2019
0b5206f
Remove unused static readonly fields.
kevzhao2 Oct 1, 2019
91fc5f7
Improve command parsing some more.
kevzhao2 Oct 1, 2019
3860b12
Remove unused resource strings.
kevzhao2 Oct 1, 2019
69edfb8
Add more command tests.
kevzhao2 Oct 1, 2019
15febbd
Remove logging in Invoke method.
kevzhao2 Oct 1, 2019
89eb94c
Remove unused usings.
kevzhao2 Oct 1, 2019
f75ddff
Migrate to using <see langword>. Add Player property to ICommandSender.
kevzhao2 Oct 1, 2019
c923e49
Start PlayerCommandSender implementation.
kevzhao2 Oct 1, 2019
da9acd6
Update attribute XML docs.
kevzhao2 Oct 1, 2019
db87668
Make RegisterParser type-safe.
kevzhao2 Oct 1, 2019
fbca462
Make ScanFor generic.
kevzhao2 Oct 1, 2019
f6b7cda
Make FlagAttribute take any number of arguments.
kevzhao2 Oct 2, 2019
69c1ad2
Make Commands an IReadOnlyCollection.
kevzhao2 Oct 2, 2019
240f5c8
Add ConsoleCommandSender.
kevzhao2 Oct 2, 2019
ee08913
Make ICommandSender take ReadOnlySpan<char>.
kevzhao2 Oct 2, 2019
a67c5b8
Add SendMessage overload to ICommandSender with no color argument.
kevzhao2 Oct 2, 2019
2493084
Add static Console property to ICommandSender.
kevzhao2 Oct 2, 2019
8b3ee39
Make ICommand take ReadOnlySpan<char>.
kevzhao2 Oct 2, 2019
f491b41
Make ICommandService use IReadOnlyDictionary, and return views.
kevzhao2 Oct 2, 2019
cd1ae3f
Use IPlayer.SendMessage in PlayerCommandSender.
kevzhao2 Oct 2, 2019
a55a167
Fix failing tests and add ICommandSender.FromPlayer.
kevzhao2 Oct 2, 2019
e6e1e8b
Use InvariantCulture in Int32Parser.
kevzhao2 Oct 2, 2019
e1b67e8
Use FormattableString.Invariant in ConsoleCommandSender.
kevzhao2 Oct 2, 2019
cbf6766
Add ReadOnlySpan<char> to sender constructors for input logging.
kevzhao2 Oct 3, 2019
3223a51
Implement player logging.
kevzhao2 Oct 3, 2019
d813ebb
Remove redundant _IsCorrect() in test names.
kevzhao2 Oct 3, 2019
a3f0a2c
General cleanup.
kevzhao2 Oct 3, 2019
1545f03
Remove localization for programmer-oriented output.
kevzhao2 Oct 3, 2019
0a0665b
Cleanup code some more.
kevzhao2 Oct 4, 2019
f0a6861
Make IndexOfOrEnd public and move to Utils/Extensions.
kevzhao2 Oct 5, 2019
bf2ecd8
Include test deletion.
kevzhao2 Oct 5, 2019
77d2b90
Rename command Name to QualifiedName.
kevzhao2 Oct 5, 2019
0a531c1
Add DictionaryExtensions.
kevzhao2 Oct 5, 2019
4650173
DESIGN DECISION: do not support command subnames natively.
kevzhao2 Oct 5, 2019
b6bc926
Implement command finding. Clean up code again.
kevzhao2 Oct 5, 2019
ee36383
Add FxCop analyzers, and treat warnings as errors.
kevzhao2 Oct 5, 2019
19b2274
Implement PlayerChat handler.
kevzhao2 Oct 5, 2019
148ffef
Apply code cleanup.
kevzhao2 Oct 5, 2019
1ca15f5
Update .editorconfig.
kevzhao2 Oct 5, 2019
29477c6
Implement Help command.
kevzhao2 Oct 5, 2019
281ecec
Implement console commands.
kevzhao2 Oct 5, 2019
12f805f
Make ICommandSender use string instead of ReadOnlySpan<char>.
kevzhao2 Oct 7, 2019
619089b
Implement /playing.
kevzhao2 Oct 7, 2019
bcd77e5
Rename Chat_BadCommand to Command_BadCommand.
kevzhao2 Oct 7, 2019
5d36b6a
Implement /me.
kevzhao2 Oct 7, 2019
4f8313c
Update /me color.
kevzhao2 Oct 7, 2019
2da15dc
Inline colors.
kevzhao2 Oct 7, 2019
a485cb7
Implement /roll.
kevzhao2 Oct 7, 2019
5ed5e55
Implement /p.
kevzhao2 Oct 8, 2019
4a43cbb
Allow optionals to be parsed with extra arguments, and fix failing te…
kevzhao2 Oct 8, 2019
9d60bcb
Improve /help to only include command namespaces if necessary.
kevzhao2 Oct 8, 2019
196558e
Make parsers public.
kevzhao2 Oct 8, 2019
84f483e
Implement params parsing.
kevzhao2 Oct 8, 2019
0c13777
Make ICommandSender implementations public, and remove input from ctors.
kevzhao2 Oct 8, 2019
dccf2de
Switch to more invariant culture strings.
kevzhao2 Oct 8, 2019
8a249ab
Remove ParseOptions.AllowEmpty, as that is no longer necessary.
kevzhao2 Oct 9, 2019
1b6eb46
Remove un-necessary spaces from XMLdoc tags.
kevzhao2 Oct 9, 2019
16e3eb0
Add test for default interface implementation.
kevzhao2 Oct 9, 2019
faa6378
Move default interface methods in ICommandSender out.
kevzhao2 Oct 9, 2019
3f370bb
Add more validation.
kevzhao2 Oct 9, 2019
bcbe2ad
Switch to attribute-based parsing.
kevzhao2 Oct 9, 2019
6dbc945
Implement localizable CommandHandlerAttribute.
kevzhao2 Oct 9, 2019
60c13e5
Add ArgumentNullException xmldoc to ResourceType.
kevzhao2 Oct 9, 2019
f32af9d
Implement extra functionality for help command.
kevzhao2 Oct 9, 2019
5851cf1
Localize log messages.
kevzhao2 Oct 9, 2019
976777e
Undo test change.
kevzhao2 Oct 9, 2019
e9756d7
Show usage text on command parsing errors.
kevzhao2 Oct 9, 2019
d9b549d
Move exceptions into the Exceptions namespace.
kevzhao2 Oct 9, 2019
c70dd79
Implement DoubleParser.
kevzhao2 Oct 9, 2019
04f761f
Make TShockCommandService thread-safe.
kevzhao2 Oct 9, 2019
9304460
Improve GetValueOrDefault.
kevzhao2 Oct 9, 2019
13bb612
Persist the PlayerCommandSender.
kevzhao2 Oct 9, 2019
a6a6a2f
Strip leading / from /help argument.
kevzhao2 Oct 9, 2019
f1737f1
Switch to string and ReadOnlySpan<char> when necessary.
kevzhao2 Oct 10, 2019
ed7c569
Remove HandlerObject and Handler from ICommand as those are implement…
kevzhao2 Oct 10, 2019
b6cf6f5
Clean up implementation and fix failing tests.
kevzhao2 Oct 10, 2019
45ac981
Implement ShouldBeLogged for sensitive commands.
kevzhao2 Oct 10, 2019
c2e5bbe
Refactor out commands into a separate module of functionality.
kevzhao2 Oct 10, 2019
3b40693
Add tests for TShockPlugin.
kevzhao2 Oct 10, 2019
2f98903
Localize Terraria command -> command map.
kevzhao2 Oct 10, 2019
a717c63
Create comprehensive logging sub-library.
kevzhao2 Oct 11, 2019
9c34a3f
Remove {Properties} from ConsoleCommandSender log.
kevzhao2 Oct 11, 2019
312c394
Update to new Orion features.
kevzhao2 Oct 14, 2019
d7723db
Update to new Orion v2 branch.
kevzhao2 Oct 23, 2019
bad3e4e
Code cleanup.
kevzhao2 Oct 23, 2019
9ad0be9
Simplify module Dispose pattern.
kevzhao2 Oct 23, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ csharp_style_var_for_built_in_types=true:silent
csharp_style_var_when_type_is_apparent=true:silent
csharp_style_var_elsewhere=true:silent
# Expression-bodied members
csharp_style_expression_bodied_methods=false:silent
csharp_style_expression_bodied_methods=true:silent
csharp_style_expression_bodied_constructors=false:silent
csharp_style_expression_bodied_operators=false:silent
csharp_style_expression_bodied_operators=true:silent
csharp_style_expression_bodied_properties=true:silent
csharp_style_expression_bodied_indexers=true:silent
csharp_style_expression_bodied_accessors=true:silent
csharp_style_expression_bodied_local_functions = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check=true:suggestion
csharp_style_pattern_matching_over_as_with_null_check=true:suggestion
Expand Down
91 changes: 76 additions & 15 deletions src/TShock/Commands/CommandHandlerAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,98 @@
// along with TShock. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using TShock.Utils;

namespace TShock.Commands {
/// <summary>
/// An attribute that can be applied to a method to indicate that it is a command handler. This can be applied to
/// a method mutiple times to provide aliasing.
/// Specifies that a method is a command handler. This controls many aspects of the command, and can be applied
/// multiple times to provide aliasing.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
[MeansImplicitUse]
public sealed class CommandHandlerAttribute : Attribute {
private readonly string _qualifiedName;

private string? _helpText;
private string? _usageText;
private Type? _resourceType;

/// <summary>
/// Gets the qualified name. This includes the namespace: e.g., <c>tshock:kick</c>.
/// </summary>
/// <value>The qualified name.</value>
public string QualifiedName => GetResourceStringMaybe(_qualifiedName);

/// <summary>
/// Gets or sets the help text. This will show up in the /help command. If <see langword="null"/>, then no help
/// text exists.
/// </summary>
/// <value>The help text.</value>
/// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>
[DisallowNull]
public string? HelpText {
get => GetResourceStringMaybe(_helpText);
set => _helpText = value ?? throw new ArgumentNullException(nameof(value));
}

/// <summary>
/// Gets the command's name. This includes the command's namespace: e.g., <c>"tshock:kick"</c>.
/// Gets or sets the usage text. This will show up in the /help command and when invalid syntax is used. If
/// <see langword="null"/>, then no usage text exists.
/// </summary>
public string CommandName { get; }
/// <value>The usage text.</value>
/// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>
[DisallowNull]
public string? UsageText {
get => GetResourceStringMaybe(_usageText);
set => _usageText = value ?? throw new ArgumentNullException(nameof(value));
}

/// <summary>
/// Gets or sets the resource type to load localizable strings from. If <see langword="null"/>, then no
/// localization will occur.
/// </summary>
/// <value>The resource type to load localizable strings from.</value>
/// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>
[DisallowNull]
public Type? ResourceType {
get => _resourceType;
set => _resourceType = value ?? throw new ArgumentNullException(nameof(value));
}

/// <summary>
/// Gets the command's sub-names.
/// Gets or sets a value indicating whether the command should be logged.
/// </summary>
public IEnumerable<string> CommandSubNames { get; }
/// <value><see langword="true"/> if the command should be logged; otherwise, <see langword="false"/>.</value>
/// <remarks>This property's value is useful for hiding, e.g., authentication commands.</remarks>
public bool ShouldBeLogged { get; set; } = true;

/// <summary>
/// Initializes a new instance of the <see cref="CommandHandlerAttribute"/> class with the given command name
/// and sub-names.
/// Initializes a new instance of the <see cref="CommandHandlerAttribute"/> class with the specified qualified
/// name.
/// </summary>
/// <param name="commandName">The command name.</param>
/// <param name="commandSubNames">The command sub-names.</param>
/// <param name="qualifiedName">
/// The qualified name. This includes the namespace: e.g., <c>tshock:kick</c>.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="commandName"/> or <paramref name="commandSubNames"/> are <c>null</c>.
/// <paramref name="qualifiedName"/> is <see langword="null"/>.
/// </exception>
public CommandHandlerAttribute(string commandName, params string[] commandSubNames) {
CommandName = commandName ?? throw new ArgumentNullException(nameof(commandName));
CommandSubNames = commandSubNames ?? throw new ArgumentNullException(nameof(commandSubNames));
public CommandHandlerAttribute(string qualifiedName) {
if (qualifiedName is null) {
throw new ArgumentNullException(nameof(qualifiedName));
}

_qualifiedName = qualifiedName;
}

[return: NotNullIfNotNull("str")]
private string? GetResourceStringMaybe(string? str) {
if (str is null) {
return null;
}

return _resourceType != null ? ResourceHelper.LoadResource<string>(_resourceType, str) : str;
}
}
}
107 changes: 107 additions & 0 deletions src/TShock/Commands/ConsoleCommandSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2019 Pryaxis & TShock Contributors
//
// This file is part of TShock.
//
// TShock is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TShock is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TShock. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Globalization;
using System.Text;
using Destructurama;
using JetBrains.Annotations;
using Microsoft.Xna.Framework;
using Orion.Players;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;

namespace TShock.Commands {
/// <summary>
/// Represents a console-based command sender.
/// </summary>
public sealed class ConsoleCommandSender : ICommandSender {
#if DEBUG
private const LogEventLevel LogLevel = LogEventLevel.Verbose;
#else
private const LogEventLevel LogLevel = LogEventLevel.Error;
#endif

/// <summary>
/// Gets the console-based command sender.
/// </summary>
/// <value>The console-based command sender.</value>
public static ConsoleCommandSender Instance { get; } = new ConsoleCommandSender();

/// <inheritdoc/>
public string Name => "Console";

/// <inheritdoc/>
public ILogger Log { get; }

/// <inheritdoc/>
public IPlayer? Player => null;

[Pure]
private static string GetColorString(Color color) => $"\x1b[38;2;{color.R};{color.G};{color.B}m";

private ConsoleCommandSender() {
Log = new LoggerConfiguration()
.Destructure.UsingAttributes()
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:l}{NewLine}{Exception}",
theme: AnsiConsoleTheme.Code)
.MinimumLevel.Is(LogLevel)
.CreateLogger();
}

/// <inheritdoc/>
public void SendMessage(string message) => SendMessageImpl(message, string.Empty);

/// <inheritdoc/>
public void SendMessage(string message, Color color) => SendMessageImpl(message, GetColorString(color));

private static void SendMessageImpl(ReadOnlySpan<char> message, string colorString) {
var output = new StringBuilder(message.Length);
while (true) {
output.Append(colorString);
var leftBracket = message.IndexOf('[');
var rightBracket = leftBracket + 1 + message[(leftBracket + 1)..].IndexOf(']');
if (leftBracket < 0 || rightBracket < 0) {
break;
}

output.Append(message[..leftBracket]);
var inside = message[(leftBracket + 1)..rightBracket];
message = message[(rightBracket + 1)..];
var colon = inside.IndexOf(':');
var isValidColorTag = inside.StartsWith("c/", StringComparison.OrdinalIgnoreCase) && colon > 2;
if (!isValidColorTag) {
output.Append('[').Append(inside).Append(']');
continue;
}

if (int.TryParse(inside[2..colon], NumberStyles.AllowHexSpecifier,
CultureInfo.InvariantCulture, out var numberColor)) {
var tagColor = new Color((numberColor >> 16) & 255, (numberColor >> 8) & 255, numberColor & 255);
output.Append(GetColorString(tagColor));
}

output.Append(inside[(colon + 1)..]);
}

output.Append(message).Append("\x1b[0m");
Console.WriteLine(output);
}
}
}
46 changes: 46 additions & 0 deletions src/TShock/Commands/Exceptions/CommandExecuteException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2019 Pryaxis & TShock Contributors
//
// This file is part of TShock.
//
// TShock is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TShock is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TShock. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Diagnostics.CodeAnalysis;

namespace TShock.Commands.Exceptions {
/// <summary>
/// The exception thrown when a command could not be executed.
/// </summary>
[ExcludeFromCodeCoverage]
public class CommandExecuteException : Exception {
/// <summary>
/// Initializes a new instance of the <see cref="CommandExecuteException"/> class.
/// </summary>
public CommandExecuteException() { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandExecuteException"/> class with the specified message.
/// </summary>
/// <param name="message">The message.</param>
public CommandExecuteException(string message) : base(message) { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandExecuteException"/> class with the specified message
/// and inner exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
public CommandExecuteException(string message, Exception innerException) : base(message, innerException) { }
}
}
46 changes: 46 additions & 0 deletions src/TShock/Commands/Exceptions/CommandNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2019 Pryaxis & TShock Contributors
//
// This file is part of TShock.
//
// TShock is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TShock is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TShock. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Diagnostics.CodeAnalysis;

namespace TShock.Commands.Exceptions {
/// <summary>
/// The exception thrown when a command could not be found.
/// </summary>
[ExcludeFromCodeCoverage]
public class CommandNotFoundException : Exception {
/// <summary>
/// Initializes a new instance of the <see cref="CommandNotFoundException"/> class.
/// </summary>
public CommandNotFoundException() { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandNotFoundException"/> class with the specified message.
/// </summary>
/// <param name="message">The message.</param>
public CommandNotFoundException(string message) : base(message) { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandNotFoundException"/> class with the specified message
/// and inner exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
public CommandNotFoundException(string message, Exception innerException) : base(message, innerException) { }
}
}
46 changes: 46 additions & 0 deletions src/TShock/Commands/Exceptions/CommandParseException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2019 Pryaxis & TShock Contributors
//
// This file is part of TShock.
//
// TShock is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TShock is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TShock. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.Diagnostics.CodeAnalysis;

namespace TShock.Commands.Exceptions {
/// <summary>
/// The exception thrown when a command input cannot be parsed.
/// </summary>
[ExcludeFromCodeCoverage]
public class CommandParseException : Exception {
/// <summary>
/// Initializes a new instance of the <see cref="CommandParseException"/> class.
/// </summary>
public CommandParseException() { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandParseException"/> class with the specified message.
/// </summary>
/// <param name="message">The message.</param>
public CommandParseException(string message) : base(message) { }

/// <summary>
/// Initializes a new instance of the <see cref="CommandParseException"/> class with the specified message and
/// inner exception.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
public CommandParseException(string message, Exception innerException) : base(message, innerException) { }
}
}
Loading