Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add condition type to fix parsing order #5809

Merged
merged 11 commits into from
Aug 19, 2024
65 changes: 42 additions & 23 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import ch.njol.skript.events.EvtSkript;
import ch.njol.skript.hooks.Hook;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Condition.ConditionType;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionInfo;
Expand Down Expand Up @@ -85,8 +86,10 @@
import ch.njol.util.StringUtils;
import ch.njol.util.coll.iterator.CheckedIterator;
import ch.njol.util.coll.iterator.EnumerationIterable;

import com.google.common.collect.Lists;
import com.google.gson.Gson;

import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -1375,23 +1378,55 @@ public static SkriptAddon getAddonInstance() {

// ================ CONDITIONS & EFFECTS & SECTIONS ================

private static final Collection<SyntaxElementInfo<? extends Condition>> conditions = new ArrayList<>(50);
private static final Collection<SyntaxElementInfo<? extends Effect>> effects = new ArrayList<>(50);
private static final Collection<SyntaxElementInfo<? extends Statement>> statements = new ArrayList<>(100);
private static final Collection<SyntaxElementInfo<? extends Section>> sections = new ArrayList<>(50);
private static final List<SyntaxElementInfo<? extends Condition>> conditions = new ArrayList<>(50);
private static final List<SyntaxElementInfo<? extends Effect>> effects = new ArrayList<>(50);
private static final List<SyntaxElementInfo<? extends Statement>> statements = new ArrayList<>(100);
private static final List<SyntaxElementInfo<? extends Section>> sections = new ArrayList<>(50);

public static Collection<SyntaxElementInfo<? extends Statement>> getStatements() {
return statements;
}

public static Collection<SyntaxElementInfo<? extends Effect>> getEffects() {
return effects;
}

public static Collection<SyntaxElementInfo<? extends Section>> getSections() {
return sections;
}

// ================ CONDITIONS ================
public static Collection<SyntaxElementInfo<? extends Condition>> getConditions() {
return conditions;
}

private final static int[] conditionTypesStartIndices = new int[ConditionType.values().length];

/**
* registers a {@link Condition}.
*
* @param condition The condition's class
* @param patterns Skript patterns to match this condition
*/
public static <E extends Condition> void registerCondition(final Class<E> condition, final String... patterns) throws IllegalArgumentException {
public static <E extends Condition> void registerCondition(Class<E> condition, String... patterns) throws IllegalArgumentException {
registerCondition(condition, ConditionType.COMBINED, patterns);
}

/**
* registers a {@link Condition}.
*
* @param condition The condition's class
* @param type The conditions {@link ConditionType type}. This is used to determine in which order to try to parse conditions.
* @param patterns Skript patterns to match this condition
*/
public static <E extends Condition> void registerCondition(Class<E> condition, ConditionType type, String... patterns) throws IllegalArgumentException {
checkAcceptRegistrations();
String originClassPath = Thread.currentThread().getStackTrace()[2].getClassName();
final SyntaxElementInfo<E> info = new SyntaxElementInfo<>(patterns, condition, originClassPath);
conditions.add(info);
statements.add(info);
conditions.add(conditionTypesStartIndices[type.ordinal()], info);
statements.add(conditionTypesStartIndices[type.ordinal()], info);
for (int i = type.ordinal(); i < ConditionType.values().length; i++)
conditionTypesStartIndices[i]++;
}

/**
Expand Down Expand Up @@ -1422,22 +1457,6 @@ public static <E extends Section> void registerSection(Class<E> section, String.
sections.add(info);
}

public static Collection<SyntaxElementInfo<? extends Statement>> getStatements() {
return statements;
}

public static Collection<SyntaxElementInfo<? extends Condition>> getConditions() {
return conditions;
}

public static Collection<SyntaxElementInfo<? extends Effect>> getEffects() {
return effects;
}

public static Collection<SyntaxElementInfo<? extends Section>> getSections() {
return sections;
}

// ================ EXPRESSIONS ================

private final static List<ExpressionInfo<?, ?>> expressions = new ArrayList<>(100);
Expand Down
12 changes: 5 additions & 7 deletions src/main/java/ch/njol/skript/conditions/CondCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
package ch.njol.skript.conditions;

import ch.njol.skript.lang.VerboseAssert;

import ch.njol.skript.log.ParseLogHandler;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.ClassInfo;

import org.skriptlang.skript.lang.comparator.Comparator;
import org.skriptlang.skript.lang.comparator.ComparatorInfo;
import org.skriptlang.skript.lang.comparator.Comparators;
import org.skriptlang.skript.lang.comparator.Relation;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
Expand All @@ -45,8 +45,6 @@
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.registrations.Classes;

import org.skriptlang.skript.lang.comparator.Comparators;
import ch.njol.skript.util.Patterns;
import ch.njol.skript.util.Utils;
import ch.njol.util.Checker;
Expand Down Expand Up @@ -95,7 +93,7 @@ public class CondCompare extends Condition implements VerboseAssert {
});

static {
Skript.registerCondition(CondCompare.class, patterns.getPatterns());
Skript.registerCondition(CondCompare.class, ConditionType.PATTERN_MATCHES_EVERYTHING, patterns.getPatterns());
}

private Expression<?> first;
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/ch/njol/skript/conditions/base/PropertyCondition.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ public enum PropertyType {
* also possibly in the negated form
*/
BE,

/**
* Indicates that the condition is in a form of <code>something can something</code>,
* also possibly in the negated form
*/
CAN,

/**
* Indicates that the condition is in a form of <code>something has/have something</code>,
* also possibly in the negated form
Expand Down Expand Up @@ -108,17 +108,17 @@ public static void register(Class<? extends Condition> condition, PropertyType p

switch (propertyType) {
case BE:
Skript.registerCondition(condition,
Skript.registerCondition(condition, ConditionType.PROPERTY,
"%" + type + "% (is|are) " + property,
"%" + type + "% (isn't|is not|aren't|are not) " + property);
break;
case CAN:
Skript.registerCondition(condition,
Skript.registerCondition(condition, ConditionType.PROPERTY,
"%" + type + "% can " + property,
"%" + type + "% (can't|cannot|can not) " + property);
break;
case HAVE:
Skript.registerCondition(condition,
Skript.registerCondition(condition, ConditionType.PROPERTY,
"%" + type + "% (has|have) " + property,
"%" + type + "% (doesn't|does not|do not|don't) have " + property);
break;
Expand All @@ -133,9 +133,9 @@ public static void register(Class<? extends Condition> condition, PropertyType p
}

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
expr = (Expression<? extends T>) expressions[0];

setNegated(matchedPattern == 1);
return true;
}
Expand All @@ -147,7 +147,7 @@ public final boolean check(Event event) {

@Override
public abstract boolean check(T value);

protected abstract String getPropertyName();

protected PropertyType getPropertyType() {
Expand Down Expand Up @@ -176,15 +176,17 @@ public static String toString(Condition condition, PropertyType propertyType, @N
case CAN:
return expr.toString(event, debug) + (condition.isNegated() ? " can't " : " can ") + property;
case HAVE:
if (expr.isSingle())
if (expr.isSingle()) {
return expr.toString(event, debug) + (condition.isNegated() ? " doesn't have " : " has ") + property;
else
} else {
return expr.toString(event, debug) + (condition.isNegated() ? " don't have " : " have ") + property;
}
case WILL:
return expr.toString(event, debug) + (condition.isNegated() ? " won't " : " will ") + "be " + property;
default:
assert false;
throw new AssertionError();
return null;
}
}

}
26 changes: 26 additions & 0 deletions src/main/java/ch/njol/skript/lang/Condition.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,25 @@
*/
public abstract class Condition extends Statement {

public enum ConditionType {
/**
* Conditions that contain other expressions, e.g. "%properties% is/are within %expressions%"
*
* @see #PROPERTY
*/
COMBINED,

/**
* Property conditions, e.g. "%properties% is/are data value[s]"
*/
PROPERTY,

/**
* Conditions whose pattern matches (almost) everything or should be last checked.
*/
PATTERN_MATCHES_EVERYTHING;
}

private boolean negated;

protected Condition() {}
Expand Down Expand Up @@ -67,6 +86,13 @@ public final boolean isNegated() {
return negated;
}

/**
* Parse a raw string input as a condition.
*
* @param input The string input to parse as a condition.
* @param defaultError The error if the condition fails.
* @return Condition if parsed correctly, otherwise null.
*/
public static @Nullable Condition parse(String input, @Nullable String defaultError) {
input = input.trim();
while (input.startsWith("(") && SkriptParser.next(input, 0, ParseContext.DEFAULT) == input.length())
Expand Down
9 changes: 9 additions & 0 deletions src/test/skript/tests/regressions/5804-is-burning.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
test "burning":
spawn a pig at event-location
set {_pig} to the last spawned pig
assert "burning" parsed as damage cause is burning with "burning damage cause compare"
set burning time of {_pig} to 9000 ticks
wait a tick
assert entity within {_pig} is burning with "is burning failed"
assert {_pig} is burning with "is burning failed ##2"
clear entity within {_pig}
Loading