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

minimessage: Unify transformations and placeholders #672

Merged
merged 17 commits into from
Feb 13, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
9 changes: 3 additions & 6 deletions .checkstyle/suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
<suppress files="api[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]Adventure.java" checks="SummaryJavadoc"/>

<!-- no javadoc on test and internal classes -->
<suppress files="src[\\/](test|jmh)[\\/]java[\\/].*" checks="FilteringWriteTag"/>
<suppress files="src[\\/](test|jmh)[\\/]java[\\/].*" checks="JavadocPackage"/>
<suppress files="src[\\/](test|jmh)[\\/]java[\\/].*" checks="MissingJavadoc.*"/>
<suppress files="api[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]internal[\\/].*" checks="FilteringWriteTag"/>
<suppress files="api[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]internal[\\/].*" checks="JavadocPackage"/>
<suppress files="api[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]internal[\\/].*" checks="MissingJavadoc.*"/>
<suppress files="src[\\/](test|jmh)[\\/]java[\\/].*" checks="(FilteringWriteTag|JavadocPackage|MissingJavadoc.*)"/>
<suppress files="api[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]internal[\\/].*" checks="(FilteringWriteTag|JavadocPackage|MissingJavadoc.*)"/>
<suppress files="minimessage[\\/]src[\\/]main[\\/]java[\\/]net[\\/]kyori[\\/]adventure[\\/]text[\\/]minimessage[\\/]parser[\\/].*" checks="(FilteringWriteTag|JavadocPackage|MissingJavadoc.*)"/>

