Skip to content

Commit

Permalink
implement LitAnyItem, basic tests, fix parser bug that wasn't attempt…
Browse files Browse the repository at this point in the history
…ing all literals.
  • Loading branch information
sovdeeth committed Feb 7, 2025
1 parent e1565dc commit d72470e
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 4 deletions.
4 changes: 1 addition & 3 deletions src/main/java/ch/njol/skript/aliases/Aliases.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ public abstract class Aliases {

static {
everything.setAll(true);
ItemData all = new ItemData(Material.AIR);
all.isAnything = true;
everything.add(all);
everything.add(ItemData.wildcard());
}

@Nullable
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/ch/njol/skript/aliases/ItemData.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ public static class OldItemData {
* Some properties about this item.
*/
int itemFlags;


public static ItemData wildcard() {
ItemData data = new ItemData(Material.AIR);
data.isAnything = true;
return data;
}

public ItemData(Material type, @Nullable String tags) {
this.type = type;

Expand Down Expand Up @@ -148,6 +154,8 @@ public ItemData(ItemData data) {
this.isAlias = data.isAlias;
this.plain = data.plain;
this.itemFlags = data.itemFlags;
this.isAnything = data.isAnything;
this.itemForm = data.itemForm;
}

public ItemData(Material material, @Nullable BlockValues values) {
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/ch/njol/skript/lang/SkriptParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import ch.njol.util.NonNullPair;
import ch.njol.util.StringUtils;
import ch.njol.util.coll.CollectionUtils;
import ch.njol.util.coll.iterator.CheckedIterator;
import com.google.common.primitives.Booleans;
import org.bukkit.event.Event;
import org.bukkit.plugin.java.JavaPlugin;
Expand Down Expand Up @@ -577,6 +578,55 @@ public boolean hasTag(String tag) {
log.printError();
return null;
}

// try to parse as Literal expression

//noinspection rawtypes,unchecked
Literal<?> parsedLiteral = (Literal<?>) parse(expr,
new CheckedIterator<SyntaxElementInfo<SyntaxElement>>((Iterator) Skript.getExpressions(types),
type -> type != null && Literal.class.isAssignableFrom(type.getElementClass())),
null);
if (parsedLiteral != null) { // Expression/VariableString parsing success
Class<?> parsedReturnType = parsedLiteral.getReturnType();
for (int i = 0; i < types.length; i++) {
Class<?> type = types[i];
if (type == null) // Ignore invalid (null) types
continue;

// Check return type against the expression's return type
if (type.isAssignableFrom(parsedReturnType)) {
if (!exprInfo.isPlural[i] && !parsedLiteral.isSingle()) { // Wrong number of arguments
if (context == ParseContext.COMMAND) {
Skript.error(Commands.m_too_many_arguments.toString(exprInfo.classes[i].getName().getIndefiniteArticle(), exprInfo.classes[i].getName().toString()));
} else {
Skript.error("'" + expr + "' can only accept a single " + exprInfo.classes[i].getName() + ", not more");
}
return null;
}

log.printLog();
return parsedLiteral;
}
}

if (onlySingular && !parsedLiteral.isSingle()) {
Skript.error("'" + expr + "' can only accept singular expressions, not plural");
return null;
}

// No directly same type found
Literal<?> convertedLiteral = parsedLiteral.getConvertedExpression((Class<Object>[]) types);
if (convertedLiteral != null) {
log.printLog();
return convertedLiteral;
}

// Print errors, if we couldn't get the correct type
log.printError(parsedLiteral.toString(null, false) + " " + Language.get("is") + " " + notOfType(types), ErrorQuality.NOT_AN_EXPRESSION);
return null;
}
log.clear();

if (exprInfo.classes[0].getC() == Object.class) {
// Do check if a literal with this name actually exists before returning an UnparsedLiteral
if (!allowUnparsedLiteral || Classes.parseSimple(expr, Object.class, context) == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.skriptlang.skript.bukkit.tags.elements;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemData;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleLiteral;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Material;
import org.bukkit.Tag;

import java.util.Objects;

public class LitAnyItem extends SimpleLiteral<ItemType> {

static {
Skript.registerExpression(LitAnyItem.class, ItemType.class, ExpressionType.SIMPLE,
"[an[y]] item [tagged as %-minecrafttag%]",
"all items [tagged as %-minecrafttag%]");
}

public LitAnyItem() {
super(CollectionUtils.array(new ItemType(ItemData.wildcard())), ItemType.class, true);
}

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
Expression<?> tagExpression = expressions[0];
if (tagExpression != null) {
if (!(tagExpression.simplify() instanceof Literal)) {
Skript.error("The tag in an any/all item expression must be a literal.");
return false;
}
// filter by tag
Tag<?> tag = (Tag<?>) ((Literal<?>) tagExpression.simplify()).getSingle();
Material[] values = tag.getValues().stream()
.filter(Objects::nonNull)
.filter(Material.class::isInstance)
.toArray(Material[]::new);
if (values.length == 0) {
Skript.error("The tag in an any/all item expression must be a tag of materials.");
return false;
}
this.data[0] = new ItemType(values);
}
if (matchedPattern == 1)
this.data[0].setAll(true);
return true;
}
}
22 changes: 22 additions & 0 deletions src/test/skript/tests/syntaxes/expressions/LitAnyItem.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
test "any item literal":
assert a diamond sword is any item with "diamond sword should be in any item"
assert a diamond sword is an item with "diamond sword should be an item"
assert a diamond sword is an item type with "diamond sword should be an item type"
assert a diamond sword is an item tagged as (tag "swords") with "diamond sword should be an item tagged as 'swords'"

parse:
results: {LitAnyItem::parse-a::*}
code:
on right click with any item tagged as tag "pickaxes":
broadcast "test"

parse:
results: {LitAnyItem::parse-b::*}
code:
on right click with any item tagged as tag {_tag}:
broadcast "test"


test "any item literal parse check":
assert {LitAnyItem::parse-a::*} is not set with "Any item literal failed to parse"
assert {LitAnyItem::parse-b::*} is "The tag in an any/all item expression must be a literal." with "Any item literal didn't fail properly when given a non-literal tag"

0 comments on commit d72470e

Please sign in to comment.