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
30 changes: 21 additions & 9 deletions src/main/java/org/avarion/yaml/TypeConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,33 @@ final class TypeConverter {
static final Logger LOG = Logger.getLogger(TypeConverter.class.getName());

/**
* Per-thread sink for lenient warnings. Always non-null — defaults to {@link #LOG}'s
* {@code warning(String)} so callers don't need to null-check.
* {@link YamlFileInterface#load(Object)} replaces it with the plugin's logger for the
* duration of the load.
* Per-thread sink for lenient warnings, unset unless a caller installs one.
* {@link YamlFileInterface#load(Object)} installs the plugin's logger for the duration
* of the load, then restores what was there before.
*/
private static final ThreadLocal<Consumer<String>> ACTIVE = ThreadLocal.withInitial(() -> LOG::warning);
private static final ThreadLocal<Consumer<String>> ACTIVE = new ThreadLocal<>();

static void warn(String message) {
ACTIVE.get().accept(message);
Consumer<String> sink = ACTIVE.get();
if (sink == null) {
LOG.warning(message);
} else {
sink.accept(message);
}
}

/** Install {@code sink} for the current thread; returns the previous one for restore-in-finally. */
static Consumer<String> pushSink(@NotNull Consumer<String> sink) {
/**
* Install {@code sink} for the current thread; returns the previous one for restore-in-finally.
* A {@code null} sink clears the entry rather than parking a stale reference on a thread that
* may outlive the load — server thread pools are long-lived.
*/
static @Nullable Consumer<String> pushSink(final @Nullable Consumer<String> sink) {
Consumer<String> prev = ACTIVE.get();
ACTIVE.set(sink);
if (sink == null) {
ACTIVE.remove();
} else {
ACTIVE.set(sink);
}
return prev;
}

Expand Down
1 change: 0 additions & 1 deletion src/test/java/org/avarion/yaml/LeniencyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down
9 changes: 9 additions & 0 deletions src/test/java/org/avarion/yaml/testClasses/Sounds.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import org.jetbrains.annotations.NotNull;

/**
* Mirrors a Minecraft-style registry constant: named instances reached through a static
* factory. Deliberately has no public String constructor and no toString() override, so
* YamlWriter falls through to matching the value against a static field.
*/
public class Sounds {
public static final Sounds MY_SOUND_ROCKS = getSound("my.sound.rocks");
public static final Sounds YOUR_SOUND_ROCKS_TOO = getSound("your.sound.rocks.2");
Expand All @@ -15,4 +20,8 @@ public class Sounds {
private Sounds(String name) {
this.name = name;
}

public String getName() {
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ public class StaticFieldTestClass {
// Public static field - should be found
public static final StaticFieldTestClass PUBLIC_INSTANCE = new StaticFieldTestClass("public");

// Private static field - should NOT be found (not public)
// Private static field - should NOT be found (not public). Read only by reflection, in
// YamlWriter#getStaticFieldName: it is the sole case exercising the canAccess(null) == false
// branch, so deleting it drops that method from 8/8 to 7/8 branches covered.
@SuppressWarnings("unused")
private static final StaticFieldTestClass PRIVATE_INSTANCE = new StaticFieldTestClass("private");

// Public static but different value - should NOT match
Expand Down
8 changes: 8 additions & 0 deletions src/test/java/org/bukkit/NamespacedKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import net.kyori.adventure.key.Key;
import org.jetbrains.annotations.NotNull;

/**
* Mirrors the shape of the real Bukkit NamespacedKey, including its namespace/key pair,
* so the reflective lookups in YamlWriter run against a realistic class.
*/
public final class NamespacedKey implements Key {
private final String ns;
private final String key;
Expand All @@ -12,6 +16,10 @@ public NamespacedKey(String ns, String key) {
this.key = key;
}

public @NotNull String getNamespace() {
return ns;
}

@Override
public @NotNull String value() {
return key;
Expand Down