Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SuggestionsBuilder.getRemainingLowerCase() does not work correctly for Unicode special casing rules #92

Open
Marcono1234 opened this issue May 4, 2021 · 0 comments

Comments

@Marcono1234
Copy link

Marcono1234 commented May 4, 2021

Version

1.0.18

Description

This is basically what has been raised as concern in #86 (comment)

The current SuggestionsBuilder code does not correctly handle cases where after lowercasing the string, the length respectively the character indices change.
For language-insensitive conversion (Locale.ROOT) this can currently only occur for İ (U+0130; "Latin Capital Letter I with Dot Above"), see also Unicode Special Casing (but it could affect more code points in the future).

The effect of this is that command nodes and argument types which use SuggestionsBuilder.getRemainingLowerCase() fail to provide command suggestions.
Affected built-in command nodes / argument types:

  • LiteralCommandNode
  • BoolArgumentType

Possible solutions

Manually trying to map between the source and the lowercased string is probably rather difficult, if not impossible.
Instead an alternative might be to use one of the Character methods for lowercasing (toLowerCase(char) or toLowerCase(int)), which maintain a 1:1 relationship. However, that would require manually going through all characters / code points and converting them which is very likely less performant than the String.toLowerCase methods.

Example (Minecraft)

Version: 21w17a

Type in chat:

/execute as @e[name="İ"] 

❌ Notice how no suggestions are shown

Example (code)

public class BrigadierTest {
    public static void main(String[] args) throws CommandSyntaxException {
        List<CommandDispatcher<Object>> dispatchers = Arrays.asList(createWithLiteral(), createWithBool());
        for (CommandDispatcher<Object> dispatcher : dispatchers) {
            for (String s : Arrays.asList("'!'", "'\u0130'")) {
                ParseResults<Object> parseResults = dispatcher.parse("command " + s + " ", null);
                System.out.println(s + ": " + dispatcher.getCompletionSuggestions(parseResults).join());
            }
        }
    }

    private static CommandDispatcher<Object> createWithLiteral() {
        CommandDispatcher<Object> dispatcher = new CommandDispatcher<>();
        dispatcher.register(LiteralArgumentBuilder.literal("command")
                .then(RequiredArgumentBuilder.argument("first", StringArgumentType.string()).executes(c -> {
                    return 1;
                }).then(LiteralArgumentBuilder.literal("second")).executes(c -> {
                    return 1;
                })));
        return dispatcher;
    }

    private static CommandDispatcher<Object> createWithBool() {
        CommandDispatcher<Object> dispatcher = new CommandDispatcher<>();
        dispatcher.register(LiteralArgumentBuilder.literal("command")
                .then(RequiredArgumentBuilder.argument("first", StringArgumentType.string()).executes(c -> {
                    return 1;
                }).then(RequiredArgumentBuilder.argument("second", BoolArgumentType.bool()).executes(c -> {
                    return 1;
                }))));
        return dispatcher;
    }
}

❌ When the first argument contains İ (\u0130) CommandDispatcher does not provide any suggestions

@Marcono1234 Marcono1234 changed the title SuggestionsBuilder.getRemainingLowerCase() does not work correctly when string length changes SuggestionsBuilder.getRemainingLowerCase() does not work correctly for Unicode special casing rules May 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant