Skip to content

Commit 2e1d112

Browse files
committed
Add actual keyed returning support
1 parent 6f4575e commit 2e1d112

8 files changed

Lines changed: 70 additions & 15 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public ExprFunctionCall(FunctionReference<?> reference, Class<? extends T>[] exp
3939
Class<?> returnType = Utils.getComponentType(functionReturnType);
4040
if (CollectionUtils.containsSuperclass(expectedReturnTypes, returnType)) {
4141
// Function returns expected type already
42-
this.returnTypes = new Class[] {returnType};
42+
this.returnTypes = new Class[]{returnType};
4343
this.returnType = (Class<T>) returnType;
4444
} else {
4545
// Return value needs to be converted
@@ -55,12 +55,12 @@ public ExprFunctionCall(FunctionReference<?> reference, Class<? extends T>[] exp
5555
if (execute == null) {
5656
values = null;
5757
} else if (!execute.getClass().isArray()) {
58-
values = new Object[] {execute};
58+
values = new Object[]{execute};
5959
} else {
6060
values = (Object[]) execute;
6161
}
6262

63-
String[] keys = reference.function().returnedKeys();
63+
String[] keys = reference.function().getReturnedKeys().toArray(new String[0]);
6464
reference.function().resetReturnValue();
6565

6666
//noinspection unchecked
@@ -71,7 +71,7 @@ public ExprFunctionCall(FunctionReference<?> reference, Class<? extends T>[] exp
7171
}
7272

7373
Converters.convert(values, convertedValues, returnTypes);
74-
if (keys != null) {
74+
if (keys.length > 0) {
7575
for (int i = 0; i < convertedValues.length; i++) {
7676
if (convertedValues[i] == null)
7777
keys[i] = null;

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import ch.njol.skript.SkriptConfig;
44
import ch.njol.skript.classes.ClassInfo;
55
import ch.njol.skript.lang.Expression;
6-
import ch.njol.skript.lang.KeyProviderExpression;
76
import ch.njol.skript.lang.KeyedValue;
87
import ch.njol.util.coll.CollectionUtils;
98
import org.bukkit.Bukkit;
@@ -16,6 +15,8 @@
1615
import org.skriptlang.skript.common.function.ScriptParameter;
1716

1817
import java.util.Arrays;
18+
import java.util.Collections;
19+
import java.util.SequencedCollection;
1920

2021
/**
2122
* Functions can be called using arguments.
@@ -188,6 +189,11 @@ public Class<T> type() {
188189
return null;
189190
}
190191

192+
@Override
193+
public @NotNull SequencedCollection<String> getReturnedKeys() {
194+
return Collections.emptyList();
195+
}
196+
191197
/**
192198
* Resets the return value of the {@code Function}.
193199
* Should be called right after execution.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import java.util.Collections;
1616
import java.util.List;
17+
import java.util.SequencedCollection;
1718

1819
/**
1920
* @deprecated Use {@link DefaultFunction} instead.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.skriptlang.skript.common.function.Parameters;
1616

1717
import java.util.Arrays;
18+
import java.util.SequencedCollection;
1819

1920
public class ScriptFunction<T> extends Function<T> implements ReturnHandler<T> {
2021

src/main/java/org/skriptlang/skript/common/elements/functions/MathFunctions.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ch.njol.skript.Skript;
44
import ch.njol.skript.lang.Expression;
5+
import ch.njol.skript.lang.KeyedValue;
56
import ch.njol.skript.lang.function.Functions;
67
import ch.njol.skript.util.Contract;
78
import ch.njol.util.Math2;
@@ -298,7 +299,7 @@ private static String str(double n) {
298299
"clamp((5, 0, 10, 9, 13), 7, 10) = (7, 7, 10, 9, 10)",
299300
"set {_clamped::*} to clamp({_values::*}, 0, 10)")
300301
.since("2.8.0")
301-
.parameter("values", Number[].class)
302+
.parameter("values", Number[].class, Modifier.KEYED)
302303
.parameter("min", Number.class)
303304
.parameter("max", Number.class)
304305
.contract(new Contract() {
@@ -312,16 +313,19 @@ public Class<?> getReturnType(Expression<?>... arguments) {
312313
return Number.class;
313314
}
314315
})
315-
.build(args -> {
316-
Number[] values = args.get("values");
316+
.buildKeyed(args -> {
317+
KeyedValue<Number>[] values = args.get("values");
318+
return KeyedValue.unzip(values).keys();
319+
}, args -> {
320+
KeyedValue<Number>[] values = args.get("values");
317321
Double[] clampedValues = new Double[values.length];
318322
double min = args.<Number>get("min").doubleValue();
319323
double max = args.<Number>get("max").doubleValue();
320324
// we'll be nice and swap them if they're in the wrong order
321325
double trueMin = Math.min(min, max);
322326
double trueMax = Math.max(min, max);
323327
for (int i = 0; i < values.length; i++) {
324-
double value = values[i].doubleValue();
328+
double value = values[i].value().doubleValue();
325329
if (!Double.isNaN(value) && !Double.isNaN(trueMin) && !Double.isNaN(trueMax)) {
326330
clampedValues[i] = Math.clamp(value, trueMin, trueMax);
327331
} else {

src/main/java/org/skriptlang/skript/common/function/DefaultFunction.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import org.skriptlang.skript.addon.SkriptAddon;
77
import org.skriptlang.skript.common.function.Parameter.Modifier;
88

9+
import java.util.SequencedCollection;
10+
911
/**
1012
* A function that has been implemented in Java, instead of in Skript.
1113
* <p>
@@ -134,6 +136,17 @@ interface Builder<T> {
134136
*/
135137
DefaultFunction<T> build(@NotNull java.util.function.Function<FunctionArguments, T> execute);
136138

139+
/**
140+
* Completes this builder with the code to execute on call of this function.
141+
* Adds a function for setting the returned keys by this function.
142+
*
143+
* @param keys The function which sets the return keys.
144+
* @param execute The code to execute and the key consumer.
145+
* @return The final function.
146+
*/
147+
DefaultFunction<T> buildKeyed(@NotNull java.util.function.Function<FunctionArguments, SequencedCollection<String>> keys,
148+
@NotNull java.util.function.Function<FunctionArguments, T> execute);
149+
137150
}
138151

139152
}

src/main/java/org/skriptlang/skript/common/function/DefaultFunctionImpl.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,24 @@ final class DefaultFunctionImpl<T> extends ch.njol.skript.lang.function.Function
1919
private final SkriptAddon source;
2020
private final SequencedMap<String, Parameter<?>> parameters;
2121
private final Function<FunctionArguments, T> execute;
22+
private final Function<FunctionArguments, SequencedCollection<String>> keys;
2223

2324
private final List<String> description;
2425
private final List<String> since;
2526
private final List<String> examples;
2627
private final List<String> keywords;
2728
private final List<String> requires;
2829

30+
private SequencedCollection<String> returnedKeys;
31+
2932
DefaultFunctionImpl(
3033
SkriptAddon source,
3134
String name,
3235
SequencedMap<String, Parameter<?>> parameters,
3336
Class<T> returnType, boolean single,
3437
@Nullable ch.njol.skript.util.Contract contract,
3538
Function<FunctionArguments, T> execute,
39+
Function<FunctionArguments, SequencedCollection<String>> keys,
3640
String[] description, String[] since, String[] examples,
3741
String[] keywords, String[] requires
3842
) {
@@ -47,6 +51,7 @@ final class DefaultFunctionImpl<T> extends ch.njol.skript.lang.function.Function
4751
this.source = source;
4852
this.parameters = parameters;
4953
this.execute = execute;
54+
this.keys = keys;
5055
this.description = description != null ? List.of(description) : Collections.emptyList();
5156
this.since = since != null ? List.of(since) : Collections.emptyList();
5257
this.examples = examples != null ? List.of(examples) : Collections.emptyList();
@@ -100,6 +105,7 @@ final class DefaultFunctionImpl<T> extends ch.njol.skript.lang.function.Function
100105
}
101106

102107
FunctionArgumentsImpl arguments = new FunctionArgumentsImpl(args);
108+
returnedKeys = keys.apply(arguments);
103109
T result = execute.apply(arguments);
104110

105111
if (result == null) {
@@ -133,6 +139,7 @@ public T execute(@NotNull FunctionEvent<?> event, @NotNull FunctionArguments arg
133139
}
134140
}
135141

142+
returnedKeys = keys.apply(arguments);
136143
return execute.apply(arguments);
137144
}
138145

@@ -141,6 +148,16 @@ public boolean resetReturnValue() {
141148
return true;
142149
}
143150

151+
@Override
152+
public @NotNull String @Nullable [] returnedKeys() {
153+
return returnedKeys.toArray(new String[0]);
154+
}
155+
156+
@Override
157+
public @NotNull SequencedCollection<String> getReturnedKeys() {
158+
return returnedKeys;
159+
}
160+
144161
@Override
145162
public @NotNull String name() {
146163
return getName();
@@ -273,7 +290,19 @@ public DefaultFunction<T> build(@NotNull Function<FunctionArguments, T> execute)
273290
Preconditions.checkNotNull(execute, "execute cannot be null");
274291

275292
return new DefaultFunctionImpl<>(source, name, parameters,
276-
returnType, !returnType.isArray(), contract, execute,
293+
returnType, !returnType.isArray(), contract, execute, (_) -> Collections.emptyList(),
294+
description, since, examples, keywords, requires);
295+
}
296+
297+
@Override
298+
public DefaultFunction<T> buildKeyed(@NotNull Function<FunctionArguments, SequencedCollection<String>> keys,
299+
@NotNull Function<FunctionArguments, T> execute) {
300+
Preconditions.checkNotNull(execute, "execute cannot be null");
301+
Preconditions.checkArgument(parameters.values().stream().anyMatch(it -> it.hasModifier(Modifier.KEYED)),
302+
"buildKeyed cannot be called without any keyed arguments");
303+
304+
return new DefaultFunctionImpl<>(source, name, parameters,
305+
returnType, !returnType.isArray(), contract, execute, keys,
277306
description, since, examples, keywords, requires);
278307
}
279308

@@ -293,10 +322,10 @@ private static void checkNotNull(@NotNull String[] strings, @NotNull String mess
293322
/**
294323
* A parameter for a {@link DefaultFunction}.
295324
*
296-
* @param name The name.
297-
* @param type The type's class.
325+
* @param name The name.
326+
* @param type The type's class.
298327
* @param modifiers The modifiers.
299-
* @param <T> The type.
328+
* @param <T> The type.
300329
*/
301330
record DefaultParameter<T>(String name, Class<T> type, Set<Modifier> modifiers)
302331
implements Parameter<T> {

src/main/java/org/skriptlang/skript/common/function/Function.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import org.jetbrains.annotations.NotNull;
88
import org.jetbrains.annotations.Nullable;
99

10+
import java.util.SequencedCollection;
11+
1012
/**
1113
* Represents a function implementation.
1214
*
@@ -41,7 +43,6 @@ public interface Function<T> {
4143
/**
4244
* @return The returned keys.
4345
*/
44-
@Experimental
45-
@NotNull String @Nullable [] returnedKeys();
46+
@NotNull SequencedCollection<String> getReturnedKeys();
4647

4748
}

0 commit comments

Comments
 (0)