Skip to content

Commit

Permalink
Merge pull request #1051 from KyoriPowered/feature/minimessage-target
Browse files Browse the repository at this point in the history
feat(minimessage): Add target to deserialization for contextual tags
  • Loading branch information
kezz authored Mar 19, 2024
2 parents 72ad416 + a45c4db commit 720b5cf
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package net.kyori.adventure.text.minimessage;

import net.kyori.adventure.pointer.Pointered;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
Expand All @@ -40,6 +41,40 @@
@ApiStatus.NonExtendable
public interface Context {

/**
* The target of the parse context, if provided.
* Can be used for tags that provide information relating to the target of the resulting message.
*
* @return the target, if provided
* @since 4.17.0
*/
public @Nullable Pointered target();

/**
* The target of the parse context.
* Can be used for tags that provide information relating to the target of the resulting message.
*
* <p>If the caller did not provide a target, a parse exception is thrown with a default message.</p>
*
* @return the target, if provided
* @since 4.17.0
*/
public @NotNull Pointered targetOrThrow();

/**
* The target of the parse context, casted to a provided type.
* Can be used for tags that provide information relating to the target of the resulting message.
*
* <p>If the caller did not provide a target, or the target is not of the provided type, a parse
* exception is thrown with a default message.</p>
*
* @param <T> the required type
* @param targetClass the class of the required type
* @return the target
* @since 4.17.0
*/
public <T extends Pointered> @NotNull T targetAsType(final @NotNull Class<T> targetClass);

/**
* Deserializes a MiniMessage string using all the settings of this context.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.List;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import net.kyori.adventure.pointer.Pointered;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl;
import net.kyori.adventure.text.minimessage.internal.parser.Token;
Expand All @@ -51,6 +52,7 @@ class ContextImpl implements Context {
private final Consumer<String> debugOutput;
private String message;
private final MiniMessage miniMessage;
private final @Nullable Pointered target;
private final TagResolver tagResolver;
private final UnaryOperator<String> preProcessor;
private final UnaryOperator<Component> postProcessor;
Expand All @@ -60,31 +62,21 @@ class ContextImpl implements Context {
final Consumer<String> debugOutput,
final String message,
final MiniMessage miniMessage,
final @NotNull TagResolver extraTags,
final UnaryOperator<String> preProcessor,
final UnaryOperator<Component> postProcessor
final @Nullable Pointered target,
final @Nullable TagResolver extraTags,
final @Nullable UnaryOperator<String> preProcessor,
final @Nullable UnaryOperator<Component> postProcessor
) {
this.strict = strict;
this.debugOutput = debugOutput;
this.message = message;
this.miniMessage = miniMessage;
this.tagResolver = extraTags;
this.target = target;
this.tagResolver = extraTags == null ? TagResolver.empty() : extraTags;
this.preProcessor = preProcessor == null ? UnaryOperator.identity() : preProcessor;
this.postProcessor = postProcessor == null ? UnaryOperator.identity() : postProcessor;
}

static ContextImpl of(
final boolean strict,
final Consumer<String> debugOutput,
final String input,
final MiniMessageImpl miniMessage,
final TagResolver extraTags,
final UnaryOperator<String> preProcessor,
final UnaryOperator<Component> postProcessor
) {
return new ContextImpl(strict, debugOutput, input, miniMessage, extraTags, preProcessor, postProcessor);
}

public boolean strict() {
return this.strict;
}
Expand Down Expand Up @@ -113,6 +105,29 @@ public UnaryOperator<String> preProcessor() {
return this.preProcessor;
}

@Override
public @Nullable Pointered target() {
return this.target;
}

@Override
public @NotNull Pointered targetOrThrow() {
if (this.target == null) {
throw this.newException("A target is required for this deserialization attempt");
} else {
return this.target;
}
}

@Override
public <T extends Pointered> @NotNull T targetAsType(final @NotNull Class<T> targetClass) {
if (requireNonNull(targetClass, "targetClass").isInstance(this.target)) {
return targetClass.cast(this.target);
} else {
throw this.newException("A target with type " + targetClass.getSimpleName() + " is required for this deserialization attempt");
}
}

@Override
public @NotNull Component deserialize(final @NotNull String message) {
return this.miniMessage.deserialize(requireNonNull(message, "message"), this.tagResolver);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import net.kyori.adventure.builder.AbstractBuilder;
import net.kyori.adventure.pointer.Pointered;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.kyori.adventure.text.minimessage.tree.Node;
Expand Down Expand Up @@ -132,6 +133,16 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
return this.stripTags(input, TagResolver.resolver(tagResolvers));
}

/**
* Deserializes a string into a component, with a target.
*
* @param input the input string
* @param target the target of the deserialization
* @return the output component
* @since 4.17.0
*/
@NotNull Component deserialize(final @NotNull String input, final @NotNull Pointered target);

/**
* Deserializes a string into a component, with a tag resolver to parse tags of the form {@code <key>}.
*
Expand All @@ -145,7 +156,20 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
@NotNull Component deserialize(final @NotNull String input, final @NotNull TagResolver tagResolver);

/**
* Deserializes a string into a component, with a tag resolver to parse tags of the form {@code <key>}.
* Deserializes a string into a component, with a tag resolver to parse tags of the form {@code <key>} and a target.
*
* <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 target the target of the deserialization
* @param tagResolver the tag resolver for any additional tags to handle
* @return the output component
* @since 4.17.0
*/
@NotNull Component deserialize(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver tagResolver);

/**
* Deserializes a string into a component, with tag resolvers to parse tags of the form {@code <key>}.
*
* <p>Tags will be resolved from the resolver parameters before the resolver provided in the builder is used.</p>
*
Expand All @@ -159,7 +183,22 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
}

/**
* Deserializes a string into a tree of parsed elements,
* Deserializes a string into a component, with tag resolvers to parse tags of the form {@code <key>} and a target.
*
* <p>Tags will be resolved from the resolver parameters before the resolver provided in the builder is used.</p>
*
* @param input the input string
* @param target the target of the deserialization
* @param tagResolvers a series of tag resolvers to apply extra tags from, last specified taking priority
* @return the output component
* @since 4.17.0
*/
default @NotNull Component deserialize(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver... tagResolvers) {
return this.deserialize(input, target, TagResolver.resolver(tagResolvers));
}

/**
* Deserializes a string into a tree of parsed elements.
* This is intended for inspecting the output of the parser for debugging purposes.
*
* @param input the input string
Expand All @@ -168,6 +207,17 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
*/
Node.@NotNull Root deserializeToTree(final @NotNull String input);

/**
* Deserializes a string into a tree of parsed elements, with a target.
* This is intended for inspecting the output of the parser for debugging purposes.
*
* @param input the input string
* @param target the target of the deserialization
* @return the root of the resulting tree
* @since 4.17.0
*/
Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull Pointered target);

