Compare commits

..

2 commits

Author SHA1 Message Date
slicedlime (Mikael Hedberg)
ed60bb27c8 Use rootian locale for case conversion. 2021-03-18 15:32:47 +01:00
slicedlime (Mikael Hedberg)
b0029617cb Cache lowercase versions of inputs and literals to avoid repeated calls to toLowerCase().
Thank you to Spottedleaf.
2021-03-18 15:11:25 +01:00
16 changed files with 57 additions and 248 deletions

View file

@ -1,51 +0,0 @@
name: $(Rev:r)
trigger:
branches:
include:
- '*'
exclude:
- master
pr:
branches:
include:
- '*'
jobs:
- job: 'Build'
displayName: 'Build for testing'
pool: 'MC-Build-1ES-Azure-Pipeline-Linux'
container: adoptopenjdk/openjdk8:latest
workspace:
clean: all
steps:
- task: Gradle@2
displayName: Build and Test
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
options: '-PbuildNumber=0'
javaHomeOption: 'JDKVersion'
jdkUserInputPath: '/usr/java/openjdk-8'
testResultsFiles: '**/TEST-*.xml'
tasks: 'build test publish'
# This is a workaround for ComponentGovernanceComponentDetection@0 not recognizing the generated `.pom` file(s)
- task: Bash@3
displayName: Copy pom for component governance
inputs:
targetType: 'inline'
script: |
pompath=`find build/repo -name *.pom`
cp "${pompath}" build/pom.xml
- task: ComponentGovernanceComponentDetection@0
inputs:
scanType: 'Register'
verbosity: 'Verbose'
alertWarningLevel: 'High'

View file

@ -1,87 +0,0 @@
name: $(Rev:r)
trigger:
branches:
include:
- master
pr: none
variables:
rConnection: 'mc-java-sc'
storageAccount: 'librariesminecraftnet'
storageAccountContainer: 'librariesminecraftnet'
keyVault: 'mc-java-vault'
jobs:
- job: 'Build'
displayName: 'Build for release'
pool: 'MC-Build-1ES-Azure-Pipeline-Linux'
container: adoptopenjdk/openjdk8:latest
workspace:
clean: all
steps:
- task: Gradle@2
displayName: Build and Test
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
options: '-PbuildNumber=$(Build.BuildNumber)'
javaHomeOption: 'JDKVersion'
jdkUserInputPath: '/usr/java/openjdk-8'
testResultsFiles: '**/TEST-*.xml'
tasks: 'build test publish report'
# This is a workaround for ComponentGovernanceComponentDetection@0 not recognizing the generated `.pom` file(s)
- task: Bash@3
displayName: Copy pom for component governance
inputs:
targetType: 'inline'
script: |
pompath=`find build/repo -name *.pom`
cp "${pompath}" build/pom.xml
- task: ComponentGovernanceComponentDetection@0
inputs:
scanType: 'Register'
verbosity: 'Verbose'
alertWarningLevel: 'High'
- publish: 'build/repo/'
artifact: repo
- job: 'Publish'
displayName: 'Publish release'
dependsOn: Build
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
pool: 'MC-Build-1ES-Azure-Pipeline-Linux'
workspace:
clean: all
steps:
- download: current
artifact: repo
- task: AzureKeyVault@1
displayName: 'Fetching secrets'
name: secrets
inputs:
azureSubscription: '$(rConnection)'
KeyVaultName: '$(keyVault)'
SecretsFilter: 'access-key-prod-librariesminecraftnet'
RunAsPreJob: false
- task: AzureCLI@2
displayName: Azure CLI
inputs:
azureSubscription: '$(rConnection)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
az storage blob upload-batch -s '$(Pipeline.Workspace)/repo' -d $(storageAccountContainer) --account-name $(storageAccount) --account-key $(access-key-prod-librariesminecraftnet)

View file

@ -1,22 +0,0 @@
name: pr-check
on: [ pull_request ]
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
container:
image: adoptopenjdk/openjdk8:latest
steps:
- uses: actions/checkout@v3
- name: Build with Gradle
uses: gradle/gradle-build-action@v2
with:
arguments: build test
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'

17
.travis.yml Normal file
View file

@ -0,0 +1,17 @@
sudo: false
dist: trusty
language: java
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
jdk:
- oraclejdk8
script:
- ./gradlew check --info -S --parallel

View file

