Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public boolean isSatisfiedBy(ExperimentSet experimentSet) {
TriggerItem.walk(first, event);
ExprCaughtErrors.lastErrors = catcher.getCachedErrors().stream().map(RuntimeError::error).toArray(String[]::new);
catcher.clearCachedErrors()
.clearCachedFrames()
.stop();
return walk(event, false);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package org.skriptlang.skript.log.runtime;

import ch.njol.skript.Skript;
import ch.njol.skript.log.SkriptLogger;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnmodifiableView;
import org.skriptlang.skript.log.runtime.Frame.FrameOutput;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Level;

/**
Expand All @@ -20,15 +21,21 @@ public class RuntimeErrorCatcher implements RuntimeErrorConsumer {

private final List<RuntimeError> cachedErrors = new ArrayList<>();

private final List<Entry<FrameOutput, Level>> cachedFrames = new ArrayList<>();
// hard limit on stored errors to prevent a runaway loop from filling up memory, for example.
private static final int ERROR_LIMIT = 1000;

public RuntimeErrorCatcher() {}

/**
* Gets the {@link RuntimeErrorManager}.
*/
private RuntimeErrorManager getManager() {
return RuntimeErrorManager.getInstance();
return Skript.getRuntimeErrorManager();
}

@Override
public @Nullable RuntimeErrorFilter getFilter() {
return RuntimeErrorFilter.NO_FILTER; // no filter means everything gets printed.
}

/**
Expand All @@ -47,7 +54,7 @@ public RuntimeErrorCatcher start() {
/**
* Stops this {@link RuntimeErrorCatcher}, removing from {@link RuntimeErrorManager} and restoring the previous
* {@link RuntimeErrorConsumer}s from {@link #storedConsumers}.
* Prints all cached {@link RuntimeError}s, {@link #cachedErrors}, and cached {@link FrameOutput}s, {@link #cachedFrames}.
* Prints all cached {@link RuntimeError}s, {@link #cachedErrors}.
*/
public void stop() {
if (!getManager().removeConsumer(this)) {
Expand All @@ -57,8 +64,6 @@ public void stop() {
getManager().addConsumers(storedConsumers.toArray(RuntimeErrorConsumer[]::new));
for (RuntimeError runtimeError : cachedErrors)
storedConsumers.forEach(consumer -> consumer.printError(runtimeError));
for (Entry<FrameOutput, Level> entry : cachedFrames)
storedConsumers.forEach(consumer -> consumer.printFrameOutput(entry.getKey(), entry.getValue()));
}

/**
Expand All @@ -68,13 +73,6 @@ public void stop() {
return Collections.unmodifiableList(cachedErrors);
}

/**
* Gets all cached {@link FrameOutput}s stored with its corresponding {@link Level} in an {@link Entry}
*/
public @UnmodifiableView List<Entry<FrameOutput, Level>> getCachedFrames() {
return Collections.unmodifiableList(cachedFrames);
}

/**
* Clear all cached {@link RuntimeError}s.
*/
Expand All @@ -83,37 +81,15 @@ public RuntimeErrorCatcher clearCachedErrors() {
return this;
}

/**
* Clears all cached {@link FrameOutput}s.
*/
public RuntimeErrorCatcher clearCachedFrames() {
cachedFrames.clear();
return this;
}

@Override
public void printError(RuntimeError error) {
cachedErrors.add(error);
if (cachedErrors.size() < ERROR_LIMIT)
cachedErrors.add(error);
}

@Override
public void printFrameOutput(FrameOutput output, Level level) {
cachedFrames.add(new Entry<FrameOutput, Level>() {
@Override
public FrameOutput getKey() {
return output;
}

@Override
public Level getValue() {
return level;
}

@Override
public Level setValue(Level value) {
return null;
}
});
// do nothing, this won't be called since we have no filter.
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.skriptlang.skript.log.runtime;

import org.jetbrains.annotations.Nullable;

import java.util.logging.Level;

/**
Expand All @@ -15,6 +17,15 @@ public interface RuntimeErrorConsumer {
*/
void printError(RuntimeError error);

/**
* @return The filter to use when checking if this consumer should print an error. Defaults to the standard
* config-driven filter. If no filter should be used, return {@link RuntimeErrorFilter#NO_FILTER}. This value
* MUST be effectively final.
*/
default @Nullable RuntimeErrorFilter getFilter() {
return RuntimeErrorManager.standardFilter;
}

/**
* Prints the output of a frame, including skipped errors, timeouts, and whatever other information required.
* @param output An output object containing unmodifiable views of the frame data.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.skriptlang.skript.log.runtime;

import org.jetbrains.annotations.NotNull;

import java.util.logging.Level;

/**
* Handles filtering of runtime errors based on their level and predefined limits.
* Uses the concept of 'frames' to track the number of errors and warnings that are allowed in a given period.
* Use {@link #test(RuntimeError)} to determine if a runtime error should be printed or not.
* Printing the frame outputs can be done via {@link #getErrorFrame()} and {@link #getWarningFrame()}.
*/
public class RuntimeErrorFilter {

/**
* A filter that does not filter anything, allowing all errors and warnings to be printed.
* Modifications to its limits will do nothing, and the returned frames will hold no relevant data.
*/
public static final RuntimeErrorFilter NO_FILTER = new RuntimeErrorFilter(
new Frame.FrameLimit(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE),
new Frame.FrameLimit(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE)
) {
@Override
public boolean test(@NotNull RuntimeError error) {
return true;
}
};

private Frame errorFrame, warningFrame;

public RuntimeErrorFilter(Frame.FrameLimit errorFrameLimits, Frame.FrameLimit warningFrameLimits) {
this.errorFrame = new Frame(errorFrameLimits);
this.warningFrame = new Frame(warningFrameLimits);
}

/**
* Tests whether a runtime error should be printed or not.
* @param error True if it should be printed, false if not.
*/
public boolean test(@NotNull RuntimeError error) {
// print if < limit
return (error.level() == Level.SEVERE && errorFrame.add(error))
|| (error.level() == Level.WARNING && warningFrame.add(error));
}

public void setErrorFrameLimits(Frame.FrameLimit limits) {
this.errorFrame = new Frame(limits);
}

public void setWarningFrameLimits(Frame.FrameLimit limits) {
this.warningFrame = new Frame(limits);
}

/**
* @return The frame containing emitted errors.
*/
public Frame getErrorFrame() {
return errorFrame;
}

/**
* @return The frame containing emitted warnings.
*/
public Frame getWarningFrame() {
return warningFrame;
}

}
Loading