/**
* Deserializes a string into a tree of parsed elements, with a tag resolver to parse tags of the form {@code <key>}.
* This is intended for inspecting the output of the parser for debugging purposes.
Expand All @@ -181,6 +231,20 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
*/
Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull TagResolver tagResolver);

/**
* Deserializes a string into a tree of parsed elements, with a tag resolver to parse tags of the form {@code <key>} and a target.
* This is intended for inspecting the output of the parser for debugging purposes.
*
* <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 target the target of the deserialization
* @param tagResolver the tag resolver for any additional tags to handle
* @return the root of the resulting tree
* @since 4.17.0
*/
Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver tagResolver);

/**
* Deserializes a string into a tree of parsed elements, with a tag resolver to parse tags of the form {@code <key>}.
* This is intended for inspecting the output of the parser for debugging purposes.
Expand All @@ -196,6 +260,22 @@ public interface MiniMessage extends ComponentSerializer<Component, Component, S
return this.deserializeToTree(input, TagResolver.resolver(tagResolvers));
}

/**
* Deserializes a string into a tree of parsed elements, with a tag resolver to parse tags of the form {@code <key>}.
* This is intended for inspecting the output of the parser for debugging purposes.
*
* <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 target the target of the deserialization
* @param tagResolvers a series of tag resolvers to apply extra tags from, last specified taking priority
* @return the root of the resulting tree
* @since 4.17.0
*/
default Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver... tagResolvers) {
return this.deserializeToTree(input, target, TagResolver.resolver(tagResolvers));
}