@ -38,7 +38,7 @@ And then use this library (change `(the latest version)` to the latest version!)
```
# Contributing
Contributions are welcome! :D
Contributions are welcome ! :D
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.
@ -128,8 +128,8 @@ the reason why is inside this exception map.
## Displaying usage info
There are 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>`].
`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>)`.
`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>)`
[![GitHub forks](https://img.shields.io/github/forks/Mojang/brigadier.svg?style=social&label=Fork)](https://github.com/Mojang/brigadier/fork) [![GitHub stars](https://img.shields.io/github/stars/Mojang/brigadier.svg?style=social&label=Stars)](https://github.com/Mojang/brigadier/stargazers)

View file

@ -1,4 +1,6 @@
import groovy.io.FileType
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider
import com.amazonaws.services.s3.AmazonS3Client
apply plugin: 'java-library'
apply plugin: 'maven-publish'
@ -13,6 +15,10 @@ buildscript {
url "https://libraries.minecraft.net"
}
}
dependencies {
classpath 'com.amazonaws:aws-java-sdk:1.11.33'
}
}
repositories {
@ -80,12 +86,18 @@ publishing {
task report {
doLast {
println "##vso[build.updatebuildnumber]${project.version}"
println "##teamcity[buildNumber '${project.version}']"
}
}
def publishDir = file("$buildDir/repo")
def uploadFile(s3, bucket, path, filename) {
println "Uploading $filename to $bucket as $path"
s3.putObject(bucket, path, filename)
}
clean.doLast {
delete publishDir
}
@ -102,13 +114,14 @@ if (version.endsWith("SNAPSHOT")) {
}
publish.doLast {
def AWSRoleARN = (System.getenv("AWS_ROLE_ARN") != null && System.getenv("AWS_ROLE_ARN") != "" ? System.getenv("AWS_ROLE_ARN") : null)
if (AWSRoleARN == null) throw new GradleException("AWS Role has not been configured, use the `AWS_ROLE_ARN` environment variable")
def auth = new STSAssumeRoleSessionCredentialsProvider.Builder(AWSRoleARN, "JavaBrigadierPublish").build()
def s3 = new AmazonS3Client(auth)
publishDir.eachFileRecurse {
if (!it.isFile()) {
return
}
// Remove junk files
if (it.name.contains(".xml") || it.name.contains(".md5")) {
it.delete()
if (!it.name.contains(".xml") && !it.name.contains(".md5") && it.isFile()) {
def relPath = publishDir.toPath().relativize(it.toPath()).toFile().toString().replaceAll('\\\\', '/')
uploadFile(s3, "minecraft-libraries", relPath, it)
}
}
}

View file

@ -1 +1 @@
majorMinor: 1.1
majorMinor: 1.0

View file

@ -231,6 +231,7 @@ public class CommandDispatcher<S> {
if (child != null) {
forked |= context.isForked();
if (child.hasNodes()) {
foundCommand = true;
final RedirectModifier<S> modifier = context.getRedirectModifier();
if (modifier == null) {
if (next == null) {
@ -247,8 +248,6 @@ public class CommandDispatcher<S> {
for (final S source : results) {
next.add(child.copyFor(source));
}
} else {
foundCommand = true;
}
} catch (final CommandSyntaxException ex) {
consumer.onCommandComplete(context, false, 0);

View file

@ -4,7 +4,6 @@
package com.mojang.brigadier.builder;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.RedirectModifier;
import com.mojang.brigadier.SingleRedirectModifier;
import com.mojang.brigadier.tree.CommandNode;
@ -21,7 +20,6 @@ public abstract class ArgumentBuilder<S, T extends ArgumentBuilder<S, T>> {
private CommandNode<S> target;
private RedirectModifier<S> modifier = null;
private boolean forks;
private Message description;
protected abstract T getThis();
@ -54,15 +52,6 @@ public abstract class ArgumentBuilder<S, T extends ArgumentBuilder<S, T>> {
return command;
}
public T describe(final Message description) {
this.description = description;
return getThis();
}
public Message getDescription() {
return description;
}
public T requires(final Predicate<S> requirement) {
this.requirement = requirement;
return getThis();

View file

@ -28,7 +28,7 @@ public class LiteralArgumentBuilder<S> extends ArgumentBuilder<S, LiteralArgumen
@Override
public LiteralCommandNode<S> build() {
final LiteralCommandNode<S> result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getDescription());
final LiteralCommandNode<S> result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork());
for (final CommandNode<S> argument : getArguments()) {
result.addChild(argument);

View file

@ -45,7 +45,7 @@ public class RequiredArgumentBuilder<S, T> extends ArgumentBuilder<S, RequiredAr
}
public ArgumentCommandNode<S, T> build() {
final ArgumentCommandNode<S, T> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider(), getDescription());
final ArgumentCommandNode<S, T> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider());
for (final CommandNode<S> argument : getArguments()) {
result.addChild(argument);

View file

@ -4,7 +4,6 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.RedirectModifier;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
@ -30,11 +29,7 @@ public class ArgumentCommandNode<S, T> extends CommandNode<S> {
private final SuggestionProvider<S> customSuggestions;
public ArgumentCommandNode(final String name, final ArgumentType<T> type, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks, final SuggestionProvider<S> customSuggestions) {
this(name, type, command, requirement, redirect, modifier, forks, customSuggestions, null);
}
public ArgumentCommandNode(final String name, final ArgumentType<T> type, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks, final SuggestionProvider<S> customSuggestions, final Message description) {
super(command, requirement, redirect, modifier, forks, description);
super(command, requirement, redirect, modifier, forks);
this.name = name;
this.type = type;
this.customSuggestions = customSuggestions;

View file

@ -3,7 +3,10 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.*;
import com.mojang.brigadier.AmbiguityConsumer;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.RedirectModifier;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
@ -19,39 +22,30 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
private Map<String, CommandNode<S>> children = new LinkedHashMap<>();
private Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
private Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
private final Predicate<S> requirement;
private final CommandNode<S> redirect;
private final RedirectModifier<S> modifier;
private final boolean forks;
private Command<S> command;
private Message description;
protected CommandNode(final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks) {
this(command, requirement, redirect, modifier, forks, null);
}
protected CommandNode(final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks, final Message description) {
this.command = command;
this.requirement = requirement;
this.redirect = redirect;
this.modifier = modifier;
this.forks = forks;
this.description = description;
}
public Command<S> getCommand() {
return command;
}
public Message getDescription() {
return description;
}
public Collection<CommandNode<S>> getChildren() {
return children.values();
}
@ -94,6 +88,8 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
arguments.put(node.getName(), (ArgumentCommandNode<S, ?>) node);
}
}
children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
public void findAmbiguities(final AmbiguityConsumer<S> consumer) {

View file

@ -4,7 +4,6 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.RedirectModifier;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
@ -26,11 +25,7 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
private final String literalLowerCase;
public LiteralCommandNode(final String literal, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks) {
this(literal, command, requirement, redirect, modifier, forks, null);
}
public LiteralCommandNode(final String literal, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks, final Message description) {
super(command, requirement, redirect, modifier, forks, description);
super(command, requirement, redirect, modifier, forks);
this.literal = literal;
this.literalLowerCase = literal.toLowerCase(Locale.ROOT);
}

View file

@ -17,7 +17,7 @@ import java.util.concurrent.CompletableFuture;
public class RootCommandNode<S> extends CommandNode<S> {
public RootCommandNode() {
super(null, c -> true, null, s -> Collections.singleton(s.getSource()), false, null);
super(null, c -> true, null, s -> Collections.singleton(s.getSource()), false);
}
@Override

View file

@ -4,7 +4,6 @@
package com.mojang.brigadier;
import com.google.common.collect.Lists;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -15,9 +14,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument;
@ -330,37 +326,6 @@ public class CommandDispatcherTest {
verify(command).run(argThat(hasProperty("source", is(source2))));
}
@Test
public void testIncompleteRedirectShouldThrow() {
final LiteralCommandNode<Object> foo = subject.register(literal("foo")
.then(literal("bar")
.then(argument("value", integer()).executes(context -> IntegerArgumentType.getInteger(context, "value"))))
.then(literal("awa").executes(context -> 2)));
final LiteralCommandNode<Object> baz = subject.register(literal("baz").redirect(foo));
try {
int result = subject.execute("baz bar", source);
fail("Should have thrown an exception");
} catch (CommandSyntaxException e) {
assertThat(e.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()));
}
}
@Test
public void testRedirectModifierEmptyResult() {
final LiteralCommandNode<Object> foo = subject.register(literal("foo")
.then(literal("bar")
.then(argument("value", integer()).executes(context -> IntegerArgumentType.getInteger(context, "value"))))
.then(literal("awa").executes(context -> 2)));
final RedirectModifier<Object> emptyModifier = context -> Collections.emptyList();
final LiteralCommandNode<Object> baz = subject.register(literal("baz").fork(foo, emptyModifier));
try {
int result = subject.execute("baz bar 100", source);
assertThat(result, is(0)); // No commands executed, so result is 0
} catch (CommandSyntaxException e) {
fail("Should not throw an exception");
}
}
@Test
public void testExecuteOrphanedSubcommand() throws Exception {
subject.register(literal("foo").then(