Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void createTestTask(String name, String desc, String environments, int javaVersi
boolean releaseDocs = modifiers.contains(Modifiers.GEN_RELEASE_DOCS)
boolean docs = modifiers.contains(Modifiers.GEN_NIGHTLY_DOCS) || releaseDocs
def artifact = 'build' + File.separator + 'libs' + File.separator
if (junit) {
if (junit || modifiers.contains(Modifiers.DEV_MODE)) {
artifact += 'Skript-JUnit.jar'
} else if (releaseDocs) {
artifact += 'Skript-' + version + '.jar'
Expand All @@ -197,7 +197,8 @@ void createTestTask(String name, String desc, String environments, int javaVersi
}
tasks.register(name, JavaExec) {
description = desc
if (junit) {
boolean devMode = modifiers.contains(Modifiers.DEV_MODE)
if (junit || devMode) {
dependsOn testJar
} else if (releaseDocs) {
dependsOn githubRelease, testNaming
Expand All @@ -207,7 +208,7 @@ void createTestTask(String name, String desc, String environments, int javaVersi
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(javaVersion)
}
if (modifiers.contains(Modifiers.DEV_MODE)) {
if (devMode) {
standardInput = System.in
}
group = 'execution'
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ public void run() {
tainted = true;
try {
getAddonInstance().loadClasses("ch.njol.skript.test.runner");
if (TestMode.JUNIT)
if (TestMode.JUNIT || TestMode.DEV_MODE)
getAddonInstance().loadClasses("org.skriptlang.skript.test.junit.registration");
} catch (IOException e) {
Skript.exception("Failed to load testing environment.");
Expand Down
61 changes: 35 additions & 26 deletions src/main/java/ch/njol/skript/effects/EffCancelEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.util.Utils;
import ch.njol.util.Kleenean;
import org.bukkit.entity.Player;
Expand All @@ -23,6 +22,7 @@
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.lang.script.ScriptWarning;

@Name("Cancel Event")
@Description("Cancels the event (e.g. prevent blocks from being placed, or damage being taken).")
Expand All @@ -38,60 +38,69 @@ public class EffCancelEvent extends Effect {
static {
Skript.registerEffect(EffCancelEvent.class, "cancel [the] event", "uncancel [the] event");
}

private boolean cancel;

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern,
Kleenean isDelayed, ParseResult parseResult) {
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
if (isDelayed == Kleenean.TRUE) {
Skript.error("An event cannot be cancelled after it has already passed", ErrorQuality.SEMANTIC_ERROR);
Skript.error("An event cannot be cancelled after it has already passed");
return false;
}

cancel = matchedPattern == 0;
Class<? extends Event>[] currentEvents = getParser().getCurrentEvents();

if (currentEvents == null)
return false;

if (cancel && getParser().isCurrentEvent(PlayerLoginEvent.class)) {
Skript.error("A connect event cannot be cancelled, but the player may be kicked ('kick player by reason of \"...\"')");
return false;
}
if (cancel && getParser().isCurrentEvent(EntityToggleSwimEvent.class)) {
Skript.error("Cancelling a toggle swim event has no effect");
return false;
}

int cancellable = 0;
for (Class<? extends Event> event : currentEvents) {
if (Cancellable.class.isAssignableFrom(event) || BlockCanBuildEvent.class.isAssignableFrom(event))
return true; // TODO warning if some event(s) cannot be cancelled even though some can (needs a way to be suppressed)
cancellable++;
}

if (getParser().isCurrentEvent(PlayerLoginEvent.class))
Skript.error("A connect event cannot be cancelled, but the player may be kicked ('kick player by reason of \"...\"')", ErrorQuality.SEMANTIC_ERROR);
else
Skript.error(Utils.A(getParser().getCurrentEventName()) + " event cannot be cancelled", ErrorQuality.SEMANTIC_ERROR);
// All events are cancellable.
if (cancellable == currentEvents.length)
return true;
// Some events are cancellable.
if (cancellable > 0) {
if (!getParser().getCurrentScript().suppressesWarning(ScriptWarning.EVENT_CANNOT_BE_CANCELLED))
Skript.warning(Utils.A(getParser().getCurrentEventName()) + " event can be triggered for multiple events, some of which cannot be cancelled.");
return true;
}
// No events are cancellable.
Skript.error(Utils.A(getParser().getCurrentEventName()) + " event cannot be cancelled");
return false;
}

@Override
public void execute(Event event) {
if (event instanceof Cancellable)
((Cancellable) event).setCancelled(cancel);
if (event instanceof PlayerInteractEvent) {
if (event instanceof Cancellable cancellable)
cancellable.setCancelled(cancel);
if (event instanceof PlayerInteractEvent playerInteractEvent) {
EvtClick.interactTracker.eventModified((Cancellable) event);
((PlayerInteractEvent) event).setUseItemInHand(cancel ? Event.Result.DENY : Event.Result.DEFAULT);
((PlayerInteractEvent) event).setUseInteractedBlock(cancel ? Event.Result.DENY : Event.Result.DEFAULT);
} else if (event instanceof BlockCanBuildEvent) {
((BlockCanBuildEvent) event).setBuildable(!cancel);
} else if (event instanceof PlayerDropItemEvent) {
PlayerUtils.updateInventory(((PlayerDropItemEvent) event).getPlayer());
} else if (event instanceof InventoryInteractEvent) {
PlayerUtils.updateInventory(((Player) ((InventoryInteractEvent) event).getWhoClicked()));
playerInteractEvent.setUseItemInHand(cancel ? Event.Result.DENY : Event.Result.DEFAULT);
playerInteractEvent.setUseInteractedBlock(cancel ? Event.Result.DENY : Event.Result.DEFAULT);
} else if (event instanceof BlockCanBuildEvent blockCanBuildEvent) {
blockCanBuildEvent.setBuildable(!cancel);
} else if (event instanceof PlayerDropItemEvent playerDropItemEvent) {
PlayerUtils.updateInventory(playerDropItemEvent.getPlayer());
} else if (event instanceof InventoryInteractEvent inventoryInteractEvent) {
PlayerUtils.updateInventory(((Player) inventoryInteractEvent.getWhoClicked()));
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return (cancel ? "" : "un") + "cancel event";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
}

@Override
protected void execute(Event event) { }
protected void execute(Event event) {}

@Override
public String toString(@Nullable Event event, boolean debug) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/ch/njol/skript/test/runner/EffAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class EffAssert extends Effect {
static {
if (TestMode.ENABLED)
Skript.registerEffect(EffAssert.class,
"assert [:unsafely] <.+> [(1:to fail)] with [error] %string%",
"assert [:unsafely] <.+> [(1:to fail)] with [error] %string%, expected [value] %object%, [and] (received|got) [value] %object%",
"assert [:unsafely] <.+> [(1:to fail)]");
"assert [:unsafely] [that] <.+> [(1:to fail)] with [error] %string%",
"assert [:unsafely] [that] <.+> [(1:to fail)] with [error] %string%, expected [value] %object%, [and] (received|got) [value] %object%",
"assert [:unsafely] [that] <.+> [(1:to fail)]");
}

private @Nullable Condition condition;
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/ch/njol/skript/test/runner/EffDebug.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@
public class EffDebug extends Effect {

static {
if (TestMode.ENABLED)
Skript.registerEffect(EffDebug.class,
"debug [:verbose] %objects%",
"debug-effect <.+>",
"debug-condition <.+>"
);
Skript.registerEffect(EffDebug.class,
"debug [:verbose] %objects%",
"debug-effect <.+>",
"debug-condition <.+>"
);
}

private Expression<?> expressions;
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/ch/njol/skript/test/runner/EffObjectives.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ public String toString(@Nullable Event event, boolean debug) {
return "complete objectives " + objectives.toString(event, debug) + " on junit test " + junit.toString(event, debug);
}

/**
* Complete a JUnit objective on the Java side.
*
* @param test The test name used in the complete objectives string effect.
* @param objectives The objectives setup in the complete objectives string effect
*/
public static void complete(String test, String... objectives) {
completeness.putAll(test, Lists.newArrayList(objectives));
}

/**
* Check if the currently running JUnit test has passed all
* it's required objectives that the script test setup.
Expand Down
16 changes: 7 additions & 9 deletions src/main/java/ch/njol/skript/test/runner/EvtTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
public class EvtTestCase extends SkriptEvent {

static {
if (TestMode.ENABLED && !TestMode.GEN_DOCS) {
Skript.registerEvent("Test Case", EvtTestCase.class, SkriptTestEvent.class, "test %string% [when <.+>]")
.description("Contents represent one test case.")
.examples("")
.since("2.5");
Skript.registerEvent("Test Case", EvtTestCase.class, SkriptTestEvent.class, "test %string% [when <.+>]")
.description("Contents represent one test case.")
.examples("")
.since("2.5");

EventValues.registerEventValue(SkriptTestEvent.class, Block.class, ignored -> SkriptJUnitTest.getBlock());
EventValues.registerEventValue(SkriptTestEvent.class, Location.class, ignored -> SkriptJUnitTest.getTestLocation());
EventValues.registerEventValue(SkriptTestEvent.class, World.class, ignored -> SkriptJUnitTest.getTestWorld());
}
EventValues.registerEventValue(SkriptTestEvent.class, Location.class, ignored -> SkriptJUnitTest.getTestLocation());
EventValues.registerEventValue(SkriptTestEvent.class, World.class, ignored -> SkriptJUnitTest.getTestWorld());
EventValues.registerEventValue(SkriptTestEvent.class, Block.class, ignored -> SkriptJUnitTest.getBlock());
}

private Literal<String> name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ public enum ScriptWarning {
/**
* The code cannot be reached due to a previous statement stopping further execution
*/
UNREACHABLE_CODE("unreachable code");
UNREACHABLE_CODE("unreachable code"),

/**
* Suppressible because an event structure can contain multiple events, and some may be cancellable and others not.
*/
EVENT_CANNOT_BE_CANCELLED("event cannot be cancelled");

private final String warningName;
private final String pattern;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.skriptlang.skript.test.junit.registration;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.NoDoc;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.coll.CollectionUtils;

import org.bukkit.Bukkit;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.Nullable;

@Name("Multiple Cancel Events")
@Description("Test registration to ensure that the 'some events cannot be cancelled' error works.")
@NoDoc
public class MultipleCancellableEvents extends SkriptEvent {

static {
Skript.registerEvent("cancel events test 1", MultipleCancellableEvents.class, CollectionUtils.array(NotCancellableEvent.class, CancellableEvent.class), "cancel events test 1");
Skript.registerEvent("cancel events test 2", MultipleCancellableEvents.class, CancellableEvent.class, "cancel events test 2");
Skript.registerEvent("cancel events test 3", MultipleCancellableEvents.class, NotCancellableEvent.class, "cancel events test 3");
}

public static class CancellableEvent extends Event implements Cancellable {

// Bukkit stuff
private final static HandlerList handlers = new HandlerList();

@Override
public HandlerList getHandlers() {
return handlers;
}

public static HandlerList getHandlerList() {
return handlers;
}

@Override
public boolean isCancelled() {
return false;
}

@Override
public void setCancelled(boolean cancel) {}

}

public static class NotCancellableEvent extends Event {

// Bukkit stuff
private final static HandlerList handlers = new HandlerList();

@Override
public HandlerList getHandlers() {
return handlers;
}

public static HandlerList getHandlerList() {
return handlers;
}

}

static boolean done;

@Override
public boolean init(Literal<?>[] args, int matchedPattern, ParseResult parseResult) {
if (!done) {
done = true;
Bukkit.getScheduler().runTask(Skript.getInstance(), () -> {
Bukkit.getPluginManager().callEvent(new CancellableEvent());
Bukkit.getPluginManager().callEvent(new NotCancellableEvent());
});
}
return true;
}

@Override
public boolean check(Event event) {
return true;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "cancel events test";
}

}
14 changes: 14 additions & 0 deletions src/test/skript/junit/MultipleCancellableEvents.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

on cancel events test 1:
parse:
cancel event
assert that the first element out of the parse logs is "An on cancel events test 1 event can be triggered for multiple events, some of which cannot be cancelled." with "Failed to parse or grab cancel events 1 warning"

on cancel events test 2:
cancel event
assert true is true with "Failed to continue cancel events test 2"

on cancel events test 3:
parse:
cancel event
assert that the first element out of the parse logs is "An on cancel events test 3 event cannot be cancelled" with "Failed to parse or grab cancel events 3 error"