/**
* Returns if this MiniMessage instance is in strict mode.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import net.kyori.adventure.pointer.Pointered;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.internal.serializer.SerializableResolver;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
Expand Down Expand Up @@ -76,22 +77,42 @@ static final class Instances {

@Override
public @NotNull Component deserialize(final @NotNull String input) {
return this.parser.parseFormat(this.newContext(input, null));
return this.parser.parseFormat(this.newContext(input, null, null));
}

@Override
public @NotNull Component deserialize(final @NotNull String input, final @NotNull Pointered target) {
return this.parser.parseFormat(this.newContext(input, requireNonNull(target, "target"), null));
}

@Override
public @NotNull Component deserialize(final @NotNull String input, final @NotNull TagResolver tagResolver) {
return this.parser.parseFormat(this.newContext(input, requireNonNull(tagResolver, "tagResolver")));
return this.parser.parseFormat(this.newContext(input, null, requireNonNull(tagResolver, "tagResolver")));
}

@Override
public @NotNull Component deserialize(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver tagResolver) {
return this.parser.parseFormat(this.newContext(input, requireNonNull(target, "target"), requireNonNull(tagResolver, "tagResolver")));
}

@Override
public Node.@NotNull Root deserializeToTree(final @NotNull String input) {
return this.parser.parseToTree(this.newContext(input, null));
return this.parser.parseToTree(this.newContext(input, null, null));
}

@Override
public Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull Pointered target) {
return this.parser.parseToTree(this.newContext(input, requireNonNull(target, "target"), null));
}

@Override
public Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull TagResolver tagResolver) {
return this.parser.parseToTree(this.newContext(input, requireNonNull(tagResolver, "tagResolver")));
return this.parser.parseToTree(this.newContext(input, null, requireNonNull(tagResolver, "tagResolver")));
}

@Override
public Node.@NotNull Root deserializeToTree(final @NotNull String input, final @NotNull Pointered target, final @NotNull TagResolver tagResolver) {
return this.parser.parseToTree(this.newContext(input, requireNonNull(target, "target"), requireNonNull(tagResolver, "tagResolver")));
}

@Override
Expand All @@ -116,22 +137,22 @@ private SerializableResolver serialResolver(final @Nullable TagResolver extraRes

@Override
public @NotNull String escapeTags(final @NotNull String input) {
return this.parser.escapeTokens(this.newContext(input, null));
return this.parser.escapeTokens(this.newContext(input, null, null));
}

@Override
public @NotNull String escapeTags(final @NotNull String input, final @NotNull TagResolver tagResolver) {
return this.parser.escapeTokens(this.newContext(input, tagResolver));
return this.parser.escapeTokens(this.newContext(input, null, tagResolver));
}

@Override
public @NotNull String stripTags(final @NotNull String input) {
return this.parser.stripTokens(this.newContext(input, null));
return this.parser.stripTokens(this.newContext(input, null, null));
}

@Override
public @NotNull String stripTags(final @NotNull String input, final @NotNull TagResolver tagResolver) {
return this.parser.stripTokens(this.newContext(input, tagResolver));
return this.parser.stripTokens(this.newContext(input, null, tagResolver));
}

@Override
Expand All @@ -144,13 +165,9 @@ public boolean strict() {
return this.parser.tagResolver;
}

private @NotNull ContextImpl newContext(final @NotNull String input, final @Nullable TagResolver resolver) {
private @NotNull ContextImpl newContext(final @NotNull String input, final @Nullable Pointered target, final @Nullable TagResolver resolver) {
requireNonNull(input, "input");
if (resolver == null) {
return ContextImpl.of(this.strict, this.debugOutput, input, this, TagResolver.empty(), this.preProcessor, this.postProcessor);
} else {
return ContextImpl.of(this.strict, this.debugOutput, input, this, resolver, this.preProcessor, this.postProcessor);
}
return new ContextImpl(this.strict, this.debugOutput, input, this, target, resolver, this.preProcessor, this.postProcessor);
}

static final class BuilderImpl implements Builder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected final String prettyPrint(final Component component) {
}

public static Context dummyContext(final String originalMessage) {
return ContextImpl.of(false, null, originalMessage, (MiniMessageImpl) PARSER, TagResolver.empty(), UnaryOperator.identity(), Component::compact);
return new ContextImpl(false, null, originalMessage, PARSER, null, TagResolver.empty(), UnaryOperator.identity(), Component::compact);
}

public static ArgumentQueue emptyArgumentQueue(final Context context) {
Expand Down
Loading

0 comments on commit 720b5cf

Please sign in to comment.