Skip to content

Commit 1a2bb40

Browse files
authored
Fix bad FunctionRegistry#remove logic (#8015)
* fix bad remove logic * update to pr
1 parent 7c17430 commit 1a2bb40

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

src/main/java/ch/njol/skript/lang/function/FunctionRegistry.java

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,34 @@ public static FunctionRegistry getRegistry() {
6464

6565
/**
6666
* Registers a signature.
67+
* <p>
68+
* Attempting to register a local signature in the global namespace, or a global signature in
69+
* a local namespace, will throw an {@link IllegalArgumentException}.
70+
* </p>
6771
*
6872
* @param namespace The namespace to register the signature in.
6973
* If namespace is null, will register this signature globally.
7074
* Usually represents the path of the script this signature is registered in.
7175
* @param signature The signature to register.
7276
* @throws SkriptAPIException if a signature with the same name and parameters is already registered
7377
* in this namespace.
78+
* @throws IllegalArgumentException if the signature is global and namespace is not null, or
79+
* if the signature is local and namespace is null.
7480
*/
7581
public void register(@Nullable String namespace, @NotNull Signature<?> signature) {
7682
Preconditions.checkNotNull(signature, "signature cannot be null");
83+
if (signature.isLocal() && namespace == null) {
84+
throw new IllegalArgumentException("Cannot register a local signature in the global namespace");
85+
}
86+
if (!signature.isLocal() && namespace != null) {
87+
throw new IllegalArgumentException("Cannot register a global signature in a local namespace");
88+
}
89+
7790
Skript.debug("Registering signature '%s'", signature.getName());
7891

7992
// namespace
8093
NamespaceIdentifier namespaceId;
81-
if (namespace != null && signature.isLocal()) {
94+
if (namespace != null) {
8295
namespaceId = new NamespaceIdentifier(namespace);
8396
} else {
8497
namespaceId = GLOBAL_NAMESPACE;
@@ -118,17 +131,29 @@ public void register(@NotNull Function<?> function) {
118131

119132
/**
120133
* Registers a function.
134+
* <p>
135+
* Attempting to register a local function in the global namespace, or a global function in
136+
* a local namespace, will throw an {@link IllegalArgumentException}.
137+
* </p>
121138
*
122139
* @param namespace The namespace to register the function in.
123-
* If namespace is null, will register this function globally.
140+
* If namespace is null, will register this function globally, only if the function is global.
124141
* Usually represents the path of the script this function is registered in.
125142
* @param function The function to register.
126-
* @throws SkriptAPIException if the function name is invalid or if
127-
* a function with the same name and parameters is already registered
128-
* in this namespace.
143+
* @throws SkriptAPIException if the function name is invalid or if
144+
* a function with the same name and parameters is already registered
145+
* in this namespace.
146+
* @throws IllegalArgumentException if the function is global and namespace is not null, or
147+
* if the function is local and namespace is null.
129148
*/
130149
public void register(@Nullable String namespace, @NotNull Function<?> function) {
131150
Preconditions.checkNotNull(function, "function cannot be null");
151+
if (function.getSignature().isLocal() && namespace == null) {
152+
throw new IllegalArgumentException("Cannot register a local function in the global namespace");
153+
}
154+
if (!function.getSignature().isLocal() && namespace != null) {
155+
throw new IllegalArgumentException("Cannot register a global function in a local namespace");
156+
}
132157
Skript.debug("Registering function '%s'", function.getName());
133158

134159
String name = function.getName();
@@ -138,7 +163,7 @@ public void register(@Nullable String namespace, @NotNull Function<?> function)
138163

139164
// namespace
140165
NamespaceIdentifier namespaceId;
141-
if (namespace != null && function.getSignature().isLocal()) {
166+
if (namespace != null) {
142167
namespaceId = new NamespaceIdentifier(namespace);
143168
} else {
144169
namespaceId = GLOBAL_NAMESPACE;
@@ -487,8 +512,13 @@ public void remove(@NotNull Signature<?> signature) {
487512
String name = signature.getName();
488513
FunctionIdentifier identifier = FunctionIdentifier.of(signature);
489514

490-
Namespace namespace = namespaces.getOrDefault(new NamespaceIdentifier(signature.script),
491-
namespaces.get(GLOBAL_NAMESPACE));
515+
Namespace namespace;
516+
if (signature.isLocal()) {
517+
namespace = namespaces.get(new NamespaceIdentifier(signature.script));
518+
} else {
519+
namespace = namespaces.get(GLOBAL_NAMESPACE);
520+
}
521+
492522
if (namespace == null) {
493523
return;
494524
}
@@ -532,6 +562,7 @@ private record NamespaceIdentifier(@Nullable String name) {
532562

533563
/**
534564
* Returns whether this identifier is for local namespaces.
565+
*
535566
* @return Whether this identifier is for local namespaces.
536567
*/
537568
public boolean local() {

src/main/java/ch/njol/skript/lang/function/Functions.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ public static JavaFunction<?> registerFunction(JavaFunction<?> function) {
104104
namespace.addFunction(function);
105105
}
106106

107-
FunctionRegistry.getRegistry().register(script.getConfig().getFileName(), function);
107+
if (function.getSignature().isLocal()) {
108+
FunctionRegistry.getRegistry().register(script.getConfig().getFileName(), function);
109+
} else {
110+
FunctionRegistry.getRegistry().register(null, function);
111+
}
108112

109113
return function;
110114
}

src/test/java/ch/njol/skript/lang/function/FunctionRegistryTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,4 +388,35 @@ public void testIdentifierSignatureOf() {
388388
assertEquals(FunctionIdentifier.of(function2.getSignature()), identifier);
389389
}
390390

391+
// see https://github.com/SkriptLang/Skript/pull/8015
392+
@Test
393+
public void testRemoveGlobalScriptFunctions8015() {
394+
// create empty TEST_SCRIPT namespace such that it is not null
395+
registry.register(TEST_SCRIPT, LOCAL_TEST_FUNCTION);
396+
registry.remove(LOCAL_TEST_FUNCTION.getSignature());
397+
398+
assertEquals(RetrievalResult.NOT_REGISTERED, registry.getSignature(TEST_SCRIPT, FUNCTION_NAME).result());
399+
400+
// construct a global function with a non-null script, which happens in script functions
401+
Signature<Boolean> signature = new Signature<>(TEST_SCRIPT, FUNCTION_NAME, new Parameter<?>[0],
402+
false, DefaultClasses.BOOLEAN, true, "");
403+
SimpleJavaFunction<Boolean> fn = new SimpleJavaFunction<>(signature) {
404+
@Override
405+
public Boolean @Nullable [] executeSimple(Object[][] params) {
406+
return new Boolean[] { true };
407+
}
408+
};
409+
410+
// ensure new behaviour
411+
assertThrows(IllegalArgumentException.class, () -> registry.register(TEST_SCRIPT, fn));
412+
413+
registry.register(null, fn);
414+
415+
assertEquals(RetrievalResult.EXACT, registry.getSignature(null, FUNCTION_NAME).result());
416+
417+
registry.remove(signature);
418+
419+
assertEquals(RetrievalResult.NOT_REGISTERED, registry.getSignature(null, FUNCTION_NAME).result());
420+
}
421+
391422
}

0 commit comments

Comments
 (0)