From a8048d2236f41db19df39cfaacd37a5722875805 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 07:15:08 -0800 Subject: [PATCH 1/9] CondExprIsEmpty - set priority higher than CondCompare - This prevents comparing a list to an object named "empty" --- .../syst3ms/skriptparser/expressions/CondExprIsEmpty.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java index 4434b2ac..4556aa0d 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java @@ -28,6 +28,9 @@ public class CondExprIsEmpty extends ConditionalExpression { .examples("if {_list::*} is empty:", "if {_string} is not empty:") .since("1.0.0") + .setPriority(1) + // Higher priority than CondExprContains(0) + // This prevents trying to compare to an object named "empty" .register(); } From 9918cc0bad3d48c8c9251841a37ca8f6b9dea618 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 08:04:33 -0800 Subject: [PATCH 2/9] Improve structure registration --- .../skriptparser/parsing/SyntaxParser.java | 2 +- .../registration/SkriptRegistration.java | 139 +++++++++++++++++- .../registration/StructureInfo.java | 23 +++ .../registration/SyntaxManager.java | 13 +- .../structures/functions/StructFunction.java | 2 +- 5 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 src/main/java/io/github/syst3ms/skriptparser/registration/StructureInfo.java diff --git a/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java b/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java index d40a4fdc..70c17c41 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java +++ b/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java @@ -701,7 +701,7 @@ private static Optional matchSectionInfo(FileSection sect public static Optional parseTrigger(FileSection section, SkriptLogger logger) { if (section.getLineContent().isEmpty()) return Optional.empty(); - for (var info : recentEvents.mergeWith(SyntaxManager.getEvents())) { + for (var info : recentEvents.mergeWith(SyntaxManager.getTriggers())) { var trigger = matchEventInfo(section, info, logger); if (trigger.isPresent()) { recentEvents.acknowledge(info); diff --git a/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java b/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java index dd5f3557..d4e764df 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java +++ b/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java @@ -4,6 +4,7 @@ import io.github.syst3ms.skriptparser.lang.CodeSection; import io.github.syst3ms.skriptparser.lang.Effect; import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.Structure; import io.github.syst3ms.skriptparser.lang.SyntaxElement; import io.github.syst3ms.skriptparser.lang.TriggerContext; import io.github.syst3ms.skriptparser.lang.base.ContextExpression; @@ -77,6 +78,7 @@ public class SkriptRegistration { private final List> converters = new ArrayList<>(); private final List> tags = new ArrayList<>(); private final List> events = new ArrayList<>(); + private final List> structures = new ArrayList<>(); protected final List> types = new ArrayList<>(); private final SkriptAddon registerer; private final SkriptLogger logger; @@ -130,6 +132,13 @@ public List> getEvents() { return events; } + /** + * @return All currently registered structures + */ + public List> getStructures() { + return this.structures; + } + /** * @return all currently registered types */ @@ -424,6 +433,18 @@ public EventRegistrar newEvent(Class c, String... return new EventRegistrar<>(c, patterns); } + /** + * Starts a registration process for a {@link Structure} + * + * @param c the Structure's class + * @param patterns the Structure's patterns + * @param the Structure + * @return an {@link EventRegistrar} to continue the registration process + */ + public StructureRegistrar newStructure(Class c, String... patterns) { + return new StructureRegistrar<>(c, patterns); + } + /** * Registers a {@link SkriptEvent} * @@ -719,7 +740,8 @@ public class TypeRegistrar implements Registrar { private final String baseName; private final String pattern; private Function toStringFunction = o -> Objects.toString(o, TypeManager.NULL_REPRESENTATION); - @Nullable private Function toVariableNameFunction; + @Nullable + private Function toVariableNameFunction; @Nullable private Function literalParser; @Nullable @@ -1069,6 +1091,121 @@ public void register() { } } + public class StructureRegistrar extends SyntaxRegistrar { + private Set> handledContexts = new HashSet<>(); + private final Documentation documentation = new Documentation(); + + StructureRegistrar(Class c, String... patterns) { + super(c, patterns); + this.documentation.setName(c.getSimpleName()); // Dummy name if not specified + typeCheck(); + } + + /** + * Set the contexts this structure can handle + * + * @param contexts the contexts + * @return The registrar + */ + @SafeVarargs + public final StructureRegistrar setHandledContexts(Class... contexts) { + this.handledContexts = Set.of(contexts); + return this; + } + + /** + * Prevent documentation generation for this structure. + * + * @return The registrar + */ + public final StructureRegistrar noDoc() { + this.documentation.noDoc(); + return this; + } + + /** + * Mark this structure as experimental for documentation. + * + * @return The registrar + */ + public final StructureRegistrar experimental() { + this.documentation.experimental(); + return this; + } + + /** + * Mark this structure as experimental with a custom message for documentation. + * + * @param message The custom message + * @return The registrar + */ + public final StructureRegistrar experimental(String message) { + this.documentation.experimental(message); + return this; + } + + /** + * The name of this structure for documentation. + * + * @param name Name of the structure + * @return The registrar + */ + public final StructureRegistrar name(String name) { + this.documentation.setName(name); + return this; + } + + /** + * The description of this structure for documentation. + * + * @param description The description of the structure + * @return The registrar + */ + public final StructureRegistrar description(String... description) { + this.documentation.setDescription(description); + return this; + } + + /** + * Examples of this structure for documentation. + * + * @param examples The examples of the structure + * @return The registrar + */ + public final StructureRegistrar examples(String... examples) { + this.documentation.setExamples(examples); + return this; + } + + /** + * The version this was added in for documentation. + * + * @param since The version this was added in + * @return The registrar + */ + public final StructureRegistrar since(String since) { + this.documentation.setSince(since); + return this; + } + + /** + * Adds this structure to the list of currently registered syntaxes + */ + @Override + public void register() { + for (int i = 0; i < super.patterns.size(); i++) { + var pattern = super.patterns.get(i); + if (pattern.startsWith("*")) { + super.patterns.set(i, pattern.substring(1)); + } else { + super.patterns.set(i, pattern); + } + } + structures.add(new StructureInfo<>(registerer, super.c, handledContexts, priority, parsePatterns(), this.documentation, data)); + registerer.addHandledEvent(this.c); + } + } + public class ContextValueRegistrar implements Registrar { private final Class context; private final Class returnType; diff --git a/src/main/java/io/github/syst3ms/skriptparser/registration/StructureInfo.java b/src/main/java/io/github/syst3ms/skriptparser/registration/StructureInfo.java new file mode 100644 index 00000000..1151ab9c --- /dev/null +++ b/src/main/java/io/github/syst3ms/skriptparser/registration/StructureInfo.java @@ -0,0 +1,23 @@ +package io.github.syst3ms.skriptparser.registration; + +import io.github.syst3ms.skriptparser.docs.Documentation; +import io.github.syst3ms.skriptparser.lang.Structure; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.pattern.PatternElement; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A class containing info about a {@link Structure} syntax + * + * @param the {@link Structure} class + */ +public class StructureInfo extends SkriptEventInfo { + + public StructureInfo(SkriptAddon registerer, Class c, Set> handledContexts, int priority, List patterns, Documentation documentation, Map data) { + super(registerer, c, handledContexts, priority, patterns, documentation, data); + } + +} diff --git a/src/main/java/io/github/syst3ms/skriptparser/registration/SyntaxManager.java b/src/main/java/io/github/syst3ms/skriptparser/registration/SyntaxManager.java index 377fdf83..205b0d2e 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/registration/SyntaxManager.java +++ b/src/main/java/io/github/syst3ms/skriptparser/registration/SyntaxManager.java @@ -11,6 +11,7 @@ import java.util.Optional; public class SyntaxManager { + /** * The ordering describing the order in which syntaxes should be tested during parsing */ @@ -32,6 +33,7 @@ static void register(SkriptRegistration reg) { sections.addAll(reg.getSections()); sections.sort(INFO_COMPARATOR); triggers.addAll(reg.getEvents()); + triggers.addAll(reg.getStructures()); triggers.sort(INFO_COMPARATOR); for (var entry : reg.getExpressions().entrySet()) { var key = entry.getKey(); @@ -53,8 +55,8 @@ static void register(SkriptRegistration reg) { /** * @param expr the expression instance - * @param the expression class - * @param the expression return type + * @param the expression class + * @param the expression return type * @return the {@link ExpressionInfo} corresponding to the given {@link Expression} instance */ @SuppressWarnings("unchecked") @@ -83,9 +85,12 @@ public static List> getEffects() { } /** - * @return a list of all currently registered events + * Get all currently registered triggers (events/structures). + * + * @return a list of all currently registered triggers (events/structures) */ - public static List> getEvents() { + public static List> getTriggers() { return triggers; } + } diff --git a/src/main/java/io/github/syst3ms/skriptparser/structures/functions/StructFunction.java b/src/main/java/io/github/syst3ms/skriptparser/structures/functions/StructFunction.java index 801946e8..85767da1 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/structures/functions/StructFunction.java +++ b/src/main/java/io/github/syst3ms/skriptparser/structures/functions/StructFunction.java @@ -16,7 +16,7 @@ public class StructFunction extends Structure { static { Parser.getMainRegistration() - .newEvent(StructFunction.class, "*[:local[ ]] func[tion] <" + Functions.FUNCTION_NAME_REGEX + ">" + + .newStructure(StructFunction.class, "*[:local[ ]] func[tion] <" + Functions.FUNCTION_NAME_REGEX + ">" + "\\([params:%*functionparameters%]\\)[return: \\:\\: <.+>]") .setHandledContexts(FunctionContext.class) .name("Function") From 60a185a6f7dd13160283ab60629fd5c03c321135 Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 08:33:57 -0800 Subject: [PATCH 3/9] EffFunctionCall - fix allowing incorrect types --- .../structures/functions/EffFunctionCall.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/io/github/syst3ms/skriptparser/structures/functions/EffFunctionCall.java b/src/main/java/io/github/syst3ms/skriptparser/structures/functions/EffFunctionCall.java index 2da64abc..bc44ac4b 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/structures/functions/EffFunctionCall.java +++ b/src/main/java/io/github/syst3ms/skriptparser/structures/functions/EffFunctionCall.java @@ -96,9 +96,27 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex } } } else { + FunctionParameter functionParameter = functionParameters[0]; + Class paramType = functionParameter.getType(); + if (!paramType.isAssignableFrom(this.parsedExpr.getReturnType())) { + String typeText = TypeManager.getByClass(paramType).get().withIndefiniteArticle(false); + logger.error("The type of the provided value for the '" + functionParameter.getName() + + "' parameter is not " + typeText + "/couldn't be converted to " + + typeText, ErrorType.SEMANTIC_ERROR); + return false; + } paramsExprs = new Expression[]{parsedExpr}; // single parameter setting it to multiple values } } else { + FunctionParameter functionParameter = functionParameters[0]; + Class paramType = functionParameter.getType(); + if (!paramType.isAssignableFrom(this.parsedExpr.getReturnType())) { + String typeText = TypeManager.getByClass(paramType).get().withIndefiniteArticle(false); + logger.error("The type of the provided value for the '" + functionParameter.getName() + + "' parameter is not " + typeText + "/couldn't be converted to " + + typeText, ErrorType.SEMANTIC_ERROR); + return false; + } paramsExprs = new Expression[]{parsedExpr}; // } } From c4551fe08499c5de5f671b2b0aabed6803e8554d Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 10:15:00 -0800 Subject: [PATCH 4/9] ContextValues - revamp how they're handled - Rather than trying to parse, they're now their own expression --- .../expressions/ExprContextValue.java | 157 ++++++++++++++++++ .../lang/base/ContextExpression.java | 89 ---------- .../skriptparser/parsing/SyntaxParser.java | 86 ---------- .../registration/SkriptRegistration.java | 8 +- 4 files changed, 161 insertions(+), 179 deletions(-) create mode 100644 src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java delete mode 100644 src/main/java/io/github/syst3ms/skriptparser/lang/base/ContextExpression.java diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java new file mode 100644 index 00000000..bde1899e --- /dev/null +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java @@ -0,0 +1,157 @@ +package io.github.syst3ms.skriptparser.expressions; + +import io.github.syst3ms.skriptparser.Parser; +import io.github.syst3ms.skriptparser.lang.Expression; +import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.log.ErrorContext; +import io.github.syst3ms.skriptparser.log.ErrorType; +import io.github.syst3ms.skriptparser.log.SkriptLogger; +import io.github.syst3ms.skriptparser.parsing.MatchContext; +import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.parsing.ParserState; +import io.github.syst3ms.skriptparser.pattern.PatternElement; +import io.github.syst3ms.skriptparser.pattern.PatternParser; +import io.github.syst3ms.skriptparser.registration.context.ContextValue; +import io.github.syst3ms.skriptparser.registration.context.ContextValue.State; +import io.github.syst3ms.skriptparser.registration.context.ContextValues; +import io.github.syst3ms.skriptparser.types.changers.ChangeMode; +import org.jetbrains.annotations.Contract; + +import java.lang.reflect.Array; +import java.util.Optional; + +public class ExprContextValue implements Expression { + + private static final String PATTERN = "[the] [(1:(past|previous)|2:(future|next))] [ctx:(context|event)-]<.+>"; + private static final PatternElement CONTEXT_VALUE_PATTERN = PatternParser.parsePattern(PATTERN, new SkriptLogger()).orElseThrow(); + + private ContextValue info; + private String value; + private boolean alone; + + static { + //noinspection unchecked + Parser.getMainRegistration().newExpression(ExprContextValue.class, Object.class, false, + PATTERN) + .name("Context/Event Value") + .description("Returns a value from the current context/event.") + .examples("set {_var} to context-player") + .since("1.0.0") + .register(); + } + + @SuppressWarnings("unchecked") + @Override + @Contract("_, _, _ -> fail") + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + boolean alone = !parseContext.hasMark("ctx"); + String toParse = parseContext.getMatches().getFirst().group(); + String value = parseContext.getMatches().getFirst().group(); + State state = switch (parseContext.getNumericMark()) { + case 0 -> State.PRESENT; + case 1 -> State.PAST; + case 2 -> State.FUTURE; + default -> throw new IllegalArgumentException("Invalid state index: " + parseContext.getNumericMark()); + }; + + + ParserState parserState = parseContext.getParserState(); + SkriptLogger logger = parseContext.getLogger(); + + var matchContext = new MatchContext(CONTEXT_VALUE_PATTERN, parserState, logger); + + for (Class ctx : parserState.getCurrentContexts()) { + for (var info : ContextValues.getContextValues(ctx)) { + matchContext = new MatchContext(info.getPattern(), parserState, logger); + + // Checking all conditions, so no false results slip through. + if (info.getPattern().match(value, 0, matchContext) != value.length()) { + continue; + } else if (!info.getUsage().isCorrect(alone)) { + if (alone) { + logger.error( + "The context value matching '" + toParse + "' cannot be used alone", + ErrorType.SEMANTIC_ERROR, + "Use 'context-" + toParse + "' instead of using just '" + toParse + "' alone" + ); + } else { + logger.error( + "The context value matching '" + toParse + "' must be used alone", + ErrorType.SEMANTIC_ERROR, + "Instead of 'context-" + toParse + "', use this context value as '" + toParse + "'" + ); + } + return false; + } else if (state != info.getState()) { + logger.error("The time state of this context value (" + state.toString().toLowerCase() + ") is incorrect", ErrorType.SEMANTIC_ERROR); + return false; + } else if (parserState.isRestrictingExpressions() && parserState.forbidsSyntax(ExprContextValue.class)) { + logger.setContext(ErrorContext.RESTRICTED_SYNTAXES); + logger.error("The enclosing section does not allow the use of context expressions.", ErrorType.SEMANTIC_ERROR); + return false; + } + + this.info = (ContextValue) info; + this.value = value; + this.alone = alone; + return true; + } + } + if (!alone) { + logger.error("No context value matching '" + toParse + "' was found", ErrorType.SEMANTIC_ERROR); + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public T[] getValues(TriggerContext ctx) { + if (!this.info.getContext().isAssignableFrom(ctx.getClass())) { + return (T[]) Array.newInstance(getReturnType(), 0); + } + assert this.info.getContext().isInstance(ctx); + if (this.info.isSingle()) { + T apply = this.info.getSingleFunction().apply((C) ctx); + T[] array = (T[]) Array.newInstance(getReturnType(), 1); + array[0] = apply; + return array; + } else { + return this.info.getListFunction().apply((C) ctx); + } + } + + @Override + public Optional[]> acceptsChange(ChangeMode mode) { + if (mode == ChangeMode.SET && this.info.canBeSet()) return Optional.of(new Class[]{getReturnType()}); + return Optional.empty(); + } + + @SuppressWarnings("unchecked") + @Override + public void change(TriggerContext ctx, ChangeMode changeMode, Object[] changeWith) { + if (changeMode != ChangeMode.SET) return; + + if (this.info.isSingle()) { + this.info.getSingleSetterFunction().accept((C) ctx, (T) changeWith[0]); + } else { + this.info.getListSetterFunction().accept((C) ctx, (T[]) changeWith); + } + } + + @Override + public boolean isSingle() { + return this.info.isSingle(); + } + + @Override + public Class getReturnType() { + return this.info.getReturnType().getType().getTypeClass(); + } + + @Override + public String toString(TriggerContext ctx, boolean debug) { + return new String[]{"past ", "", "future "}[this.info.getState().ordinal()] + + (this.alone ? "" : "context-") + this.value; + } + +} diff --git a/src/main/java/io/github/syst3ms/skriptparser/lang/base/ContextExpression.java b/src/main/java/io/github/syst3ms/skriptparser/lang/base/ContextExpression.java deleted file mode 100644 index 55db756d..00000000 --- a/src/main/java/io/github/syst3ms/skriptparser/lang/base/ContextExpression.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.github.syst3ms.skriptparser.lang.base; - -import io.github.syst3ms.skriptparser.lang.Expression; -import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.parsing.ParseContext; -import io.github.syst3ms.skriptparser.registration.context.ContextValue; -import io.github.syst3ms.skriptparser.types.changers.ChangeMode; -import org.jetbrains.annotations.Contract; - -import java.lang.reflect.Array; -import java.util.Optional; - -/** - * An {@link Expression} that corresponds to a contextual value. Each trigger - * can carry multiple instances of data (called 'context values'). This expression - * holds a reference to such a value. - * - * @param the TriggerContext class - * @param the Expression's type - * @author Mwexim - */ -public class ContextExpression implements Expression { - private final ContextValue info; - private final String value; - private final boolean alone; - - public ContextExpression(ContextValue info, String value, boolean alone) { - this.info = info; - this.value = value; - this.alone = alone; - } - - @Override - @Contract("_, _, _ -> fail") - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("unchecked") - @Override - public T[] getValues(TriggerContext ctx) { - if (!this.info.getContext().isAssignableFrom(ctx.getClass())) { - return (T[]) Array.newInstance(getReturnType(), 0); - } - assert info.getContext().isInstance(ctx); - if (info.isSingle()) { - T apply = this.info.getSingleFunction().apply((C) ctx); - T[] array = (T[]) Array.newInstance(getReturnType(), 1); - array[0] = apply; - return array; - } else { - return info.getListFunction().apply((C) ctx); - } - } - - @Override - public Optional[]> acceptsChange(ChangeMode mode) { - if (mode == ChangeMode.SET && this.info.canBeSet()) return Optional.of(new Class[]{getReturnType()}); - return Optional.empty(); - } - - @SuppressWarnings("unchecked") - @Override - public void change(TriggerContext ctx, ChangeMode changeMode, Object[] changeWith) { - if (changeMode != ChangeMode.SET) return; - - if (this.info.isSingle()) { - this.info.getSingleSetterFunction().accept((C) ctx, (T) changeWith[0]); - } else { - this.info.getListSetterFunction().accept((C) ctx, (T[]) changeWith); - } - } - - @Override - public boolean isSingle() { - return this.info.isSingle(); - } - - @Override - public Class getReturnType() { - return this.info.getReturnType().getType().getTypeClass(); - } - - @Override - public String toString(TriggerContext ctx, boolean debug) { - return new String[]{"past ", "", "future "}[info.getState().ordinal()] + (alone ? "" : "context-") + value; - } - -} diff --git a/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java b/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java index 70c17c41..87f79135 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java +++ b/src/main/java/io/github/syst3ms/skriptparser/parsing/SyntaxParser.java @@ -15,8 +15,6 @@ import io.github.syst3ms.skriptparser.lang.Variable; import io.github.syst3ms.skriptparser.lang.VariableString; import io.github.syst3ms.skriptparser.lang.base.ConditionalExpression; -import io.github.syst3ms.skriptparser.lang.base.ContextExpression; -import io.github.syst3ms.skriptparser.lang.base.ConvertedExpression; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.log.ErrorContext; import io.github.syst3ms.skriptparser.log.ErrorType; @@ -27,9 +25,6 @@ import io.github.syst3ms.skriptparser.registration.SkriptEventInfo; import io.github.syst3ms.skriptparser.registration.SyntaxInfo; import io.github.syst3ms.skriptparser.registration.SyntaxManager; -import io.github.syst3ms.skriptparser.registration.context.ContextValue; -import io.github.syst3ms.skriptparser.registration.context.ContextValue.State; -import io.github.syst3ms.skriptparser.registration.context.ContextValues; import io.github.syst3ms.skriptparser.types.PatternType; import io.github.syst3ms.skriptparser.types.Type; import io.github.syst3ms.skriptparser.types.TypeManager; @@ -114,10 +109,6 @@ public class SyntaxParser { * All {@link ConditionalExpression conditions} that are successfully parsed during parsing, in order of last successful parsing */ private static final RecentElementList> recentConditions = new RecentElementList<>(); - /** - * All {@link ContextValue context values} that are successfully parsed during parsing, in order of last successful parsing - */ - private static final RecentElementList> recentContextValues = new RecentElementList<>(); /** * Parses an {@link Expression} from the given {@linkplain String} and {@link PatternType expected return type} @@ -193,18 +184,6 @@ public static Optional> parseExpression(St logger.forgetError(); } - // Parsing of standalone context values - var contextValue = parseContextValue(s, expectedType, parserState, logger); - if (contextValue.isPresent()) { - logger.clearErrors(); - ContextExpression contextExpression = contextValue.get(); - if (!expectedType.getType().getTypeClass().isAssignableFrom(contextExpression.getReturnType())) { - Optional> convertedExpression = ConvertedExpression.newInstance(contextExpression, expectedType.getType().getTypeClass()); - return convertedExpression; - } - return contextValue; - } - logger.setContext(ErrorContext.NO_MATCH); logger.error("No expression matching '" + s + "' was found", ErrorType.NO_MATCH); return Optional.empty(); @@ -293,71 +272,6 @@ public static Optional> parseBooleanExpression(Str return Optional.empty(); } - /** - * Parses a {@link ContextValue} from the given {@linkplain String} and {@link PatternType expected return type} - * @param the type of the context value - * @param toParse the string to be parsed as a context value - * @param expectedType the expected return type - * @param parserState the current parser state - * @param logger the logger - * @return an expression that was successfully parsed, or {@literal null} if the string is empty, - * no match was found - * or for another reason detailed in an error message. - */ - public static Optional> parseContextValue(String toParse, PatternType expectedType, ParserState parserState, SkriptLogger logger) { - var matchContext = new MatchContext(CONTEXT_VALUE_PATTERN, parserState, logger); - CONTEXT_VALUE_PATTERN.match(toParse, 0, matchContext); - - var parseContext = matchContext.toParseResult(); - var state = State.values()[parseContext.getNumericMark()]; - boolean alone = !parseContext.hasMark("ctx"); - var value = parseContext.getMatches().get(0).group(); - - for (Class ctx : parseContext.getParserState().getCurrentContexts()) { - for (var info : ContextValues.getContextValues(ctx)) { - matchContext = new MatchContext(info.getPattern(), parserState, logger); - - // Checking all conditions, so no false results slip through. - if (info.getPattern().match(value, 0, matchContext) != value.length()) { - continue; - } else if (!info.getUsage().isCorrect(alone)) { - if (alone) { - logger.error( - "The context value matching '" + toParse + "' cannot be used alone", - ErrorType.SEMANTIC_ERROR, - "Use 'context-something' instead of using this context value alone" - ); - } else { - logger.error( - "The context value matching '" + toParse + "' must be used alone", - ErrorType.SEMANTIC_ERROR, - "Instead of 'context-something', use this context value as 'something'" - ); - } - return Optional.empty(); - } else if (state != info.getState()) { - logger.error("The time state of this context value (" + state.toString().toLowerCase() + ") is incorrect", ErrorType.SEMANTIC_ERROR); - continue; - } else if (expectedType.isSingle() && !info.getReturnType().isSingle()) { - logger.error( - "A single value was expected, but " + toParse + " represents multiple values.", - ErrorType.SEMANTIC_ERROR, - "Use a loop/map to divert each element of this list into single elements" - ); - return Optional.empty(); - } else if (parserState.isRestrictingExpressions() && parserState.forbidsSyntax(ContextExpression.class)) { - logger.setContext(ErrorContext.RESTRICTED_SYNTAXES); - logger.error("The enclosing section does not allow the use of context expressions.", ErrorType.SEMANTIC_ERROR); - return Optional.empty(); - } - - recentContextValues.acknowledge(info); - return Optional.of(new ContextExpression<>((ContextValue) info, value, alone)); - } - } - return Optional.empty(); - } - private static Optional> matchExpressionInfo(String s, ExpressionInfo info, PatternType expectedType, ParserState parserState, SkriptLogger logger) { var patterns = info.getPatterns(); var infoType = info.getReturnType(); diff --git a/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java b/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java index d4e764df..bf160ef8 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java +++ b/src/main/java/io/github/syst3ms/skriptparser/registration/SkriptRegistration.java @@ -1,13 +1,13 @@ package io.github.syst3ms.skriptparser.registration; import io.github.syst3ms.skriptparser.docs.Documentation; +import io.github.syst3ms.skriptparser.expressions.ExprContextValue; import io.github.syst3ms.skriptparser.lang.CodeSection; import io.github.syst3ms.skriptparser.lang.Effect; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.Structure; import io.github.syst3ms.skriptparser.lang.SyntaxElement; import io.github.syst3ms.skriptparser.lang.TriggerContext; -import io.github.syst3ms.skriptparser.lang.base.ContextExpression; import io.github.syst3ms.skriptparser.lang.base.ExecutableExpression; import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.properties.ConditionalType; @@ -469,7 +469,7 @@ public void addEvent(Class c, Class ContextValueRegistrar newContextValue } /** - * Starts a registration process for a {@link ContextExpression} with a single return value. + * Starts a registration process for a {@link ExprContextValue} with a single return value. * * @param context the TriggerContext class * @param returnType the returned type of this context value @@ -506,7 +506,7 @@ public ContextValueRegistrar newSingleContex } /** - * Starts a registration process for a {@link ContextExpression} with a list return value. + * Starts a registration process for a {@link ExprContextValue} with a list return value. * * @param context the TriggerContext class * @param returnType the returned type of this context value From 15360a5e5610849b01c23a1681ff19da8ef4567a Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 10:43:31 -0800 Subject: [PATCH 5/9] build.yml - add dev/** to branches --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3dfc119b..cc4bff71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - dev/** pull_request: jobs: From 9de721a5a7175d9eba160e919490c561b1ae693c Mon Sep 17 00:00:00 2001 From: ShaneBeee Date: Tue, 10 Feb 2026 10:44:02 -0800 Subject: [PATCH 6/9] Add checkstyle and reformat lots of code --- .editorconfig | 23 + build.gradle.kts | 12 + config/checkstyle/checkstyle.xml | 62 ++ .../syst3ms/skriptparser/effects/EffExit.java | 5 +- .../skriptparser/effects/EffReturn.java | 2 +- .../expressions/CondExprChance.java | 4 +- .../expressions/CondExprCompare.java | 272 +++-- .../expressions/CondExprContains.java | 38 +- .../expressions/CondExprIsEmpty.java | 6 +- .../expressions/CondExprIsSet.java | 2 +- .../expressions/CondExprMatch.java | 20 +- .../expressions/ExecExprListOperators.java | 346 +++---- .../expressions/ExecExprReplace.java | 206 ++-- .../skriptparser/expressions/ExprAmount.java | 110 +- .../skriptparser/expressions/ExprAnswer.java | 10 +- .../expressions/ExprBooleanOperators.java | 16 +- .../expressions/ExprColorFromHex.java | 54 +- .../expressions/ExprColorFromRGB.java | 70 +- .../expressions/ExprContextValue.java | 10 +- .../expressions/ExprDateAgoLater.java | 78 +- .../skriptparser/expressions/ExprDateNow.java | 50 +- .../expressions/ExprDateTodayAt.java | 71 +- .../expressions/ExprDefaultValue.java | 6 +- .../expressions/ExprDifference.java | 52 +- .../skriptparser/expressions/ExprElement.java | 4 +- .../expressions/ExprLoopValue.java | 248 ++--- .../expressions/ExprMutableList.java | 10 +- .../expressions/ExprPrimeNumber.java | 63 -- .../expressions/ExprRandomNumber.java | 4 +- .../skriptparser/expressions/ExprRange.java | 36 +- .../expressions/ExprStringCharAt.java | 70 +- .../expressions/ExprStringChars.java | 4 +- .../expressions/ExprUnaryMathFunctions.java | 140 +-- .../skriptparser/expressions/ExprWhether.java | 2 +- .../expressions/LitScriptName.java | 4 +- .../expressions/LitTimeConstants.java | 2 +- .../skriptparser/lang/CodeSection.java | 62 +- .../syst3ms/skriptparser/lang/Expression.java | 145 +-- .../skriptparser/lang/ExpressionList.java | 10 +- .../syst3ms/skriptparser/lang/Literal.java | 9 +- .../skriptparser/lang/LiteralList.java | 1 + .../skriptparser/lang/SimpleCodeSection.java | 36 +- .../skriptparser/lang/SimpleExpression.java | 3 +- .../skriptparser/lang/SimpleLiteral.java | 3 +- .../syst3ms/skriptparser/lang/Statement.java | 75 +- .../skriptparser/lang/SyntaxElement.java | 53 +- .../skriptparser/lang/UnloadedTrigger.java | 36 +- .../syst3ms/skriptparser/lang/Variable.java | 26 +- .../skriptparser/lang/VariableString.java | 18 +- .../lang/base/ConditionalExpression.java | 5 +- .../lang/base/ConvertedExpression.java | 17 +- .../lang/base/ExecutableExpression.java | 5 +- .../lang/base/RestrictedExpression.java | 14 +- .../lang/base/TaggedExpression.java | 66 +- .../lang/control/Continuable.java | 24 +- .../skriptparser/lang/control/Finishing.java | 38 +- .../lang/control/SelfReferencing.java | 20 +- .../lang/entries/EntryLoader.java | 51 +- .../lang/entries/LiteralLoader.java | 116 +-- .../lang/entries/OptionLoader.java | 80 +- .../lang/entries/SectionConfiguration.java | 12 +- .../lang/entries/SectionLoader.java | 34 +- .../lang/lambda/ArgumentSection.java | 2 + .../lang/lambda/ReturnSection.java | 3 + .../lang/lambda/SectionValue.java | 28 +- .../lang/properties/ConditionalType.java | 30 +- .../lang/properties/PropertyConditional.java | 67 +- .../lang/properties/PropertyExpression.java | 41 +- .../skriptparser/parsing/ParserState.java | 4 +- .../skriptparser/parsing/ScriptLoader.java | 12 +- .../skriptparser/parsing/SyntaxParser.java | 20 +- .../pattern/ExpressionElement.java | 2 +- .../skriptparser/pattern/PatternParser.java | 2 +- .../registration/DefaultRegistration.java | 6 +- .../registration/ExpressionInfo.java | 1 + .../registration/PatternInfos.java | 3 + .../registration/SkriptAddon.java | 21 +- .../registration/SkriptEventInfo.java | 1 + .../registration/SkriptRegistration.java | 117 ++- .../skriptparser/registration/SyntaxInfo.java | 6 +- .../registration/context/ContextValues.java | 8 +- .../registration/tags/ContinuousTag.java | 28 +- .../skriptparser/registration/tags/Tag.java | 85 +- .../registration/tags/TagInfo.java | 25 +- .../registration/tags/TagManager.java | 20 +- .../skriptparser/sections/SecAsync.java | 2 +- .../skriptparser/sections/SecCase.java | 44 +- .../skriptparser/sections/SecConditional.java | 19 +- .../skriptparser/sections/SecFilter.java | 23 +- .../skriptparser/sections/SecFlatMap.java | 131 ++- .../skriptparser/sections/SecLoop.java | 36 +- .../syst3ms/skriptparser/sections/SecMap.java | 5 +- .../skriptparser/sections/SecSwitch.java | 8 +- .../skriptparser/sections/SecWhile.java | 2 +- .../functions/DefaultFunctions.java | 2 +- .../structures/functions/EffFunctionCall.java | 37 +- .../functions/ExprFunctionCall.java | 29 +- .../structures/functions/Function.java | 14 +- .../structures/functions/FunctionContext.java | 12 +- .../functions/FunctionParameter.java | 34 +- .../structures/functions/Functions.java | 5 +- .../structures/functions/ScriptFunction.java | 6 +- .../structures/functions/StructFunction.java | 2 +- .../syst3ms/skriptparser/tags/TagCase.java | 44 +- .../syst3ms/skriptparser/tags/TagReset.java | 31 +- .../tags/TagSpecialCharacters.java | 83 +- .../skriptparser/types/PatternType.java | 20 +- .../syst3ms/skriptparser/types/Type.java | 3 +- .../skriptparser/types/TypeManager.java | 9 +- .../types/changers/Arithmetic.java | 1 + .../skriptparser/types/changers/Changer.java | 6 +- .../types/changers/TypeSerializer.java | 8 +- .../types/comparisons/Comparator.java | 1 + .../types/comparisons/ComparatorInfo.java | 26 +- .../types/comparisons/Comparators.java | 30 +- .../types/comparisons/InverseComparator.java | 1 + .../types/conversions/ChainedConverter.java | 4 +- .../types/conversions/ConverterInfo.java | 26 +- .../types/conversions/ConverterUtils.java | 24 +- .../types/conversions/Converters.java | 194 ++-- .../skriptparser/types/ranges/RangeInfo.java | 24 +- .../skriptparser/types/ranges/Ranges.java | 4 +- .../syst3ms/skriptparser/util/ClassUtils.java | 2 +- .../skriptparser/util/CollectionUtils.java | 7 +- .../skriptparser/util/DoubleOptional.java | 71 +- .../skriptparser/util/DurationUtils.java | 11 +- .../syst3ms/skriptparser/util/FileUtils.java | 10 +- .../syst3ms/skriptparser/util/MultiMap.java | 2 +- .../skriptparser/util/NumberUtils.java | 62 +- .../syst3ms/skriptparser/util/Pair.java | 20 +- .../skriptparser/util/RecentElementList.java | 12 +- .../syst3ms/skriptparser/util/SkriptDate.java | 24 +- .../skriptparser/util/StringUtils.java | 45 +- .../skriptparser/util/ThreadUtils.java | 152 +-- .../syst3ms/skriptparser/util/Time.java | 29 +- .../skriptparser/util/color/Color.java | 21 +- .../util/math/AsinCalculator.java | 61 +- .../util/math/BigDecimalMath.java | 28 +- .../skriptparser/util/math/BigRational.java | 946 +++++++++--------- .../skriptparser/util/math/CosCalculator.java | 67 +- .../skriptparser/util/math/ExpCalculator.java | 55 +- .../skriptparser/util/math/NumberMath.java | 68 +- .../skriptparser/util/math/PowerIterator.java | 35 +- .../util/math/PowerNIterator.java | 49 +- .../util/math/PowerTwoNIterator.java | 49 +- .../util/math/PowerTwoNPlusOneIterator.java | 49 +- .../util/math/SeriesCalculator.java | 201 ++-- .../skriptparser/util/math/SinCalculator.java | 69 +- .../variables/SerializedVariable.java | 43 +- .../skriptparser/variables/VariableMap.java | 12 +- .../variables/VariableStorage.java | 39 +- .../skriptparser/variables/Variables.java | 41 +- 152 files changed, 3415 insertions(+), 3418 deletions(-) create mode 100644 .editorconfig create mode 100644 config/checkstyle/checkstyle.xml delete mode 100644 src/main/java/io/github/syst3ms/skriptparser/expressions/ExprPrimeNumber.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..772fe705 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +tab_width = 4 +trim_trailing_whitespace = true +ij_continuation_indent_size = 4 +[*.java] +ij_java_class_count_to_use_import_on_demand = 1024 +ij_java_names_count_to_use_import_on_demand = 1024 +[*.yml] +indent_size = 2 +[*.json] +indent_size = 2 +[*.md] +trim_trailing_whitespace=false +[*.sk] +indent_style = tab diff --git a/build.gradle.kts b/build.gradle.kts index fd38e5a5..f2d425af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("java") id("maven-publish") + id("checkstyle") } group = "com.github.SkriptDev" version = "1.0.6" @@ -56,6 +57,17 @@ tasks { java { withSourcesJar() } + checkstyle { + // Specify the version of the Checkstyle tool to use + toolVersion = "10.21.0" // Use a recent version of Checkstyle + + isIgnoreFailures = false + + // Point to your custom Checkstyle configuration file + // The default location is config/checkstyle/checkstyleMain.xml + configFile = file("${rootProject.projectDir}/config/checkstyle/checkstyle.xml") + } + publishing { publications { create("maven") { diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 00000000..22c57fb3 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java index 8b0647d1..690ef6d6 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java @@ -39,7 +39,10 @@ public class EffExit extends Effect { "(exit|stop) %*integer% (0:section|1:loop|2:condition[al])[s]", "(exit|stop) (every|all [[of] the]) (0:section|1:loop|2:condition[al])[s]") .name("Exit") - .description("Exits the entire trigger, preventing all upcoming statements to not get triggered. There's also a possibility to only exit certain sections. If more sections are exited than the total amount of nested sections, the trigger will stop. Note that stopping loops also stops while-loops.") + .description("Exits the entire trigger, preventing all upcoming statements to not get triggered", + "There's also a possibility to only exit certain sections.", + "If more sections are exited than the total amount of nested sections, the trigger will stop.", + "Note that stopping loops also stops while-loops.") .since("1.0.0") .register(); } diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java index 8a7d6f83..e50d45ab 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java @@ -114,7 +114,7 @@ public Optional walk(TriggerContext ctx) { }); if (isInFunction) { FunctionContext functionContext = (FunctionContext) ctx; - Function function = functionContext.getOwningFunction(); + Function function = functionContext.owningFunction(); function.setReturnValue(returned.getValues(ctx)); return Optional.empty(); // stop the trigger } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprChance.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprChance.java index 801f0941..2540e2ac 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprChance.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprChance.java @@ -10,6 +10,8 @@ public class CondExprChance extends ConditionalExpression { + private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); + static { Parser.getMainRegistration().newExpression(CondExprChance.class, Boolean.class, true, "chance of %number%[1:\\%]") @@ -22,8 +24,6 @@ public class CondExprChance extends ConditionalExpression { .register(); } - private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); - private Expression chance; private boolean percent; diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprCompare.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprCompare.java index f3cef0f5..cdbfde27 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprCompare.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprCompare.java @@ -40,14 +40,14 @@ */ public class CondExprCompare extends ConditionalExpression { public static final PatternInfos PATTERNS = new PatternInfos<>(new Object[][]{ - {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) (greater|more|higher|bigger|larger|above) [than] or (equal to|the same as)|\\>=) %objects% [0x10:each|0x18:respectively]", Relation.GREATER_OR_EQUAL}, - {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) (less|smaller|below) [than] or (equal to|the same as)|\\<=) %objects% [0x10:each|0x18:respectively]", Relation.SMALLER_OR_EQUAL}, - {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) ((greater|more|higher|bigger|larger) than|above)|\\>) %objects% [0x10:each|0x18:respectively]", Relation.GREATER}, - {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) ((less|smaller) than|below)|\\<) %objects% [0x10:each|0x18:respectively]", Relation.SMALLER}, - {"[1:neither] %objects% [8:each] (is|are)(2:n't [8:each]|2:[8: each] not) between %objects% and %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, - {"[1:neither] %objects% [8:each] (is|are) [8:each] between %objects% and %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, - {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)) [equal to]|2:!=) %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, - {"[1:neither] %objects% [8:each] ((is|are) [8:each] [equal to|the same as]|=[=]) %objects% [0x10:each|0x18:respectively]", Relation.EQUAL} + {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) (greater|more|higher|bigger|larger|above) [than] or (equal to|the same as)|\\>=) %objects% [0x10:each|0x18:respectively]", Relation.GREATER_OR_EQUAL}, + {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) (less|smaller|below) [than] or (equal to|the same as)|\\<=) %objects% [0x10:each|0x18:respectively]", Relation.SMALLER_OR_EQUAL}, + {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) ((greater|more|higher|bigger|larger) than|above)|\\>) %objects% [0x10:each|0x18:respectively]", Relation.GREATER}, + {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)| [8:each]) ((less|smaller) than|below)|\\<) %objects% [0x10:each|0x18:respectively]", Relation.SMALLER}, + {"[1:neither] %objects% [8:each] (is|are)(2:n't [8:each]|2:[8: each] not) between %objects% and %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, + {"[1:neither] %objects% [8:each] (is|are) [8:each] between %objects% and %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, + {"[1:neither] %objects% [8:each] ((is|are)(2:(n't [8:each]|[8: each] not|4:[8: each] neither)) [equal to]|2:!=) %objects% [0x10:each|0x18:respectively]", Relation.EQUAL}, + {"[1:neither] %objects% [8:each] ((is|are) [8:each] [equal to|the same as]|=[=]) %objects% [0x10:each|0x18:respectively]", Relation.EQUAL} }); static { @@ -74,6 +74,14 @@ public class CondExprCompare extends ConditionalExpression { private boolean firstEach; private boolean secondEach; + private static String errorString(Expression expr, boolean debug) { + if (expr.getReturnType() == Object.class) + return expr.toString(TriggerContext.DUMMY, debug); + Optional> exprType = TypeManager.getByClass(expr.getReturnType()); + assert exprType.isPresent(); + return StringUtils.withIndefiniteArticle(exprType.get().getBaseName(), !expr.isSingle()); + } + @SuppressWarnings("null") @Override public boolean init(Expression[] expressions, int matchedPattern, ParseContext result) { @@ -88,7 +96,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex setNegated(true); if ((parseMark & 1) != 0) // "neither" on the left side setNegated(!isNegated()); - if ((parseMark & 4) != 0) {// "neither" on the right side + if ((parseMark & 4) != 0) { // "neither" on the right side if (second instanceof ExpressionList) { second.setAndList(!second.isAndList()); } @@ -101,42 +109,42 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (firstEach && secondEach && first.isSingle() && second.isSingle() && (third == null || third.isSingle())) { logger.warn("Using \"respectively\" or two \"each\" options on single values is redundant"); } else if (firstEach - && secondEach - && (first.isAndList() != second.isAndList() || - first.isSingle() != second.isSingle())) { + && secondEach + && (first.isAndList() != second.isAndList() || + first.isSingle() != second.isSingle())) { /* * Here we want to rule out some obviously impossible combinations: * - Respectively comparing a single value and a list * - Respectively comparing lists that aren't both "and" or "or" */ logger.error( - "'" + - first.toString(TriggerContext.DUMMY, logger.isDebug()) + - "' and '" + - second.toString(TriggerContext.DUMMY, logger.isDebug()) + - "' cannot be compared respectively", - ErrorType.SEMANTIC_ERROR + "'" + + first.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' and '" + + second.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' cannot be compared respectively", + ErrorType.SEMANTIC_ERROR ); return false; } else if (third != null - && secondEach - && (firstEach && first.isAndList() != second.isAndList() - || second.isAndList() != third.isAndList() - || firstEach && first.isSingle() != second.isSingle() - || second.isSingle() != third.isSingle())) { + && secondEach + && (firstEach && first.isAndList() != second.isAndList() + || second.isAndList() != third.isAndList() + || firstEach && first.isSingle() != second.isSingle() + || second.isSingle() != third.isSingle())) { /* * What is ruled out here is using "each" when "second" and "third" don't match in number or in and/or type. * Otherwise these are fundamentally the same checks as above but when "third" is present. */ logger.error( - "'" + - first.toString(TriggerContext.DUMMY, logger.isDebug()) + - "' cannot be compared respectively with '" + - second.toString(TriggerContext.DUMMY, logger.isDebug()) + - "' and '" + - third.toString(TriggerContext.DUMMY, logger.isDebug()) + - "'", - ErrorType.SEMANTIC_ERROR + "'" + + first.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' cannot be compared respectively with '" + + second.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' and '" + + third.toString(TriggerContext.DUMMY, logger.isDebug()) + + "'", + ErrorType.SEMANTIC_ERROR ); return false; } else if (firstEach && first.isSingle()) { @@ -164,30 +172,30 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex * two lists order-insensitively. */ contentComparison = third == null - && relation == Relation.EQUAL - && !(firstEach || secondEach) - && !(first.isSingle() || second.isSingle()); + && relation == Relation.EQUAL + && !(firstEach || secondEach) + && !(first.isSingle() || second.isSingle()); if (!initComparator()) { if (third == null) { logger.error( - "'" + + "'" + first.toString(TriggerContext.DUMMY, logger.isDebug()) + "' and '" + second.toString(TriggerContext.DUMMY, logger.isDebug()) + "' cannot be compared", - ErrorType.SEMANTIC_ERROR + ErrorType.SEMANTIC_ERROR ); } else { logger.error( - "'" + + "'" + first.toString(TriggerContext.DUMMY, logger.isDebug()) + "' cannot be compared with '" + second.toString(TriggerContext.DUMMY, logger.isDebug()) + "' and '" + third.toString(TriggerContext.DUMMY, logger.isDebug()) + "'", - ErrorType.SEMANTIC_ERROR + ErrorType.SEMANTIC_ERROR ); } return false; @@ -197,7 +205,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex return relation.isEqualOrInverse() || comparator.supportsOrdering(); } else if (!comparator.supportsOrdering()) { logger.error( - errorString(first, logger.isDebug()) + + errorString(first, logger.isDebug()) + " cannot be ordered between " + errorString(second, logger.isDebug()) + " and " + @@ -212,8 +220,8 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex private boolean initComparator() { Class f = first.getReturnType(); Class s = third == null - ? second.getReturnType() - : ClassUtils.getCommonSuperclass(second.getReturnType(), third.getReturnType()); + ? second.getReturnType() + : ClassUtils.getCommonSuperclass(second.getReturnType(), third.getReturnType()); if (f == Object.class || s == Object.class) { return true; @@ -221,40 +229,6 @@ private boolean initComparator() { return (comparator = (Comparator) Comparators.getComparator(f, s).orElse(null)) != null; } - /* - * # := condition (e.g. is, is less than, contains, is enchanted with, has permission, etc.) - * !# := not # - * - * a and b # x === a # x && b # x - * a or b # x === a # x || b # x - * a # x and y === a # x && a # y - * a # x or y === a # x || a # y - * a and b # x and y === a # x and y && b # x and y === a # x && a # y && b # x && b # y - * a and b # x or y === a # x or y && b # x or y - * a or b # x and y === a # x and y || b # x and y - * a or b # x or y === a # x or y || b # x or y - * - * - * a and b !# x === a !# x && b !# x - * neither a nor b # x === a !# x && b !# x // nor = and - * a or b !# x === a !# x || b !# x - * - * a !# x and y === a !# x || a !# y // e.g. "player doesn't have 2 emeralds and 5 gold ingots" == "NOT(player has 2 emeralds and 5 gold ingots)" == "player doesn't have 2 emeralds OR player doesn't have 5 gold ingots" - * a # neither x nor y === a !# x && a !# y // nor = or // e.g. "player has neither 2 emeralds nor 5 gold ingots" == "player doesn't have 2 emeralds AND player doesn't have 5 gold ingots" - * a # neither x nor y === a !# x && a !# y // nor = or // e.g. "player is neither the attacker nor the victim" == "player is not the attacker AND player is not the victim" - * a !# x or y === a !# x && a !# y // e.g. "player doesn't have 2 emeralds or 5 gold ingots" == "NOT(player has 2 emeralds or 5 gold ingots)" == "player doesn't have 2 emeralds AND player doesn't have 5 gold ingots" - * - * a and b !# x and y === a !# x and y && b !# x and y === (a !# x || a !# y) && (b !# x || b !# y) - * a and b !# x or y === a !# x or y && b !# x or y - * a and b # neither x nor y === a # neither x nor y && b # neither x nor y - * - * a or b !# x and y === a !# x and y || b !# x and y - * a or b !# x or y === a !# x or y || b !# x or y - * a or b # neither x nor y === a # neither x nor y || b # neither x nor y - * - * neither a nor b # x and y === a !# x and y && b !# x and y // nor = and - * neither a nor b # x or y === a !# x or y && b !# x or y // nor = and - */ @Override public boolean check(TriggerContext ctx) { Object[] firstValues = first.getArray(ctx); @@ -270,8 +244,8 @@ public boolean check(TriggerContext ctx) { for (int i = 0; i < firstValues.length; i++) { hasElement = true; boolean b = fullCompare( - Arrays.copyOfRange(firstValues, i, i+1), - Arrays.copyOfRange(secondValues, i, i+1) + Arrays.copyOfRange(firstValues, i, i + 1), + Arrays.copyOfRange(secondValues, i, i + 1) ); if (and && !b) return false; @@ -285,17 +259,17 @@ public boolean check(TriggerContext ctx) { return hasElement && and; } else if (firstEach) { return Expression.check( - firstValues, - f -> fullCompare(new Object[]{f}, secondValues), - false, - first.isAndList() + firstValues, + f -> fullCompare(new Object[]{f}, secondValues), + false, + first.isAndList() ); } else if (secondEach) { return Expression.check( - secondValues, - s -> fullCompare(firstValues, new Object[]{s}), - false, - second.isAndList() + secondValues, + s -> fullCompare(firstValues, new Object[]{s}), + false, + second.isAndList() ); } else { return fullCompare(firstValues, secondValues); @@ -309,9 +283,9 @@ public boolean check(TriggerContext ctx) { for (int i = 0; i < firstValues.length; i++) { hasElement = true; boolean b = fullCompareWithThird( - Arrays.copyOfRange(firstValues, i, i+1), - Arrays.copyOfRange(secondValues, i, i+1), - Arrays.copyOfRange(thirdValues, i, i+1) + Arrays.copyOfRange(firstValues, i, i + 1), + Arrays.copyOfRange(secondValues, i, i + 1), + Arrays.copyOfRange(thirdValues, i, i + 1) ); if (and && !b) return false; @@ -321,10 +295,10 @@ public boolean check(TriggerContext ctx) { return hasElement && and; } else if (firstEach) { return Expression.check( - firstValues, - f -> fullCompareWithThird(new Object[]{f}, secondValues, thirdValues), - false, - first.isAndList() + firstValues, + f -> fullCompareWithThird(new Object[]{f}, secondValues, thirdValues), + false, + first.isAndList() ); } else if (secondEach) { if (secondValues.length != thirdValues.length) @@ -335,9 +309,9 @@ public boolean check(TriggerContext ctx) { for (int i = 0; i < secondValues.length; i++) { hasElement = true; boolean b = fullCompareWithThird( - firstValues, - Arrays.copyOfRange(secondValues, i, i+1), - Arrays.copyOfRange(thirdValues, i, i+1) + firstValues, + Arrays.copyOfRange(secondValues, i, i + 1), + Arrays.copyOfRange(thirdValues, i, i + 1) ); if (and && !b) return false; @@ -353,19 +327,19 @@ public boolean check(TriggerContext ctx) { private boolean fullCompare(Object[] firstValues, Object[] secondValues) { if (!contentComparison) { return Expression.check( - firstValues, - o1 -> Expression.check( - secondValues, - o2 -> relation.is( - comparator != null ? - comparator.apply(o1, o2) - : Comparators.compare(o1, o2) - ), - false, - second.isAndList() + firstValues, + o1 -> Expression.check( + secondValues, + o2 -> relation.is( + comparator != null ? + comparator.apply(o1, o2) + : Comparators.compare(o1, o2) ), - isNegated(), - first.isAndList() + false, + second.isAndList() + ), + isNegated(), + first.isAndList() ); } else { if (firstValues.length != secondValues.length) @@ -393,38 +367,38 @@ private boolean fullCompare(Object[] firstValues, Object[] secondValues) { private boolean fullCompareWithThird(Object[] firstValues, Object[] secondValues, Object[] thirdValues) { assert third != null; return Expression.check( - firstValues, - o1 -> Expression.check( - secondValues, - o2 -> Expression.check( - thirdValues, - o3 -> { - boolean isBetween; - if (comparator != null) { - isBetween = - (Relation.GREATER_OR_EQUAL.is(comparator.apply(o1, o2)) && - Relation.SMALLER_OR_EQUAL.is(comparator.apply(o1, o3))) - || // Check OPPOSITE (switching o2 / o3) - (Relation.GREATER_OR_EQUAL.is(comparator.apply(o1, o3)) && - Relation.SMALLER_OR_EQUAL.is(comparator.apply(o1, o2))); - } else { - isBetween = - (Relation.GREATER_OR_EQUAL.is(Comparators.compare(o1, o2)) && - Relation.SMALLER_OR_EQUAL.is(Comparators.compare(o1, o3))) - || // Check OPPOSITE (switching o2 / o3) - (Relation.GREATER_OR_EQUAL.is(Comparators.compare(o1, o3)) && - Relation.SMALLER_OR_EQUAL.is(Comparators.compare(o1, o2))); - } - return relation == Relation.NOT_EQUAL != isBetween; - }, - false, - third.isAndList() - ), - false, - second.isAndList() + firstValues, + o1 -> Expression.check( + secondValues, + o2 -> Expression.check( + thirdValues, + o3 -> { + boolean isBetween; + if (comparator != null) { + isBetween = + (Relation.GREATER_OR_EQUAL.is(comparator.apply(o1, o2)) && + Relation.SMALLER_OR_EQUAL.is(comparator.apply(o1, o3))) + || // Check OPPOSITE (switching o2 / o3) + (Relation.GREATER_OR_EQUAL.is(comparator.apply(o1, o3)) && + Relation.SMALLER_OR_EQUAL.is(comparator.apply(o1, o2))); + } else { + isBetween = + (Relation.GREATER_OR_EQUAL.is(Comparators.compare(o1, o2)) && + Relation.SMALLER_OR_EQUAL.is(Comparators.compare(o1, o3))) + || // Check OPPOSITE (switching o2 / o3) + (Relation.GREATER_OR_EQUAL.is(Comparators.compare(o1, o3)) && + Relation.SMALLER_OR_EQUAL.is(Comparators.compare(o1, o2))); + } + return relation == Relation.NOT_EQUAL != isBetween; + }, + false, + third.isAndList() ), - isNegated(), - first.isAndList() + false, + second.isAndList() + ), + isNegated(), + first.isAndList() ); } @@ -434,27 +408,19 @@ public String toString(TriggerContext ctx, boolean debug) { Expression third = this.third; if (third == null) { s = first.toString(ctx, debug) + " is " + (isNegated() ? "not " : "") + relation + " " + second.toString( - ctx, debug); + ctx, debug); } else { s = first.toString(ctx, debug) + - " is " + - (isNegated() ? "not " : "") + - "between " + - second.toString(ctx, debug) + - " and " + - third.toString(ctx, debug); + " is " + + (isNegated() ? "not " : "") + + "between " + + second.toString(ctx, debug) + + " and " + + third.toString(ctx, debug); } if (debug) { s += " (comparator: " + comparator + ")"; } return s; } - - private static String errorString(Expression expr, boolean debug) { - if (expr.getReturnType() == Object.class) - return expr.toString(TriggerContext.DUMMY, debug); - Optional> exprType = TypeManager.getByClass(expr.getReturnType()); - assert exprType.isPresent(); - return StringUtils.withIndefiniteArticle(exprType.get().getBaseName(), !expr.isSingle()); - } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprContains.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprContains.java index 0d478fb5..b8e1c06d 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprContains.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprContains.java @@ -16,12 +16,12 @@ * See if a given list of objects contain a given element. * You can also check if a string contains another string. * + * @author Mwexim * @name Contain * @type CONDITION * @pattern %string% [does(n't| not)] contain[s] %string% * @pattern %objects% [do[es](n't| not)] contain[s] %objects% * @since ALPHA - * @author Mwexim */ public class CondExprContains extends ConditionalExpression { static { @@ -52,16 +52,16 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex comparator = (Comparator) Comparators.getComparator(first.getReturnType(), second.getReturnType()).orElse(null); // If the expressions are variables, their return type is unknown at parse time if (first.getReturnType() != Object.class - && second.getReturnType() != Object.class - && comparator == null) { + && second.getReturnType() != Object.class + && comparator == null) { var logger = parseContext.getLogger(); logger.error( - "'" + + "'" + first.toString(TriggerContext.DUMMY, logger.isDebug()) + "' can never contain '" + second.toString(TriggerContext.DUMMY, logger.isDebug()) + "' because their values cannot be compared", - ErrorType.SEMANTIC_ERROR + ErrorType.SEMANTIC_ERROR ); return false; } @@ -70,9 +70,9 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex setNegated(parseContext.getNumericMark() == 1); if (!onlyString && !first.isAndList()) { parseContext.getLogger().error( - "An or-list cannot contain any values", - ErrorType.SEMANTIC_ERROR, - "If you want to check if an or-list 'contains' a value, you should do an equality check instead." + "An or-list cannot contain any values", + ErrorType.SEMANTIC_ERROR, + "If you want to check if an or-list 'contains' a value, you should do an equality check instead." ); return false; } @@ -83,19 +83,19 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex public boolean check(TriggerContext ctx) { if (onlyString) { return isNegated() != DoubleOptional.ofOptional(first.getSingle(ctx), second.getSingle(ctx)) - .map(toCheck -> (String) toCheck, toMatch -> (String) toMatch) - .mapToOptional(String::contains) - .orElse(false); + .map(toCheck -> (String) toCheck, toMatch -> (String) toMatch) + .mapToOptional(String::contains) + .orElse(false); } else { return second.check( - ctx, - toMatch -> Expression.check( - first.getValues(ctx), - toCheck -> (comparator == null ? Comparators.compare(toCheck, toMatch) : comparator.apply(toCheck, toMatch)).is(Relation.EQUAL), - false, - !first.isAndList() - ), - isNegated() + ctx, + toMatch -> Expression.check( + first.getValues(ctx), + toCheck -> (comparator == null ? Comparators.compare(toCheck, toMatch) : comparator.apply(toCheck, toMatch)).is(Relation.EQUAL), + false, + !first.isAndList() + ), + isNegated() ); } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java index 4556aa0d..ceef4a6c 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsEmpty.java @@ -12,11 +12,11 @@ * If you want a string list to be checked as a list instead of all separate strings, * you should use the 'list' modifier at the end. * + * @author Olyno * @name Is Empty * @pattern %objects% (is|are)[( not|n't)] empty * @pattern %strings% (is|are)[( not|n't)] [an] empty string[s] * @since ALPHA - * @author Olyno */ public class CondExprIsEmpty extends ConditionalExpression { static { @@ -52,8 +52,8 @@ public boolean check(TriggerContext ctx) { } else { var values = expression.getValues(ctx); return isNegated() != (values.length != 1 - ? values.length == 0 - : values[0] instanceof String && ((String) values[0]).isBlank()); + ? values.length == 0 + : values[0] instanceof String && ((String) values[0]).isBlank()); } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsSet.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsSet.java index 0c2e3f28..789725e3 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsSet.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprIsSet.java @@ -7,11 +7,11 @@ /** * Check if a given expression is set (null on the Java side) or not. * + * @author Syst3ms * @name Is Set * @type CONDITION * @pattern %~objects% (is|are)[ not|n't] set * @since ALPHA - * @author Syst3ms */ public class CondExprIsSet extends PropertyConditional { static { diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprMatch.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprMatch.java index 1bd8d031..1407da66 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprMatch.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/CondExprMatch.java @@ -11,11 +11,11 @@ /** * Check if the given strings match a certain regex expression. * + * @author Mwexim * @name Match * @type CONDITION * @pattern %strings% [do[es](n't| not)] [part[ial]ly] match[es] %strings% * @since ALPHA - * @author Mwexim */ public class CondExprMatch extends ConditionalExpression { static { @@ -45,21 +45,21 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex @Override public boolean check(TriggerContext ctx) { return matched.check( + ctx, + toMatch -> pattern.check( ctx, - toMatch -> pattern.check( - ctx, - pattern -> partly ? Pattern.compile(pattern).matcher(toMatch).find() : toMatch.matches(pattern) - ), - isNegated() + pattern -> partly ? Pattern.compile(pattern).matcher(toMatch).find() : toMatch.matches(pattern) + ), + isNegated() ); } @Override public String toString(TriggerContext ctx, boolean debug) { return matched.toString(ctx, debug) - + (isNegated() ? " does not" : "") - + (partly ? " partially" : "") - + (isNegated() ? " match " : " matches ") - + pattern.toString(ctx, debug); + + (isNegated() ? " does not" : "") + + (partly ? " partially" : "") + + (isNegated() ? " match " : " matches ") + + pattern.toString(ctx, debug); } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprListOperators.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprListOperators.java index bbd0576b..e6a887c0 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprListOperators.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprListOperators.java @@ -29,195 +29,195 @@ * when a negative step function is used, the list is reversed as well as the lower and upper bounds, * which means the lower bound must be higher than the upper bound. * + * @author Mwexim * @name List Operators * @type EFFECT/EXPRESSION * @pattern extract [the] (last|first|%integer%(st|nd|rd|th)) element out [of] %objects% * @pattern pop %objects% - * @pattern (shift|poll) %objects% + * @pattern (shift | poll) %objects% * @pattern splice %objects% (from %integer% to %integer%|starting (at|from) %integer%|up to %integer%) [[with] step %integer%] - * @since ALPHA - * @author Mwexim * @see ExprElement + * @since ALPHA */ public class ExecExprListOperators extends ExecutableExpression { - static { - Parser.getMainRegistration().addExecutableExpression( - ExecExprListOperators.class, - Object.class, - false, - "extract [the] (0:last|1:first|2:%integer%(st|nd|rd|th)) element out [of] %objects%", - "pop %objects%", - "(shift|poll) %objects%", - "splice %objects% (0:from %integer% to %integer%|1:starting (at|from) %integer%|2:up to %integer%) [[with] step %integer%]" - ); - } + static { + Parser.getMainRegistration().addExecutableExpression( + ExecExprListOperators.class, + Object.class, + false, + "extract [the] (0:last|1:first|2:%integer%(st|nd|rd|th)) element out [of] %objects%", + "pop %objects%", + "(shift|poll) %objects%", + "splice %objects% (0:from %integer% to %integer%|1:starting (at|from) %integer%|2:up to %integer%) [[with] step %integer%]" + ); + } - // 0 = last, 1 = first, 2 = indexed, 3 = spliced - private int type; - private Expression list; - private Expression index; - private Expression lower; - private Expression upper; - private Expression step; + // 0 = last, 1 = first, 2 = indexed, 3 = spliced + private int type; + private Expression list; + private Expression index; + private Expression lower; + private Expression upper; + private Expression step; - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - switch (matchedPattern) { - case 0: - type = parseContext.getNumericMark(); - list = (Expression) (type == 2 ? expressions[1] : expressions[0]); - if (type == 2) - index = (Expression) expressions[0]; - break; - case 1: - case 2: - type = matchedPattern - 1; - list = (Expression) expressions[0]; - break; - case 3: - type = 3; - list = (Expression) expressions[0]; - switch (parseContext.getNumericMark()) { - case 0: - lower = (Expression) expressions[1]; - upper = (Expression) expressions[2]; - if (expressions.length == 4) - step = (Expression) expressions[3]; - break; - case 1: - lower = (Expression) expressions[1]; - if (expressions.length == 3) - step = (Expression) expressions[2]; - break; - case 2: - upper = (Expression) expressions[1]; - if (expressions.length == 3) - step = (Expression) expressions[2]; - break; - default: - throw new IllegalStateException(); - } - } - var logger = parseContext.getLogger(); - if (!list.acceptsChange(ChangeMode.SET, list.getReturnType(), false)) { - logger.error( - list.toString(TriggerContext.DUMMY, logger.isDebug()) - + "' cannot be set to multiple values", - ErrorType.SEMANTIC_ERROR - ); - return false; - } else if (list.isSingle()) { - logger.error( - list.toString(TriggerContext.DUMMY, logger.isDebug()) + " represents a single value", - ErrorType.SEMANTIC_ERROR, - "List operators only work on multiple objects at the same time" - ); - return false; - } - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + switch (matchedPattern) { + case 0: + type = parseContext.getNumericMark(); + list = (Expression) (type == 2 ? expressions[1] : expressions[0]); + if (type == 2) + index = (Expression) expressions[0]; + break; + case 1: + case 2: + type = matchedPattern - 1; + list = (Expression) expressions[0]; + break; + case 3: + type = 3; + list = (Expression) expressions[0]; + switch (parseContext.getNumericMark()) { + case 0: + lower = (Expression) expressions[1]; + upper = (Expression) expressions[2]; + if (expressions.length == 4) + step = (Expression) expressions[3]; + break; + case 1: + lower = (Expression) expressions[1]; + if (expressions.length == 3) + step = (Expression) expressions[2]; + break; + case 2: + upper = (Expression) expressions[1]; + if (expressions.length == 3) + step = (Expression) expressions[2]; + break; + default: + throw new IllegalStateException(); + } + } + var logger = parseContext.getLogger(); + if (!list.acceptsChange(ChangeMode.SET, list.getReturnType(), false)) { + logger.error( + list.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' cannot be set to multiple values", + ErrorType.SEMANTIC_ERROR + ); + return false; + } else if (list.isSingle()) { + logger.error( + list.toString(TriggerContext.DUMMY, logger.isDebug()) + " represents a single value", + ErrorType.SEMANTIC_ERROR, + "List operators only work on multiple objects at the same time" + ); + return false; + } + return true; + } - @Override - public Object[] getValues(TriggerContext ctx, boolean isEffect) { - var values = list.getValues(ctx); - if (values.length == 0) - return new Object[0]; + @Override + public Object[] getValues(TriggerContext ctx, boolean isEffect) { + var values = list.getValues(ctx); + if (values.length == 0) + return new Object[0]; - switch (type) { - case 0: - if (isEffect) - list.change(ctx, ChangeMode.SET, Arrays.copyOfRange(values, 0, values.length - 1)); - return new Object[] {values[values.length - 1]}; - case 1: - if (isEffect) - list.change(ctx, ChangeMode.SET, Arrays.copyOfRange(values, 1, values.length)); - return new Object[] {values[0]}; - case 2: - int ind = index.getSingle(ctx) - .filter(n -> Integer.signum(n) > 0 && n.compareTo(Integer.valueOf(values.length)) <= 0) - .map(n -> n.intValue() - 1) - .orElse(-1); - if (ind == -1) { - return new Object[0]; - } + switch (type) { + case 0: + if (isEffect) + list.change(ctx, ChangeMode.SET, Arrays.copyOfRange(values, 0, values.length - 1)); + return new Object[]{values[values.length - 1]}; + case 1: + if (isEffect) + list.change(ctx, ChangeMode.SET, Arrays.copyOfRange(values, 1, values.length)); + return new Object[]{values[0]}; + case 2: + int ind = index.getSingle(ctx) + .filter(n -> Integer.signum(n) > 0 && n.compareTo(Integer.valueOf(values.length)) <= 0) + .map(n -> n.intValue() - 1) + .orElse(-1); + if (ind == -1) { + return new Object[0]; + } - // When used as an effect - if (isEffect) { - var skipped = new Object[values.length - 1]; - for (int i = 0, k = 0; i < values.length; i++) { - if (i == ind) { - continue; - } - skipped[k++] = values[i]; - } - list.change(ctx, ChangeMode.SET, skipped); - } - return new Object[] {values[ind]}; - case 3: - var low = lower != null - ? lower.getSingle(ctx).filter(n -> Integer.signum(n) > 0).map(n -> n.intValue() - 1).orElse(-1) - : 0; - var up = upper != null - ? upper.getSingle(ctx).filter(n -> n.compareTo(Integer.valueOf(values.length)) <= 0).map(Integer::intValue).orElse(values.length) - : values.length; - var st = step != null - ? step.getSingle(ctx).filter(n -> Integer.signum(n) != 0 && n.compareTo(Integer.valueOf(-values.length)) >= 0 && n.compareTo(Integer.valueOf(values.length)) <= 0).map(Integer::intValue).orElse(0) - : 1; + // When used as an effect + if (isEffect) { + var skipped = new Object[values.length - 1]; + for (int i = 0, k = 0; i < values.length; i++) { + if (i == ind) { + continue; + } + skipped[k++] = values[i]; + } + list.change(ctx, ChangeMode.SET, skipped); + } + return new Object[]{values[ind]}; + case 3: + var low = lower != null + ? lower.getSingle(ctx).filter(n -> Integer.signum(n) > 0).map(n -> n.intValue() - 1).orElse(-1) + : 0; + var up = upper != null + ? upper.getSingle(ctx).filter(n -> n.compareTo(Integer.valueOf(values.length)) <= 0).map(Integer::intValue).orElse(values.length) + : values.length; + var st = step != null + ? step.getSingle(ctx).filter(n -> Integer.signum(n) != 0 && n.compareTo(Integer.valueOf(-values.length)) >= 0 && n.compareTo(Integer.valueOf(values.length)) <= 0).map(Integer::intValue).orElse(0) + : 1; - if (st < 0) { - CollectionUtils.reverseArray(values); - st = -st; - int temp = low; - low = up - 1; - up = temp + 1; - } - if (low == -1 || up == -1 || up == 0 || st == 0 || low > up) { - if (isEffect) - list.change(ctx, ChangeMode.SET, new Object[0]); - return new Object[0]; - } else if (low == up) { - // Nothing to change - return new Object[0]; - } + if (st < 0) { + CollectionUtils.reverseArray(values); + st = -st; + int temp = low; + low = up - 1; + up = temp + 1; + } + if (low == -1 || up == -1 || up == 0 || st == 0 || low > up) { + if (isEffect) + list.change(ctx, ChangeMode.SET, new Object[0]); + return new Object[0]; + } else if (low == up) { + // Nothing to change + return new Object[0]; + } - var spliced = new ArrayList<>(); - var changed = new ArrayList<>(); - for (int i = 0; i < values.length; i++) { - if (i >= low && i < up && (i - low) % st == 0) { - spliced.add(values[i]); - } else { - changed.add(values[i]); - } - } + var spliced = new ArrayList<>(); + var changed = new ArrayList<>(); + for (int i = 0; i < values.length; i++) { + if (i >= low && i < up && (i - low) % st == 0) { + spliced.add(values[i]); + } else { + changed.add(values[i]); + } + } - if (isEffect) - list.change(ctx, ChangeMode.SET, changed.toArray()); - return spliced.toArray(new Object[0]); - default: - throw new IllegalStateException(); - } - } + if (isEffect) + list.change(ctx, ChangeMode.SET, changed.toArray()); + return spliced.toArray(new Object[0]); + default: + throw new IllegalStateException(); + } + } - @Override - public boolean isSingle() { - return type != 3; - } + @Override + public boolean isSingle() { + return type != 3; + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - switch (type) { - case 0: - return "pop " + list.toString(ctx, debug); - case 1: - return "poll " + list.toString(ctx, debug); - case 2: - return "extract element number " + index.toString(ctx, debug) + " from " + list.toString(ctx, debug); - case 3: - return "splice " + list.toString(ctx, debug) + " from " + lower.toString(ctx, debug) - + (upper != null ? upper.toString(ctx, debug) : ""); - default: - throw new IllegalStateException(); - } - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + switch (type) { + case 0: + return "pop " + list.toString(ctx, debug); + case 1: + return "poll " + list.toString(ctx, debug); + case 2: + return "extract element number " + index.toString(ctx, debug) + " from " + list.toString(ctx, debug); + case 3: + return "splice " + list.toString(ctx, debug) + " from " + lower.toString(ctx, debug) + + (upper != null ? upper.toString(ctx, debug) : ""); + default: + throw new IllegalStateException(); + } + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprReplace.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprReplace.java index 438cbee1..c01b0440 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprReplace.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExecExprReplace.java @@ -20,124 +20,124 @@ *
* Note that indices in Skript start at one. * + * @author Mwexim * @name Replace * @type EFFECT/EXPRESSION * @pattern replace [(all|every|[the] first|[the] last)] [regex [pattern[s]]] %strings% in %strings% with %string% * @pattern replace [(all|every|[the] first|[the] last)] [regex [pattern[s]]] %strings% with %string% in %strings% - * @since ALPHA - * @author Mwexim * @see ExprElement + * @since ALPHA */ public class ExecExprReplace extends ExecutableExpression { - static { - // TODO add "new" so we can add docs - Parser.getMainRegistration().addExecutableExpression(ExecExprReplace.class, String.class, false, - "replace [(0:all|0:every|1:[the] first|2:[the] last)] [:regex [pattern[s]]] %strings% in %strings% with %string%", - "replace [(0:all|0:every|1:[the] first|2:[the] last)] [:regex [pattern[s]]] %strings% with %string% in %strings%" - ); - } + static { + // TODO add "new" so we can add docs + Parser.getMainRegistration().addExecutableExpression(ExecExprReplace.class, String.class, false, + "replace [(0:all|0:every|1:[the] first|2:[the] last)] [:regex [pattern[s]]] %strings% in %strings% with %string%", + "replace [(0:all|0:every|1:[the] first|2:[the] last)] [:regex [pattern[s]]] %strings% with %string% in %strings%" + ); + } - private Expression toMatch; - private Expression toReplace; - private Expression replacement; + private Expression toMatch; + private Expression toReplace; + private Expression replacement; - private int type; - private boolean regex; + private int type; + private boolean regex; - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - type = parseContext.getNumericMark(); - regex = parseContext.hasMark("regex"); + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + type = parseContext.getNumericMark(); + regex = parseContext.hasMark("regex"); - toMatch = (Expression) expressions[0]; - toReplace = (Expression) expressions[1 + matchedPattern]; - replacement = (Expression) expressions[2 - matchedPattern]; + toMatch = (Expression) expressions[0]; + toReplace = (Expression) expressions[1 + matchedPattern]; + replacement = (Expression) expressions[2 - matchedPattern]; - if (!toReplace.acceptsChange(ChangeMode.SET, toReplace)) { - var logger = parseContext.getLogger(); - logger.error( - "The expression '" - + toReplace.toString(TriggerContext.DUMMY, logger.isDebug()) - + "' cannot be changed", - ErrorType.SEMANTIC_ERROR - ); - return false; - } - return true; - } + if (!toReplace.acceptsChange(ChangeMode.SET, toReplace)) { + var logger = parseContext.getLogger(); + logger.error( + "The expression '" + + toReplace.toString(TriggerContext.DUMMY, logger.isDebug()) + + "' cannot be changed", + ErrorType.SEMANTIC_ERROR + ); + return false; + } + return true; + } - @Override - public String[] getValues(TriggerContext ctx, boolean isEffect) { - String[] replacedValues = toReplace.getValues(ctx); - String[] matchedValues = toMatch.getValues(ctx); - String replacementValue = replacement.getSingle(ctx).orElse(null); - if (replacementValue == null) { - return replacedValues; - } + @Override + public String[] getValues(TriggerContext ctx, boolean isEffect) { + String[] replacedValues = toReplace.getValues(ctx); + String[] matchedValues = toMatch.getValues(ctx); + String replacementValue = replacement.getSingle(ctx).orElse(null); + if (replacementValue == null) { + return replacedValues; + } - for (int i = 0; i < replacedValues.length; i++) { - for (String match : matchedValues) { - String current = replacedValues[i]; - String replaced; - if (regex) { - // The regex pattern must be valid - try { - Pattern.compile(match); - } catch (PatternSyntaxException ignored) { - continue; - } - } - switch (type) { - case 0: - // All occurrences - replaced = regex - ? current.replaceAll(match, replacementValue) - : current.replace(match, replacementValue); - break; - case 1: - // First occurrence - replaced = current.replaceFirst( - regex ? match : Pattern.quote(match), - replacementValue - ); - break; - case 2: - // Last occurrence - // This regex pattern flushes away as many characters as it can, leaving the last occurrence. - Matcher matcher = Pattern.compile(".*(" + match + ")").matcher(current); - if (regex && !matcher.matches()) - continue; + for (int i = 0; i < replacedValues.length; i++) { + for (String match : matchedValues) { + String current = replacedValues[i]; + String replaced; + if (regex) { + // The regex pattern must be valid + try { + Pattern.compile(match); + } catch (PatternSyntaxException ignored) { + continue; + } + } + switch (type) { + case 0: + // All occurrences + replaced = regex + ? current.replaceAll(match, replacementValue) + : current.replace(match, replacementValue); + break; + case 1: + // First occurrence + replaced = current.replaceFirst( + regex ? match : Pattern.quote(match), + replacementValue + ); + break; + case 2: + // Last occurrence + // This regex pattern flushes away as many characters as it can, leaving the last occurrence. + Matcher matcher = Pattern.compile(".*(" + match + ")").matcher(current); + if (regex && !matcher.matches()) + continue; - int lastIndex = regex - ? matcher.start(1) - : current.lastIndexOf(match); - if (lastIndex < 0 || lastIndex >= current.length()) - continue; + int lastIndex = regex + ? matcher.start(1) + : current.lastIndexOf(match); + if (lastIndex < 0 || lastIndex >= current.length()) + continue; - int limitIndex = lastIndex + (regex - ? matcher.group(1).length() - : match.length()); - replaced = current.substring(0, lastIndex) - + replacementValue - + (limitIndex < current.length() ? current.substring(limitIndex) : ""); - break; - default: - throw new IllegalStateException(); - } - replacedValues[i] = replaced; - } - } - if (isEffect) - toReplace.change(ctx, ChangeMode.SET, replacedValues); - return replacedValues; - } + int limitIndex = lastIndex + (regex + ? matcher.group(1).length() + : match.length()); + replaced = current.substring(0, lastIndex) + + replacementValue + + (limitIndex < current.length() ? current.substring(limitIndex) : ""); + break; + default: + throw new IllegalStateException(); + } + replacedValues[i] = replaced; + } + } + if (isEffect) + toReplace.change(ctx, ChangeMode.SET, replacedValues); + return replacedValues; + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return "replace " - + new String[] {"all ", "first ", "last "}[type] + toMatch.toString(ctx, debug) - + " in " + toReplace.toString(ctx, debug) - + " with " + replacement.toString(ctx, debug); - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return "replace " + + new String[]{"all ", "first ", "last "}[type] + toMatch.toString(ctx, debug) + + " in " + toReplace.toString(ctx, debug) + + " with " + replacement.toString(ctx, debug); + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAmount.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAmount.java index 289b93f5..be72184d 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAmount.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAmount.java @@ -16,72 +16,72 @@ * Note that when getting the size of a list variable, it will only return the size of the first layer of elements. * If you want to get the whole list size, including nested layers in a variable, use the recursive size instead. * + * @author Olyno, Mwexim * @name Amount * @type EXPRESSION * @pattern [the] [recursive] (amount|number|size) of %~objects% * @pattern %~objects%'[s] [recursive] (amount|number|size) * @since ALPHA - * @author Olyno, Mwexim */ public class ExprAmount extends PropertyExpression { - static { - Parser.getMainRegistration().newPropertyExpression(ExprAmount.class, Number.class, - "[1:recursive] (amount|number|size)", "~objects") - .name("Amount") - .description("Returns the amount of elements in a given list.") - .examples("set {_size} to size of {_var::*}", - "if size of all players > 10:") - .since("1.0.0") - .register(); - } + static { + Parser.getMainRegistration().newPropertyExpression(ExprAmount.class, Number.class, + "[1:recursive] (amount|number|size)", "~objects") + .name("Amount") + .description("Returns the amount of elements in a given list.") + .examples("set {_size} to size of {_var::*}", + "if size of all players > 10:") + .since("1.0.0") + .register(); + } - private boolean recursive; + private boolean recursive; - @Override - public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { - super.init(expressions, matchedPattern, parseContext); - recursive = parseContext.getNumericMark() == 1; - if (recursive && !(getOwner() instanceof Variable)) { - parseContext.getLogger().error("Getting the recursive size of an expression only applies to variables.", ErrorType.SEMANTIC_ERROR); - return false; - } - return true; - } + @SuppressWarnings("unchecked") + private static long getRecursiveSize(Map map) { + long count = 0; + for (Map.Entry entry : map.entrySet()) { + Object value = entry.getValue(); + if (value instanceof Map) { + count += getRecursiveSize((Map) value); + } else { + count++; + } + } + return count; + } - @SuppressWarnings("unchecked") - @Override - public Number[] getValues(TriggerContext ctx) { - if (recursive) { - var var = ((Variable) getOwner()).getRaw(ctx); - if (var.isPresent()) - return new Number[] { - Integer.valueOf(Math.toIntExact(getRecursiveSize((Map) var.get()))) - }; - } - return new Number[] {Integer.valueOf(getOwner().getValues(ctx).length)}; - } + @Override + public boolean init(Expression @NotNull [] expressions, int matchedPattern, @NotNull ParseContext parseContext) { + super.init(expressions, matchedPattern, parseContext); + recursive = parseContext.getNumericMark() == 1; + if (recursive && !(getOwner() instanceof Variable)) { + parseContext.getLogger().error("Getting the recursive size of an expression only applies to variables.", ErrorType.SEMANTIC_ERROR); + return false; + } + return true; + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return toString(ctx, debug, (recursive ? "recursive " : "") + "size"); - } + @SuppressWarnings("unchecked") + @Override + public Number[] getValues(TriggerContext ctx) { + if (recursive) { + var var = ((Variable) getOwner()).getRaw(ctx); + if (var.isPresent()) + return new Number[]{ + Integer.valueOf(Math.toIntExact(getRecursiveSize((Map) var.get()))) + }; + } + return new Number[]{Integer.valueOf(getOwner().getValues(ctx).length)}; + } - @Override - public boolean isSingle() { - return true; - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return toString(ctx, debug, (recursive ? "recursive " : "") + "size"); + } - @SuppressWarnings("unchecked") - private static long getRecursiveSize(Map map) { - long count = 0; - for (Map.Entry entry : map.entrySet()) { - Object value = entry.getValue(); - if (value instanceof Map) { - count += getRecursiveSize((Map) value); - } else { - count++; - } - } - return count; - } + @Override + public boolean isSingle() { + return true; + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAnswer.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAnswer.java index 55a2cd5c..31714811 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAnswer.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprAnswer.java @@ -12,14 +12,16 @@ * Retrieve the last input of the user in a {@link EffAsk} effect. * This will essentially return the last line of the console. * + * @author ItsTheSky * @name Last Answer * @type EXPRESSION * @pattern [the] [last] (answer|response) * @since ALPHA - * @author ItsTheSky */ public class ExprAnswer implements Expression { + private static final Map answers = new HashMap<>(); + static { // We won't be needing this // Parser.getMainRegistration().addExpression( @@ -30,8 +32,6 @@ public class ExprAnswer implements Expression { // ); } - private static final Map answers = new HashMap<>(); - public static void addAnswer(TriggerContext ctx, String answer) { answers.put(ctx, answer); } @@ -44,8 +44,8 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex @Override public String[] getValues(TriggerContext ctx) { return answers.containsKey(ctx) - ? new String[] {answers.get(ctx)} - : new String[0]; + ? new String[]{answers.get(ctx)} + : new String[0]; } @Override diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprBooleanOperators.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprBooleanOperators.java index 67e42c07..b616312f 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprBooleanOperators.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprBooleanOperators.java @@ -11,17 +11,17 @@ /** * Basic boolean operators. It is possible to use conditions inside the operators. * + * @author Syst3ms * @name Boolean Operators * @pattern not %=boolean% * @pattern %=boolean% (or|\|\|) %=boolean% * @pattern %=boolean% (and|&&) %=boolean% * @since ALPHA - * @author Syst3ms */ public class ExprBooleanOperators implements Expression { static { Parser.getMainRegistration().newExpression( - ExprBooleanOperators.class, Boolean.class, true, + ExprBooleanOperators.class, Boolean.class, true, "not %=boolean%", "%=boolean% (or|\\|\\|) %=boolean%", "%=boolean% (and|&&) %=boolean%") @@ -54,12 +54,12 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex public Boolean[] getValues(TriggerContext ctx) { assert second != null || pattern == 0; return first.getSingle(ctx) - .flatMap(f -> pattern == 0 - ? Optional.of(!f) - : second.getSingle(ctx).map(s -> pattern == 1 ? f || s : f && s) - ) - .map(val -> new Boolean[] {val}) - .orElse(new Boolean[0]); + .flatMap(f -> pattern == 0 + ? Optional.of(!f) + : second.getSingle(ctx).map(s -> pattern == 1 ? f || s : f && s) + ) + .map(val -> new Boolean[]{val}) + .orElse(new Boolean[0]); } @Override diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromHex.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromHex.java index 90a38db1..c471898b 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromHex.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromHex.java @@ -15,41 +15,41 @@ * * A trailing hashtag (#) at the start of the string is allowed, but not necessary. * + * @author Mwexim * @name Color from Hex * @type EXPRESSION * @pattern [the] color (from|of) [the] hex[adecimal] [value] %string% * @since ALPHA - * @author Mwexim */ public class ExprColorFromHex implements Expression { - static { - Parser.getMainRegistration().newExpression(ExprColorFromHex.class, Color.class, true, - "[the] color (from|of) [the] hex[adecimal] [value] %string%") - .name("Color from Hex") - .description("Creates a color from its hexadecimal value.") - .since("1.0.0") - .register(); - } + static { + Parser.getMainRegistration().newExpression(ExprColorFromHex.class, Color.class, true, + "[the] color (from|of) [the] hex[adecimal] [value] %string%") + .name("Color from Hex") + .description("Creates a color from its hexadecimal value.") + .since("1.0.0") + .register(); + } - private Expression hex; + private Expression hex; - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - hex = (Expression) expressions[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + hex = (Expression) expressions[0]; + return true; + } - @Override - public Color[] getValues(TriggerContext ctx) { - return hex.getSingle(ctx) - .flatMap(val -> Color.ofHex(val.startsWith("#") ? val.substring(1) : val)) - .map(val -> new Color[] {val}) - .orElse(new Color[0]); - } + @Override + public Color[] getValues(TriggerContext ctx) { + return hex.getSingle(ctx) + .flatMap(val -> Color.ofHex(val.startsWith("#") ? val.substring(1) : val)) + .map(val -> new Color[]{val}) + .orElse(new Color[0]); + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return "color from hex " + hex.toString(ctx, debug); - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return "color from hex " + hex.toString(ctx, debug); + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromRGB.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromRGB.java index 3b225411..e17dee45 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromRGB.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprColorFromRGB.java @@ -13,49 +13,49 @@ * It is also possible to add the alpha value, which corresponds to the transparency. * If the argument size is not exactly 3 or 4, no color will be created. * + * @author Mwexim * @name Color from RGB * @type EXPRESSION * @pattern [the] color (from|of) [the] rgb[a] [value] %integers% * @since ALPHA - * @author Mwexim */ public class ExprColorFromRGB implements Expression { - static { - Parser.getMainRegistration().newExpression(ExprColorFromRGB.class, Color.class, true, - "[the] color (from|of) [the] rgb[a] [value] %integers%") - .name("Color from RGB") - .description("Creates a color from its RGB values.") - .since("1.0.0") - .register(); - } + static { + Parser.getMainRegistration().newExpression(ExprColorFromRGB.class, Color.class, true, + "[the] color (from|of) [the] rgb[a] [value] %integers%") + .name("Color from RGB") + .description("Creates a color from its RGB values.") + .since("1.0.0") + .register(); + } - private Expression rgb; + private Expression rgb; - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - rgb = (Expression) expressions[0]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + rgb = (Expression) expressions[0]; + return true; + } - @Override - public Color[] getValues(TriggerContext ctx) { - var values = rgb.stream(ctx).map(Integer::intValue).toArray(Integer[]::new); - if (values.length == 3) { - return Color.of(values[0], values[1], values[2]) - .map(val -> new Color[] {val}) - .orElse(new Color[0]); - } else if (values.length == 4) { - return Color.of(values[0], values[1], values[2], values[3]) - .map(val -> new Color[] {val}) - .orElse(new Color[0]); - } else { - return new Color[0]; - } - } + @Override + public Color[] getValues(TriggerContext ctx) { + var values = rgb.stream(ctx).map(Integer::intValue).toArray(Integer[]::new); + if (values.length == 3) { + return Color.of(values[0], values[1], values[2]) + .map(val -> new Color[]{val}) + .orElse(new Color[0]); + } else if (values.length == 4) { + return Color.of(values[0], values[1], values[2], values[3]) + .map(val -> new Color[]{val}) + .orElse(new Color[0]); + } else { + return new Color[0]; + } + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return "color from rgb " + rgb.toString(ctx, debug); - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return "color from rgb " + rgb.toString(ctx, debug); + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java index bde1899e..8151c05f 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprContextValue.java @@ -25,10 +25,6 @@ public class ExprContextValue implements Expression private static final String PATTERN = "[the] [(1:(past|previous)|2:(future|next))] [ctx:(context|event)-]<.+>"; private static final PatternElement CONTEXT_VALUE_PATTERN = PatternParser.parsePattern(PATTERN, new SkriptLogger()).orElseThrow(); - private ContextValue info; - private String value; - private boolean alone; - static { //noinspection unchecked Parser.getMainRegistration().newExpression(ExprContextValue.class, Object.class, false, @@ -40,6 +36,10 @@ public class ExprContextValue implements Expression .register(); } + private ContextValue info; + private String value; + private boolean alone; + @SuppressWarnings("unchecked") @Override @Contract("_, _, _ -> fail") @@ -145,7 +145,7 @@ public boolean isSingle() { @Override public Class getReturnType() { - return this.info.getReturnType().getType().getTypeClass(); + return this.info.getReturnType().type().getTypeClass(); } @Override diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateAgoLater.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateAgoLater.java index 3332c0f3..0ccd80f7 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateAgoLater.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateAgoLater.java @@ -14,54 +14,54 @@ /** * The date that was a certain duration ago or is a certain duration in the future. * + * @author Mwexim * @name Ago/Later * @type EXPRESSION * @pattern %duration% (ago|in the past|before [the] [date] %date%) * @pattern %duration% (later|in the future|(from|after) [the] [date] %date%) * @since ALPHA - * @author Mwexim */ public class ExprDateAgoLater implements Expression { - static { - Parser.getMainRegistration().newExpression( - ExprDateAgoLater.class, - SkriptDate.class, - true, - "%duration% (ago|in the past|before [the] [date] %date%)", - "%duration% (later|in the future|(from|after) [the] [date] %date%)") - .name("Date Ago/Later") - .description("Returns the date that is a certain duration ago or in the future.") - .since("1.0.0") - .register(); - } + static { + Parser.getMainRegistration().newExpression( + ExprDateAgoLater.class, + SkriptDate.class, + true, + "%duration% (ago|in the past|before [the] [date] %date%)", + "%duration% (later|in the future|(from|after) [the] [date] %date%)") + .name("Date Ago/Later") + .description("Returns the date that is a certain duration ago or in the future.") + .since("1.0.0") + .register(); + } - private Expression duration; - @Nullable - private Expression date; - private boolean past; + private Expression duration; + @Nullable + private Expression date; + private boolean past; - @SuppressWarnings("unchecked") - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - past = matchedPattern == 0; - duration = (Expression) expressions[0]; - if (expressions.length == 2) - date = (Expression) expressions[1]; - return true; - } + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + past = matchedPattern == 0; + duration = (Expression) expressions[0]; + if (expressions.length == 2) + date = (Expression) expressions[1]; + return true; + } - @Override - public SkriptDate[] getValues(TriggerContext ctx) { - var actualDate = date != null ? date.getSingle(ctx) : Optional.of(SkriptDate.now()); - return DoubleOptional.ofOptional(actualDate, duration.getSingle(ctx)) - .mapToOptional((da, du) -> new SkriptDate[] {past ? da.minus(du) : da.plus(du)}) - .orElse(new SkriptDate[0]); - } + @Override + public SkriptDate[] getValues(TriggerContext ctx) { + var actualDate = date != null ? date.getSingle(ctx) : Optional.of(SkriptDate.now()); + return DoubleOptional.ofOptional(actualDate, duration.getSingle(ctx)) + .mapToOptional((da, du) -> new SkriptDate[]{past ? da.minus(du) : da.plus(du)}) + .orElse(new SkriptDate[0]); + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return date != null - ? duration.toString(ctx, debug) + (past ? " before date " : " after date ") + date.toString(ctx, debug) - : duration.toString(ctx, debug) + (past ? " in the past" : " in the future"); - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return date != null + ? duration.toString(ctx, debug) + (past ? " before date " : " after date ") + date.toString(ctx, debug) + : duration.toString(ctx, debug) + (past ? " in the past" : " in the future"); + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateNow.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateNow.java index ecef53fa..e6b47a95 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateNow.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateNow.java @@ -11,11 +11,11 @@ /** * The current date, the one from yesterday or the one from tomorrow. * + * @author Mwexim * @name Now * @type EXPRESSION - * @pattern (yesterday|now|tomorrow) + * @pattern (yesterday | now | tomorrow) * @since ALPHA - * @author Mwexim */ public class ExprDateNow implements Expression { static { @@ -30,30 +30,30 @@ public class ExprDateNow implements Expression { .register(); } - private int mark; + private int mark; - @Override - public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - mark = parseContext.getNumericMark(); - return true; - } + @Override + public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { + mark = parseContext.getNumericMark(); + return true; + } - @Override - public SkriptDate[] getValues(TriggerContext ctx) { - switch (mark) { - case 0: - return new SkriptDate[] {SkriptDate.now().minus(Duration.ofDays(1))}; - case 1: - return new SkriptDate[] {SkriptDate.now()}; - case 2: - return new SkriptDate[] {SkriptDate.now().plus(Duration.ofDays(1))}; - default: - throw new IllegalStateException(); - } - } + @Override + public SkriptDate[] getValues(TriggerContext ctx) { + switch (mark) { + case 0: + return new SkriptDate[]{SkriptDate.now().minus(Duration.ofDays(1))}; + case 1: + return new SkriptDate[]{SkriptDate.now()}; + case 2: + return new SkriptDate[]{SkriptDate.now().plus(Duration.ofDays(1))}; + default: + throw new IllegalStateException(); + } + } - @Override - public String toString(TriggerContext ctx, boolean debug) { - return new String[] {"yesterday", "now", "tomorrow"}[mark]; - } + @Override + public String toString(TriggerContext ctx, boolean debug) { + return new String[]{"yesterday", "now", "tomorrow"}[mark]; + } } diff --git a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateTodayAt.java b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateTodayAt.java index 92205576..d7312526 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateTodayAt.java +++ b/src/main/java/io/github/syst3ms/skriptparser/expressions/ExprDateTodayAt.java @@ -13,45 +13,46 @@ /** * Today at a given time. When no time is set, * it will take today's date as it would be midnight. + *

+ * + * @author Mwexim * -+ * @author Mwexim - * @name Today At - * @type EXPRESSION - * @pattern today [at %time%] - * @since ALPHA - */ + * @name Today At + * @type EXPRESSION + * @pattern today [at %time%] + * @since ALPHA + */ public class ExprDateTodayAt implements Expression { - static { - Parser.getMainRegistration().newExpression(ExprDateTodayAt.class, SkriptDate.class, true, - "today [at %time%]") - .name("Today At") - .description("Returns the date of today at a given time. If no time is specified, it will return the date of today at midnight.") - .since("1.0.0") - .register(); - } + static { + Parser.getMainRegistration().newExpression(ExprDateTodayAt.class, SkriptDate.class, true, + "today [at %time%]") + .name("Today At") + .description("Returns the date of today at a given time. If no time is specified, it will return the date of today at midnight.") + .since("1.0.0") + .register(); + } - @Nullable - private Expression