<suppress files=".*[\\/]nbt[\\/](List|Compound)BinaryTag.java" checks="MethodName"/>
</suppressions>
20 changes: 20 additions & 0 deletions api/src/main/java/net/kyori/adventure/util/Index.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,24 @@ private Index(final Map<K, V> keyToValue, final Map<V, K> valueToKey) {
public @Nullable V value(final @NotNull K key) {
return this.keyToValue.get(key);
}

/**
* Get an unmodifiable mapping of index entries from key to value.
*
* @return a mapping from key to value in the index
* @since 4.10.0
*/
public @NotNull Map<K, V> keyToValue() {
return Collections.unmodifiableMap(this.keyToValue);
}

/**
* Get an unmodifiable mapping of index entries from value to key.
*
* @return a mapping from value to key in the index
* @since 4.10.0
*/
public @NotNull Map<V, K> valueToKey() {
return Collections.unmodifiableMap(this.valueToKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
import java.util.concurrent.TimeUnit;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.placeholder.Placeholder;
import net.kyori.adventure.text.minimessage.placeholder.PlaceholderResolver;
import net.kyori.adventure.text.minimessage.tag.Placeholder;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
Expand All @@ -50,7 +49,7 @@ public Component testSimple() {
final String input = "<yellow><test><bold>stranger";
return MiniMessage.miniMessage().deserialize(
input,
PlaceholderResolver.placeholders(Placeholder.component("test", Component.text("test2")))
Placeholder.component("test", Component.text("test2"))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
*/
package net.kyori.adventure.text.minimessage;

import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Parser context for use within transformations.
Expand All @@ -37,19 +41,50 @@
@ApiStatus.NonExtendable
public interface Context {
/**
* Returns original message as provided to the parser.
* Parses a MiniMessage using all the settings of this context, including placeholders.
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
*
* @return ogMessage
* @param message the message to parse
* @return the parsed message
* @since 4.10.0
*/
@NotNull String originalMessage();
@NotNull Component parse(final @NotNull String message);

/**
* Parses a MiniMessage using all the settings of this context, including placeholders.
* Create a new parsing exception.
*
* @param message the message to parse
* @return the parsed message
* @param message the detail message
* @param tags the tag parts which caused the error
* @return the new parsing exception
* @since 4.10.0
*/
@NotNull Component parse(final @NotNull String message);
@NotNull ParsingException newError(
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
final @NotNull String message,
final @NotNull List<? extends Tag.Argument> tags
);

/**
* Create a new parsing exception without reference to a specific location.
*
* @param message the detail message
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
* @return the new parsing exception
* @since 4.10.0
*/
default @NotNull ParsingException newError(final @NotNull String message) {
return this.newError(message, Collections.emptyList());
}

/**
* Create a new parsing exception.
*
* @param message the detail message
* @param cause the cause
* @param tags tag parts that caused the errors
* @return the new parsing exception
* @since 4.10.0
*/
@NotNull ParsingException newError(
final @NotNull String message,
final @Nullable Throwable cause,
final @NotNull List<? extends Tag.Argument> tags
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,18 @@
*/
package net.kyori.adventure.text.minimessage;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.PlaceholderResolver;
import net.kyori.adventure.text.minimessage.parser.ParsingExceptionImpl;
import net.kyori.adventure.text.minimessage.parser.Token;
import net.kyori.adventure.text.minimessage.parser.node.TagPart;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.Tag.Argument;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.util.Objects.requireNonNull;

Expand All @@ -40,24 +47,24 @@
class ContextImpl implements Context {
private final boolean strict;
private final Consumer<String> debugOutput;
private final String originalMessage;
private String message;
private final MiniMessage miniMessage;
private final PlaceholderResolver placeholderResolver;
private final TagResolver tagResolver;
private final UnaryOperator<Component> postProcessor;

ContextImpl(
final boolean strict,
final Consumer<String> debugOutput,
final String originalMessage,
final String message,
final MiniMessage miniMessage,
final @NotNull PlaceholderResolver placeholderResolver,
final @NotNull TagResolver extraTags,
final UnaryOperator<Component> postProcessor
) {
this.strict = strict;
this.debugOutput = debugOutput;
this.originalMessage = originalMessage;
this.message = message;
this.miniMessage = miniMessage;
this.placeholderResolver = placeholderResolver;
this.tagResolver = extraTags;
this.postProcessor = postProcessor == null ? UnaryOperator.identity() : postProcessor;
}

Expand All @@ -66,10 +73,10 @@ static ContextImpl of(
final Consumer<String> debugOutput,
final String input,
final MiniMessageImpl miniMessage,
final PlaceholderResolver placeholderResolver,
final TagResolver extraTags,
final UnaryOperator<Component> postProcessor
) {
return new ContextImpl(strict, debugOutput, input, miniMessage, placeholderResolver, postProcessor);
return new ContextImpl(strict, debugOutput, input, miniMessage, extraTags, postProcessor);
}

public boolean strict() {
Expand All @@ -80,13 +87,16 @@ public Consumer<String> debugOutput() {
return this.debugOutput;
}

@Override
public @NotNull String originalMessage() {
return this.originalMessage;
public @NotNull String message() {
return this.message;
}

void message(final @NotNull String message) {
this.message = message;
}

public @NotNull PlaceholderResolver placeholderResolver() {
return this.placeholderResolver;
public @NotNull TagResolver extraTags() {
return this.tagResolver;
}

public UnaryOperator<Component> postProcessor() {
Expand All @@ -95,6 +105,24 @@ public UnaryOperator<Component> postProcessor() {

@Override
public @NotNull Component parse(final @NotNull String message) {
return this.miniMessage.deserialize(requireNonNull(message, "message"), this.placeholderResolver);
return this.miniMessage.deserialize(requireNonNull(message, "message"), this.tagResolver);
}

@Override
public ParsingException newError(final String message, final @NotNull List<? extends Argument> tags) {
return new ParsingExceptionImpl(message, this.message, tagsToTokens(tags));
}

@Override
public ParsingException newError(final String message, final @Nullable Throwable cause, final @NotNull List<? extends Argument> tags) {
return new ParsingExceptionImpl(message, this.message, cause, tagsToTokens(tags));
}

private static Token[] tagsToTokens(final List<? extends Tag.Argument> tags) {
final Token[] tokens = new Token[tags.size()];
for (int i = 0, length = tokens.length; i < length; i++) {
tokens[i] = ((TagPart) tags.get(i)).token();
}
return tokens;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.placeholder.PlaceholderResolver;
import net.kyori.adventure.text.minimessage.transformation.TransformationRegistry;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.serializer.ComponentSerializer;
import net.kyori.adventure.util.Buildable;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -59,7 +58,7 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
*
* <p>Useful for untrusted input.</p>
*
* <p>Only globally known tokens will be escaped. Use the overload that takes a {@link PlaceholderResolver} if placeholders should be handled.</p>
* <p>Only globally known tokens will be escaped. Use the overload that takes a {@link TagResolver} if any custom tags should be handled.</p>
*
* @param input the input message, with tokens
* @return the output, with escaped tokens
Expand All @@ -73,18 +72,18 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
* <p>Useful for untrusted input.</p>
*
* @param input the input message, with tokens
* @param placeholders the placeholder resolver adding known placeholders
* @param tags a tag resolver to provide any additional tags that can be understood, combined with the overall tag resolver
* @return the output, with escaped tokens
* @since 4.10.0
*/
@NotNull String escapeTokens(final @NotNull String input, final @NotNull PlaceholderResolver placeholders);
@NotNull String escapeTokens(final @NotNull String input, final @NotNull TagResolver tags);
zml2008 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Removes all supported tokens in the input message.
*
* <p>Useful for untrusted input.</p>
*
* <p>Only globally known tokens will be stripped. Use the overload that takes a {@link PlaceholderResolver} if placeholders should be handled.</p>
* <p>Only globally known tokens will be stripped. Use the overload that takes a {@link TagResolver} if any custom tags should be handled.</p>
*
* @param input the input message, with tokens
* @return the output, without tokens
Expand All @@ -98,23 +97,23 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
* <p>Useful for untrusted input.</p>
*
* @param input the input message, with tokens
* @param placeholders the placeholder resolver adding known placeholders
* @param tags a tag resolver to provide any additional tags that can be understood, combined with the overall tag resolver
* @return the output, without tokens
* @since 4.10.0
*/
@NotNull String stripTokens(final @NotNull String input, final @NotNull PlaceholderResolver placeholders);
@NotNull String stripTokens(final @NotNull String input, final @NotNull TagResolver tags);

/**
* Deserializes a string into a component, with a placeholder resolver to parse placeholders of the form {@code <key>}.
*
* <p>Placeholders will be resolved from this resolver before the resolver provided in the builder is used.</p>
* <p>Tags will be resolved from the resolver parameter before the resolver provided in the builder is used.</p>
*
* @param input the input string
* @param placeholderResolver the placeholder resolver
* @param tagResolver the tag resolver for any additional tags to handle.
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
* @return the output component
* @since 4.10.0
*/
@NotNull Component deserialize(final @NotNull String input, final @NotNull PlaceholderResolver placeholderResolver);
@NotNull Component deserialize(final @NotNull String input, final @NotNull TagResolver tagResolver);

/**
* Creates a new {@link MiniMessage.Builder}.
Expand All @@ -134,41 +133,28 @@ static Builder builder() {
interface Builder extends Buildable.Builder<MiniMessage> {

/**
* Uses the supplied transformation registry.
* Set the known tags to the provided tag resolver.
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param transformationRegistry the transformation registry to use
* @param tags the tag resolver to use
* @return this builder
* @since 4.10.0
*/
@NotNull Builder transformations(final @NotNull TransformationRegistry transformationRegistry);
@NotNull Builder tags(final @NotNull TagResolver tags);

/**
* Modify the set transformation registry.
* Add to the set of known tags this MiniMessage instance can use.
zml2008 marked this conversation as resolved.
Show resolved Hide resolved
*
* <p>By default, this will start out with a registry of all default transformations.</p>
*
* @param modifier an action to perform on the registry builder
* @return this builder
* @since 4.10.0
*/
@NotNull Builder transformations(final @NotNull Consumer<TransformationRegistry.Builder> modifier);

/**
* Sets the placeholder resolver.
*
* <p>This placeholder resolver will be used after any placeholder resolved provided in {@link MiniMessage#deserialize(String, PlaceholderResolver)}.</p>
*
* @param placeholderResolver the placeholder resolver to use, if any
* @param adder a function operating on a builder containing currently known tags
* @return this builder
* @since 4.10.0
*/
@NotNull Builder placeholderResolver(final @Nullable PlaceholderResolver placeholderResolver);
@NotNull Builder tags(final @NotNull Consumer<TagResolver.Builder> adder);

/**
* Allows to enable strict mode (disabled by default).
*
* <p>By default, MiniMessage will allow non-{@link net.kyori.adventure.text.minimessage.transformation.Inserting Inserting} tags to be implicitly closed. When strict mode
* is enabled, all non-inserting tags which are {@code <opened>} must be explicitly {@code </closed>} as well.</p>
* <p>By default, MiniMessage will allow {@link net.kyori.adventure.text.minimessage.tag.Tag#allowsChildren() child-allowing} tags to be implicitly closed. When strict mode
* is enabled, all child-allowing tags which are {@code <opened>} must be explicitly {@code </closed>} as well.</p>
*
* @param strict if strict mode should be enabled
* @return this builder
Expand Down
Loading