Compare commits
4 commits
master
...
feature/co
Author | SHA1 | Date | |
---|---|---|---|
|
ff0da75678 | ||
|
e54a50f566 | ||
|
7bc3563927 | ||
|
7d201afc7f |
70 changed files with 630 additions and 0 deletions
9
LICENSE
Normal file
9
LICENSE
Normal file
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
133
README.md
Normal file
133
README.md
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Brigadier
|
||||
Brigadier is a command parser & dispatcher, designed and developed for Minecraft: Java Edition and now freely available for use elsewhere under the MIT license.
|
||||
|
||||
# Installation
|
||||
Brigadier is available to Maven & Gradle via `libraries.minecraft.net`. Its group is `com.mojang`, and artifact name is `brigadier`.
|
||||
|
||||
## Gradle
|
||||
First include our repository:
|
||||
```groovy
|
||||
maven {
|
||||
url "https://libraries.minecraft.net"
|
||||
}
|
||||
```
|
||||
|
||||
And then use this library (change `(the latest version)` to the latest version!):
|
||||
```groovy
|
||||
compile 'com.mojang:brigadier:(the latest version)'
|
||||
```
|
||||
|
||||
## Maven
|
||||
First include our repository:
|
||||
```xml
|
||||
<repository>
|
||||
<id>minecraft-libraries</id>
|
||||
<name>Minecraft Libraries</name>
|
||||
<url>https://libraries.minecraft.net</url>
|
||||
</repository>
|
||||
```
|
||||
|
||||
And then use this library (change `(the latest version)` to the latest version!):
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>brigadier</artifactId>
|
||||
<version>(the latest version)</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
# Contributing
|
||||
Contributions are suspended until we have a process in place to handle them.
|
||||
|
||||
Most contributions will require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to,
|
||||
and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
# Usage
|
||||
At the heart of Brigadier, you need a `CommandDispatcher<S>`, where `<S>` is any custom object you choose to identify a "command source".
|
||||
|
||||
A command dispatcher holds a "command tree", which are a series of `CommandNode` which represent the various possible syntax that form a valid command.
|
||||
|
||||
## Registering a new command
|
||||
Before we can start parsing and dispatching commands, we need to build up our command tree. Every registration is an append operation,
|
||||
so you can freely extend existing commands in a project without needing access to the source code that created them.
|
||||
|
||||
Command registration also encourages use of a builder pattern to keep code cruft to a minimum.
|
||||
|
||||
A "command" is a fairly loose term, but typically it means an exit point of the command tree.
|
||||
Every node can have an `executes` function attached to it, which signifies that if the input stops here then this function will be called with the context so far.
|
||||
|
||||
Consider the following example:
|
||||
```java
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher();
|
||||
|
||||
dispatcher.register(
|
||||
literal("foo")
|
||||
.then(
|
||||
argument("bar", integer())
|
||||
.executes(c -> {
|
||||
System.out.println("Bar is " + getInteger(c, "bar"));
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
.executes(c -> {
|
||||
System.out.println("Called foo with no arguments");
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
This snippet registers two "commands": `foo` and `foo <bar>`. It is also common to refer to the `<bar>` as a "subcommand" of `foo`, as it's a child node.
|
||||
|
||||
At the start of the tree is a "root node", and it **must** have `LiteralCommandNode`s as children. Here, we register one command under the root: `literal("foo")`, which means "the user must type the literal string 'foo'".
|
||||
|
||||
Under that is two extra definitions: a child node for possible further evaluation, or an `executes` block if the user input stops here.
|
||||
|
||||
The child node works exactly the same way, but is no longer limited to literals. The other type of node that is now allowed is an `ArgumentCommandNode`, which takes in a name and an argument type.
|
||||
|
||||
Arguments can be anything, and you are encouraged to build your own for seamless integration into your own product. There are some standard arguments included in brigadier, such as `IntegerArgumentType`.
|
||||
|
||||
Argument types will be asked to parse input as much as they can, and then store the "result" of that argument however they see fit or throw a relevant error if they can't parse.
|
||||
|
||||
For example, an integer argument would parse "123" and store it as `123` (`int`), but throw an error if the input were `onetwothree`.
|
||||
|
||||
When a command is actually ran, it can access these arguments in the context provided to the registered function.
|
||||
|
||||
## Parsing user input
|
||||
So, we've registered some commands and now we're ready to take in user input. If you're in a rush, you can just call `dispatcher.execute("foo 123", source)` and call it a day.
|
||||
|
||||
The result of `execute` is an integer returned by the command it evaluated. Its meaning varies depending on command, and typically will not be useful to programmers.
|
||||
|
||||
The `source` is an object of `<S>`, your own custom class to track users/players/etc. It will be provided to the command so that it has some context on what's happening.
|
||||
|
||||
If the command failed or could not parse, some form of `CommandSyntaxException` will be thrown. It is also possible for a `RuntimeException` to be bubbled up, if not properly handled in a command.
|
||||
|
||||
If you wish to have more control over the parsing & executing of commands, or wish to cache the parse results so you can execute it multiple times, you can split it up into two steps:
|
||||
|
||||
```java
|
||||
final ParseResults<S> parse = dispatcher.parse("foo 123", source);
|
||||
final int result = execute(parse);
|
||||
```
|
||||
|
||||
This is highly recommended as the parse step is the most expensive, and may be easily cached depending on your application.
|
||||
|
||||
You can also use this to do further introspection on a command, before (or without) actually running it.
|
||||
|
||||
## Inspecting a command
|
||||
If you `parse` some input, you can find out what it will perform (if anything) and provide hints to the user safely and immediately.
|
||||
|
||||
The parse will never fail, and the `ParseResults<S>` it returns will contain a *possible* context that a command may be called with
|
||||
(and from that, you can inspect which nodes the user entered, complete with start/end positions in the input string).
|
||||
It also contains a map of parse exceptions for each command node it encountered. If it couldn't build a valid context, then
|
||||
the reason why is inside this exception map.
|
||||
|
||||
## Displaying usage info
|
||||
There's two forms of "usage strings" provided by this library, both require a target node.
|
||||
|
||||
`getAllUsage(node, source, restricted)` will return a list of all possible commands (executable end-points) under the target node and their human readable path. If `restricted`, it will ignore commands that `source` does not have access to. This will look like [`foo`, `foo <bar>`]
|
||||
|
||||
`getSmartUsage(node, source)` will return a map of the child nodes to their "smart usage" human readable path. This tries to squash future-nodes together and show optional & typed information, and can look like `foo (<bar>)`
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -26,9 +29,27 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* The core command dispatcher, for registering, parsing, and executing commands.
|
||||
*
|
||||
* @param <S> a custom "source" type, such as a user or originator of a command
|
||||
*/
|
||||
public class CommandDispatcher<S> {
|
||||
/**
|
||||
* The string required to separate individual arguments in an input string
|
||||
*
|
||||
* @see #ARGUMENT_SEPARATOR_CHAR
|
||||
*/
|
||||
public static final String ARGUMENT_SEPARATOR = " ";
|
||||
|
||||
/**
|
||||
* The char required to separate individual arguments in an input string
|
||||
*
|
||||
* @see #ARGUMENT_SEPARATOR
|
||||
*/
|
||||
public static final char ARGUMENT_SEPARATOR_CHAR = ' ';
|
||||
|
||||
private static final String USAGE_OPTIONAL_OPEN = "[";
|
||||
private static final String USAGE_OPTIONAL_CLOSE = "]";
|
||||
private static final String USAGE_REQUIRED_OPEN = "(";
|
||||
|
@ -45,33 +66,144 @@ public class CommandDispatcher<S> {
|
|||
private ResultConsumer<S> consumer = (c, s, r) -> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new {@link CommandDispatcher} with the specified root node.
|
||||
*
|
||||
* <p>This is often useful to copy existing or pre-defined command trees.</p>
|
||||
*
|
||||
* @param root the existing {@link RootCommandNode} to use as the basis for this tree
|
||||
*/
|
||||
public CommandDispatcher(final RootCommandNode<S> root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandDispatcher} with an empty command tree.
|
||||
*/
|
||||
public CommandDispatcher() {
|
||||
this(new RootCommandNode<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for registering new commands.
|
||||
*
|
||||
* <p>This is a shortcut for calling {@link RootCommandNode#addChild(CommandNode)} after building the provided {@code command}.</p>
|
||||
*
|
||||
* <p>As {@link RootCommandNode} can only hold literals, this method will only allow literal arguments.</p>
|
||||
*
|
||||
* @param command a literal argument builder to add to this command tree
|
||||
* @return the node added to this tree
|
||||
*/
|
||||
public LiteralCommandNode<S> register(final LiteralArgumentBuilder<S> command) {
|
||||
final LiteralCommandNode<S> build = command.build();
|
||||
root.addChild(build);
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback to be informed of the result of every command.
|
||||
*
|
||||
* @param consumer the new result consumer to be called
|
||||
*/
|
||||
public void setConsumer(final ResultConsumer<S> consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and executes a given command.
|
||||
*
|
||||
* <p>This is a shortcut to first {@link #parse(StringReader, Object)} and then {@link #execute(ParseResults)}.</p>
|
||||
*
|
||||
* <p>It is recommended to parse and execute as separate steps, as parsing is often the most expensive step, and easiest to cache.</p>
|
||||
*
|
||||
* <p>If this command returns a value, then it successfully executed something. If it could not parse the command, or the execution was a failure,
|
||||
* then an exception will be thrown. Most exceptions will be of type {@link CommandSyntaxException}, but it is possible that a {@link RuntimeException}
|
||||
* may bubble up from the result of a command. The meaning behind the returned result is arbitrary, and will depend
|
||||
* entirely on what command was performed.</p>
|
||||
*
|
||||
* <p>If the command passes through a node that is {@link CommandNode#isFork()} then it will be 'forked'.
|
||||
* A forked command will not bubble up any {@link CommandSyntaxException}s, and the 'result' returned will turn into
|
||||
* 'amount of successful commands executes'.</p>
|
||||
*
|
||||
* <p>After each and any command is ran, a registered callback given to {@link #setConsumer(ResultConsumer)}
|
||||
* will be notified of the result and success of the command. You can use that method to gather more meaningful
|
||||
* results than this method will return, especially when a command forks.</p>
|
||||
*
|
||||
* @param input a command string to parse & execute
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @return a numeric result from a "command" that was performed
|
||||
* @throws CommandSyntaxException if the command failed to parse or execute
|
||||
* @throws RuntimeException if the command failed to execute and was not handled gracefully
|
||||
* @see #parse(String, Object)
|
||||
* @see #parse(StringReader, Object)
|
||||
* @see #execute(ParseResults)
|
||||
* @see #execute(StringReader, Object)
|
||||
*/
|
||||
public int execute(final String input, final S source) throws CommandSyntaxException {
|
||||
return execute(new StringReader(input), source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and executes a given command.
|
||||
*
|
||||
* <p>This is a shortcut to first {@link #parse(StringReader, Object)} and then {@link #execute(ParseResults)}.</p>
|
||||
*
|
||||
* <p>It is recommended to parse and execute as separate steps, as parsing is often the most expensive step, and easiest to cache.</p>
|
||||
*
|
||||
* <p>If this command returns a value, then it successfully executed something. If it could not parse the command, or the execution was a failure,
|
||||
* then an exception will be thrown. Most exceptions will be of type {@link CommandSyntaxException}, but it is possible that a {@link RuntimeException}
|
||||
* may bubble up from the result of a command. The meaning behind the returned result is arbitrary, and will depend
|
||||
* entirely on what command was performed.</p>
|
||||
*
|
||||
* <p>If the command passes through a node that is {@link CommandNode#isFork()} then it will be 'forked'.
|
||||
* A forked command will not bubble up any {@link CommandSyntaxException}s, and the 'result' returned will turn into
|
||||
* 'amount of successful commands executes'.</p>
|
||||
*
|
||||
* <p>After each and any command is ran, a registered callback given to {@link #setConsumer(ResultConsumer)}
|
||||
* will be notified of the result and success of the command. You can use that method to gather more meaningful
|
||||
* results than this method will return, especially when a command forks.</p>
|
||||
*
|
||||
* @param input a command string to parse & execute
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @return a numeric result from a "command" that was performed
|
||||
* @throws CommandSyntaxException if the command failed to parse or execute
|
||||
* @throws RuntimeException if the command failed to execute and was not handled gracefully
|
||||
* @see #parse(String, Object)
|
||||
* @see #parse(StringReader, Object)
|
||||
* @see #execute(ParseResults)
|
||||
* @see #execute(String, Object)
|
||||
*/
|
||||
public int execute(final StringReader input, final S source) throws CommandSyntaxException {
|
||||
final ParseResults<S> parse = parse(input, source);
|
||||
return execute(parse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a given pre-parsed command.
|
||||
*
|
||||
* <p>If this command returns a value, then it successfully executed something. If the execution was a failure,
|
||||
* then an exception will be thrown.
|
||||
* Most exceptions will be of type {@link CommandSyntaxException}, but it is possible that a {@link RuntimeException}
|
||||
* may bubble up from the result of a command. The meaning behind the returned result is arbitrary, and will depend
|
||||
* entirely on what command was performed.</p>
|
||||
*
|
||||
* <p>If the command passes through a node that is {@link CommandNode#isFork()} then it will be 'forked'.
|
||||
* A forked command will not bubble up any {@link CommandSyntaxException}s, and the 'result' returned will turn into
|
||||
* 'amount of successful commands executes'.</p>
|
||||
*
|
||||
* <p>After each and any command is ran, a registered callback given to {@link #setConsumer(ResultConsumer)}
|
||||
* will be notified of the result and success of the command. You can use that method to gather more meaningful
|
||||
* results than this method will return, especially when a command forks.</p>
|
||||
*
|
||||
* @param parse the result of a successful {@link #parse(StringReader, Object)}
|
||||
* @return a numeric result from a "command" that was performed.
|
||||
* @throws CommandSyntaxException if the command failed to parse or execute
|
||||
* @throws RuntimeException if the command failed to execute and was not handled gracefully
|
||||
* @see #parse(String, Object)
|
||||
* @see #parse(StringReader, Object)
|
||||
* @see #execute(String, Object)
|
||||
* @see #execute(StringReader, Object)
|
||||
*/
|
||||
public int execute(final ParseResults<S> parse) throws CommandSyntaxException {
|
||||
if (parse.getReader().canRead()) {
|
||||
if (parse.getExceptions().size() == 1) {
|
||||
|
@ -154,10 +286,64 @@ public class CommandDispatcher<S> {
|
|||
return forked ? successfulForks : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a given command.
|
||||
*
|
||||
* <p>The result of this method can be cached, and it is advised to do so where appropriate. Parsing is often the
|
||||
* most expensive step, and this allows you to essentially "precompile" a command if it will be ran often.</p>
|
||||
*
|
||||
* <p>If the command passes through a node that is {@link CommandNode#isFork()} then the resulting context will be marked as 'forked'.
|
||||
* Forked contexts may contain child contexts, which may be modified by the {@link RedirectModifier} attached to the fork.</p>
|
||||
*
|
||||
* <p>Parsing a command can never fail, you will always be provided with a new {@link ParseResults}.
|
||||
* However, that does not mean that it will always parse into a valid command. You should inspect the returned results
|
||||
* to check for validity. If its {@link ParseResults#getReader()} {@link StringReader#canRead()} then it did not finish
|
||||
* parsing successfully. You can use that position as an indicator to the user where the command stopped being valid.
|
||||
* You may inspect {@link ParseResults#getExceptions()} if you know the parse failed, as it will explain why it could
|
||||
* not find any valid commands. It may contain multiple exceptions, one for each "potential node" that it could have visited,
|
||||
* explaining why it did not go down that node.</p>
|
||||
*
|
||||
* <p>When you eventually call {@link #execute(ParseResults)} with the result of this method, the above error checking
|
||||
* will occur. You only need to inspect it yourself if you wish to handle that yourself.</p>
|
||||
*
|
||||
* @param command a command string to parse
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @return the result of parsing this command
|
||||
* @see #parse(StringReader, Object)
|
||||
* @see #execute(ParseResults)
|
||||
* @see #execute(String, Object)
|
||||
*/
|
||||
public ParseResults<S> parse(final String command, final S source) {
|
||||
return parse(new StringReader(command), source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a given command.
|
||||
*
|
||||
* <p>The result of this method can be cached, and it is advised to do so where appropriate. Parsing is often the
|
||||
* most expensive step, and this allows you to essentially "precompile" a command if it will be ran often.</p>
|
||||
*
|
||||
* <p>If the command passes through a node that is {@link CommandNode#isFork()} then the resulting context will be marked as 'forked'.
|
||||
* Forked contexts may contain child contexts, which may be modified by the {@link RedirectModifier} attached to the fork.</p>
|
||||
*
|
||||
* <p>Parsing a command can never fail, you will always be provided with a new {@link ParseResults}.
|
||||
* However, that does not mean that it will always parse into a valid command. You should inspect the returned results
|
||||
* to check for validity. If its {@link ParseResults#getReader()} {@link StringReader#canRead()} then it did not finish
|
||||
* parsing successfully. You can use that position as an indicator to the user where the command stopped being valid.
|
||||
* You may inspect {@link ParseResults#getExceptions()} if you know the parse failed, as it will explain why it could
|
||||
* not find any valid commands. It may contain multiple exceptions, one for each "potential node" that it could have visited,
|
||||
* explaining why it did not go down that node.</p>
|
||||
*
|
||||
* <p>When you eventually call {@link #execute(ParseResults)} with the result of this method, the above error checking
|
||||
* will occur. You only need to inspect it yourself if you wish to handle that yourself.</p>
|
||||
*
|
||||
* @param command a command string to parse
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @return the result of parsing this command
|
||||
* @see #parse(String, Object)
|
||||
* @see #execute(ParseResults)
|
||||
* @see #execute(String, Object)
|
||||
*/
|
||||
public ParseResults<S> parse(final StringReader command, final S source) {
|
||||
final CommandContextBuilder<S> context = new CommandContextBuilder<>(this, source, 0);
|
||||
return parseNodes(root, command, context);
|
||||
|
@ -253,6 +439,27 @@ public class CommandDispatcher<S> {
|
|||
return new ParseResults<>(contextSoFar, originalReader.getCursor(), originalReader, errors == null ? Collections.emptyMap() : errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all possible executable commands following the given node.
|
||||
*
|
||||
* <p>You may use {@link #getRoot()} as a target to get all usage data for the entire command tree.</p>
|
||||
*
|
||||
* <p>The returned syntax will be in "simple" form: {@code <param>} and {@code literal}. "Optional" nodes will be
|
||||
* listed as multiple entries: the parent node, and the child nodes.
|
||||
* For example, a required literal "foo" followed by an optional param "int" will be two nodes:</p>
|
||||
* <ul>
|
||||
* <li>{@code foo}</li>
|
||||
* <li>{@code foo <int>}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The path to the specified node will <b>not</b> be prepended to the output, as there can theoretically be many
|
||||
* ways to reach a given node. It will only give you paths relative to the specified node, not absolute from root.</p>
|
||||
*
|
||||
* @param node target node to get child usage strings for
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @param restricted if true, commands that the {@code source} cannot access will not be mentioned
|
||||
* @return array of full usage strings under the target node
|
||||
*/
|
||||
public String[] getAllUsage(final CommandNode<S> node, final S source, final boolean restricted) {
|
||||
final ArrayList<String> result = Lists.newArrayList();
|
||||
getAllUsage(node, source, result, "", restricted);
|
||||
|
@ -278,6 +485,27 @@ public class CommandDispatcher<S> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the possible executable commands from a specified node.
|
||||
*
|
||||
* <p>You may use {@link #getRoot()} as a target to get usage data for the entire command tree.</p>
|
||||
*
|
||||
* <p>The returned syntax will be in "smart" form: {@code <param>}, {@code literal}, {@code [optional]} and {@code (either|or)}.
|
||||
* These forms may be mixed and matched to provide as much information about the child nodes as it can, without being too verbose.
|
||||
* For example, a required literal "foo" followed by an optional param "int" can be compressed into one string:</p>
|
||||
* <ul>
|
||||
* <li>{@code foo [<int>]}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The path to the specified node will <b>not</b> be prepended to the output, as there can theoretically be many
|
||||
* ways to reach a given node. It will only give you paths relative to the specified node, not absolute from root.</p>
|
||||
*
|
||||
* <p>The returned usage will be restricted to only commands that the provided {@code source} can use.</p>
|
||||
*
|
||||
* @param node target node to get child usage strings for
|
||||
* @param source a custom "source" object, usually representing the originator of this command
|
||||
* @return array of full usage strings under the target node
|
||||
*/
|
||||
public Map<CommandNode<S>, String> getSmartUsage(final CommandNode<S> node, final S source) {
|
||||
final Map<CommandNode<S>, String> result = Maps.newLinkedHashMap();
|
||||
|
||||
|
@ -345,6 +573,21 @@ public class CommandDispatcher<S> {
|
|||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets suggestions for a parsed input string on what comes next.
|
||||
*
|
||||
* <p>As it is ultimately up to custom argument types to provide suggestions, it may be an asynchronous operation,
|
||||
* for example getting in-game data or player names etc. As such, this method returns a future and no guarantees
|
||||
* are made to when or how the future completes.</p>
|
||||
*
|
||||
* <p>The suggestions provided will be in the context of the end of the parsed input string, but may suggest
|
||||
* new or replacement strings for earlier in the input string. For example, if the end of the string was
|
||||
* {@code foobar} but an argument preferred it to be {@code minecraft:foobar}, it will suggest a replacement for that
|
||||
* whole segment of the input.</p>
|
||||
*
|
||||
* @param parse the result of a {@link #parse(StringReader, Object)}
|
||||
* @return a future that will eventually resolve into a {@link Suggestions} object
|
||||
*/
|
||||
public CompletableFuture<Suggestions> getCompletionSuggestions(final ParseResults<S> parse) {
|
||||
final CommandContextBuilder<S> rootContext = parse.getContext();
|
||||
final CommandContextBuilder<S> context = rootContext.getLastChild();
|
||||
|
@ -394,10 +637,33 @@ public class CommandDispatcher<S> {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the root of this command tree.
|
||||
*
|
||||
* <p>This is often useful as a target of a {@link com.mojang.brigadier.builder.ArgumentBuilder#redirect(CommandNode)},
|
||||
* {@link #getAllUsage(CommandNode, Object, boolean)} or {@link #getSmartUsage(CommandNode, Object)}.
|
||||
* You may also use it to clone the command tree via {@link #CommandDispatcher(RootCommandNode)}.</p>
|
||||
*
|
||||
* @return root of the command tree
|
||||
*/
|
||||
public RootCommandNode<S> getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a valid path to a given node on the command tree.
|
||||
*
|
||||
* <p>There may theoretically be multiple paths to a node on the tree, especially with the use of forking or redirecting.
|
||||
* As such, this method makes no guarantees about which path it finds. It will not look at forks or redirects,
|
||||
* and find the first instance of the target node on the tree.</p>
|
||||
*
|
||||
* <p>The only guarantee made is that for the same command tree and the same version of this library, the result of
|
||||
* this method will <b>always</b> be a valid input for {@link #findNode(Collection)}, which should return the same node
|
||||
* as provided to this method.</p>
|
||||
*
|
||||
* @param target the target node you are finding a path for
|
||||
* @return a path to the resulting node, or an empty list if it was not found
|
||||
*/
|
||||
public Collection<String> getPath(final CommandNode<S> target) {
|
||||
final List<List<CommandNode<S>>> nodes = new ArrayList<>();
|
||||
addPaths(root, nodes, new ArrayList<>());
|
||||
|
@ -417,6 +683,17 @@ public class CommandDispatcher<S> {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a node by its path
|
||||
*
|
||||
* <p>Paths may be generated with {@link #getPath(CommandNode)}, and are guaranteed (for the same tree, and the
|
||||
* same version of this library) to always produce the same valid node by this method.</p>
|
||||
*
|
||||
* <p>If a node could not be found at the specified path, then {@code null} will be returned.</p>
|
||||
*
|
||||
* @param path a generated path to a node
|
||||
* @return the node at the given path, or null if not found
|
||||
*/
|
||||
public CommandNode<S> findNode(final Collection<String> path) {
|
||||
CommandNode<S> node = root;
|
||||
for (final String name : path) {
|
||||
|
@ -428,6 +705,16 @@ public class CommandDispatcher<S> {
|
|||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the command tree for potential ambiguous commands.
|
||||
*
|
||||
* <p>This is a shortcut for {@link CommandNode#findAmbiguities(AmbiguityConsumer)} on {@link #getRoot()}.</p>
|
||||
*
|
||||
* <p>Ambiguities are detected by testing every {@link CommandNode#getExamples()} on one node verses every sibling
|
||||
* node. This is not fool proof, and relies a lot on the providers of the used argument types to give good examples.</p>
|
||||
*
|
||||
* @param consumer a callback to be notified of potential ambiguities
|
||||
*/
|
||||
public void findAmbiguities(final AmbiguityConsumer<S> consumer) {
|
||||
root.findAmbiguities(consumer);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
public interface ImmutableStringReader {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
public class LiteralMessage implements Message {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
public interface Message {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import java.util.Objects;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
public interface BuiltInExceptionProvider {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.LiteralMessage;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
public interface CommandExceptionType {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.ImmutableStringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.mojang.brigadier.Message;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.benchmarks;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.benchmarks;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.builder;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.context;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.LiteralMessage;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.exceptions;
|
||||
|
||||
import com.mojang.brigadier.LiteralMessage;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.mojang.brigadier.context.StringRange;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.suggestion;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.mojang.brigadier.tree;
|
||||
|
||||
import com.google.common.testing.EqualsTester;
|
||||
|
|
Loading…
Reference in a new issue