warning cleanup

This commit is contained in:
gnembon committed 2023-02-08 21:13:15 +01:00
1 parent 5ab4a9e442
commit 277872b33c
106 files changed
+4495 -4345

No files matched your search

@@ -104,10 +104,10 @@ public final class AnnotationParser
* @see ScarpetFunction
* @param clazz The class to parse
*/
public static void parseFunctionClass(final Class<?> clazz)
public static void parseFunctionClass(Class<?> clazz)
{
// Only try to instantiate or require concrete classes if there are non-static annotated methods
final Supplier<Object> instanceSupplier = Suppliers.memoize(() -> {
Supplier<Object> instanceSupplier = Suppliers.memoize(() -> {
if (Modifier.isAbstract(clazz.getModifiers()))
{
throw new IllegalArgumentException("Function class must be concrete to support non-static methods! Class: " + clazz.getSimpleName());
@@ -116,14 +116,14 @@ public final class AnnotationParser
{
return clazz.getConstructor().newInstance();
}
catch (final ReflectiveOperationException e)
catch (ReflectiveOperationException e)
{
throw new IllegalArgumentException(
"Couldn't create instance of given " + clazz + ". This is needed for non-static methods. Make sure default constructor is available", e);
}
});
final Method[] methodz = clazz.getDeclaredMethods();
for (final Method method : methodz)
Method[] methodz = clazz.getDeclaredMethods();
for (Method method : methodz)
{
if (!method.isAnnotationPresent(ScarpetFunction.class))
{
@@ -135,7 +135,7 @@ public final class AnnotationParser
throw new IllegalArgumentException("Annotated method '" + method.getName() +"', provided in '"+clazz+"' must not declare checked exceptions");
}
final ParsedFunction function = new ParsedFunction(method, clazz, instanceSupplier);
ParsedFunction function = new ParsedFunction(method, clazz, instanceSupplier);
functionList.add(function);
}
}
@@ -146,9 +146,9 @@ public final class AnnotationParser
*
* @param expr The expression to add every function to
*/
public static void apply(final Expression expr)
public static void apply(Expression expr)
{
for (final ParsedFunction function : functionList)
for (ParsedFunction function : functionList)
{
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
}
@@ -171,52 +171,52 @@ public final class AnnotationParser
private final int scarpetParamCount;
private final Context.Type contextType;
private ParsedFunction(final Method method, final Class<?> originClass, final Supplier<Object> instance)
private ParsedFunction(Method method, Class<?> originClass, Supplier<Object> instance)
{
this.name = method.getName();
this.isMethodVarArgs = method.isVarArgs();
this.methodParamCount = method.getParameterCount();
final Parameter[] methodParameters = method.getParameters();
Parameter[] methodParameters = method.getParameters();
this.valueConverters = new ValueConverter[isMethodVarArgs ? methodParamCount - 1 : methodParamCount];
for (int i = 0; i < this.methodParamCount; i++)
{
final Parameter param = methodParameters[i];
Parameter param = methodParameters[i];
if (!isMethodVarArgs || i != this.methodParamCount - 1) // Varargs converter is separate
{
this.valueConverters[i] = ValueConverter.fromAnnotatedType(param.getAnnotatedType());
}
}
final Class<?> originalVarArgsType = isMethodVarArgs ? methodParameters[methodParamCount - 1].getType().getComponentType() : null;
Class<?> originalVarArgsType = isMethodVarArgs ? methodParameters[methodParamCount - 1].getType().getComponentType() : null;
this.varArgsType = ClassUtils.primitiveToWrapper(originalVarArgsType); // Primitive array cannot be cast to Obj[]
this.primitiveVarArgs = originalVarArgsType != null && originalVarArgsType.isPrimitive();
this.varArgsConverter = isMethodVarArgs ? ValueConverter.fromAnnotatedType(methodParameters[methodParamCount - 1].getAnnotatedType()) : null;
@SuppressWarnings("unchecked") final // Yes. Making a T is not worth
@SuppressWarnings("unchecked") // Yes. Making a T is not worth
OutputConverter<Object> converter = OutputConverter.get((Class<Object>) method.getReturnType());
this.outputConverter = converter;
this.isEffectivelyVarArgs = isMethodVarArgs || Arrays.stream(valueConverters).anyMatch(ValueConverter::consumesVariableArgs);
this.minParams = Arrays.stream(valueConverters).mapToInt(ValueConverter::valueConsumption).sum(); // Note: In !varargs, this is params
int maxParams = this.minParams; // Unlimited == Integer.MAX_VALUE
int setMaxParams = this.minParams; // Unlimited == Integer.MAX_VALUE
if (this.isEffectivelyVarArgs)
{
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
if (maxParams == UNDEFINED_PARAMS)
setMaxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
if (setMaxParams == UNDEFINED_PARAMS)
{
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. "
+ "Provided in " + originClass);
}
if (maxParams == ScarpetFunction.UNLIMITED_PARAMS)
if (setMaxParams == ScarpetFunction.UNLIMITED_PARAMS)
{
maxParams = Integer.MAX_VALUE;
setMaxParams = Integer.MAX_VALUE;
}
if (maxParams < this.minParams)
if (setMaxParams < this.minParams)
{
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
+ "Provided in " + originClass);
}
}
this.maxParams = maxParams;
this.maxParams = setMaxParams;
// Why MethodHandles?
// MethodHandles are blazing fast (in some situations they can even compile to a single invokeVirtual), but slightly complex to work with.
@@ -242,9 +242,9 @@ public final class AnnotationParser
}
@Override
public LazyValue apply(final Context context, final Context.Type t, final List<LazyValue> lazyValues)
public LazyValue apply(Context context, Context.Type t, List<LazyValue> lazyValues)
{
final List<Value> lv = AbstractLazyFunction.unpackLazy(lazyValues, context, contextType);
List<Value> lv = AbstractLazyFunction.unpackLazy(lazyValues, context, contextType);
if (isEffectivelyVarArgs)
{
if (lv.size() < minParams)
@@ -258,12 +258,12 @@ public final class AnnotationParser
+ getUsage());
}
}
final Object[] params = getMethodParams(lv, context, t);
Object[] params = getMethodParams(lv, context, t);
try
{
return outputConverter.convert(handle.invokeExact(params));
}
catch (final Throwable e)
catch (Throwable e)
{
if (e instanceof RuntimeException re)
{
@@ -274,12 +274,12 @@ public final class AnnotationParser
}
// Hot code: Must be optimized
private Object[] getMethodParams(final List<Value> lv, final Context context, final Context.Type theLazyT)
private Object[] getMethodParams(List<Value> lv, Context context, Context.Type theLazyT)
{
final Object[] params = new Object[methodParamCount];
final ListIterator<Value> lvIterator = lv.listIterator();
Object[] params = new Object[methodParamCount];
ListIterator<Value> lvIterator = lv.listIterator();
final int regularArgs = isMethodVarArgs ? methodParamCount - 1 : methodParamCount;
int regularArgs = isMethodVarArgs ? methodParamCount - 1 : methodParamCount;
for (int i = 0; i < regularArgs; i++)
{
params[i] = valueConverters[i].checkAndConvert(lvIterator, context, theLazyT);
@@ -290,14 +290,14 @@ public final class AnnotationParser
}
if (isMethodVarArgs)
{
final int remaining = lv.size() - lvIterator.nextIndex();
final Object[] varArgs;
int remaining = lv.size() - lvIterator.nextIndex();
Object[] varArgs;
if (varArgsConverter.consumesVariableArgs())
{
final List<Object> varArgsList = new ArrayList<>(); // fastutil's is extremely slow in toArray, and we use that
List<Object> varArgsList = new ArrayList<>(); // fastutil's is extremely slow in toArray, and we use that
while (lvIterator.hasNext())
{
final Object obj = varArgsConverter.checkAndConvert(lvIterator, context, theLazyT);
Object obj = varArgsConverter.checkAndConvert(lvIterator, context, theLazyT);
if (obj == null)
{
throw new InternalExpressionException("Incorrect argument passsed to '" + name + "' function.\n" + getUsage());
@@ -326,7 +326,7 @@ public final class AnnotationParser
public String getUsage()
{
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
final StringBuilder builder = new StringBuilder("Usage: '");
StringBuilder builder = new StringBuilder("Usage: '");
builder.append(name);
builder.append('(');
builder.append(Arrays.stream(valueConverters).map(ValueConverter::getTypeName).filter(Objects::nonNull).collect(Collectors.joining(", ")));
@@ -10,6 +10,8 @@ import carpet.script.Context;
import carpet.script.value.ListValue;
import carpet.script.value.Value;
import javax.annotation.Nullable;
/**
* <p>Converts a given {@link ListValue} into a {@link List} of values converted to {@code <T>}.</p>
*
@@ -32,18 +34,20 @@ final class ListConverter<T> implements ValueConverter<List<T>>
return (allowSingletonCreation ? itemConverter.getTypeName() + " or " : "") + "list of " + itemConverter.getTypeName() + "s";
}
@Nullable
@Override
public List<T> convert(final Value value, final Context context)
public List<T> convert(Value value, @Nullable Context context)
{
return value instanceof ListValue ? convertListValue((ListValue) value, context) : allowSingletonCreation ? convertSingleton(value, context) : null;
}
private List<T> convertListValue(final ListValue values, final Context context)
@Nullable
private List<T> convertListValue(ListValue values, @Nullable Context context)
{
final List<T> list = new ArrayList<>(values.getItems().size());
for (final Value value : values)
List<T> list = new ArrayList<>(values.getItems().size());
for (Value value : values)
{
final T converted = itemConverter.convert(value, context);
T converted = itemConverter.convert(value, context);
if (converted == null)
{
return null;
@@ -53,9 +57,10 @@ final class ListConverter<T> implements ValueConverter<List<T>>
return list;
}
private List<T> convertSingleton(final Value val, final Context context)
@Nullable
private List<T> convertSingleton(Value val, @Nullable Context context)
{
final T converted = itemConverter.convert(val, context);
T converted = itemConverter.convert(val, context);
if (converted == null)
{
return null;
@@ -64,7 +69,7 @@ final class ListConverter<T> implements ValueConverter<List<T>>
}
private ListConverter(final AnnotatedType itemType, final boolean allowSingletonCreation)
private ListConverter(AnnotatedType itemType, boolean allowSingletonCreation)
{
itemConverter = ValueConverter.fromAnnotatedType(itemType);
this.allowSingletonCreation = allowSingletonCreation;
@@ -84,11 +89,11 @@ final class ListConverter<T> implements ValueConverter<List<T>>
* @param annotatedType The type to get generics information from
* @return A new {@link ListConverter} for the data specified in the {@link AnnotatedType}
*/
static ListConverter<?> fromAnnotatedType(final AnnotatedType annotatedType)
static ListConverter<?> fromAnnotatedType(AnnotatedType annotatedType)
{
final AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType;
final AnnotatedType itemType = paramType.getAnnotatedActualTypeArguments()[0];
final boolean allowSingletonCreation = annotatedType.isAnnotationPresent(Param.AllowSingleton.class);
AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType;
AnnotatedType itemType = paramType.getAnnotatedActualTypeArguments()[0];
boolean allowSingletonCreation = annotatedType.isAnnotationPresent(Param.AllowSingleton.class);
return new ListConverter<>(itemType, allowSingletonCreation);
}
@@ -20,6 +20,8 @@ import carpet.script.value.BlockValue;
import carpet.script.value.FunctionValue;
import carpet.script.value.Value;
import javax.annotation.Nullable;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@@ -122,7 +124,7 @@ public interface Locator
super();
}
static <R> ValueConverter<R> fromAnnotatedType(final AnnotatedType annoType, final Class<R> type)
static <R> ValueConverter<R> fromAnnotatedType(AnnotatedType annoType, Class<R> type)
{
if (annoType.isAnnotationPresent(Block.class))
{
@@ -146,7 +148,7 @@ public interface Locator
private final boolean anyString;
private final boolean optional;
public BlockLocator(final Block annotation, final Class<R> type)
public BlockLocator(Block annotation, Class<R> type)
{
super();
this.acceptString = annotation.acceptString();
@@ -163,8 +165,9 @@ public interface Locator
}
}
@Nullable
@SuppressWarnings("unchecked")
private static <R> java.util.function.Function<BlockArgument, R> getReturnFunction(final Class<R> type)
private static <R> java.util.function.Function<BlockArgument, R> getReturnFunction(Class<R> type)
{
if (type == BlockArgument.class)
{
@@ -192,9 +195,9 @@ public interface Locator
}
@Override
public R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
final BlockArgument locator = BlockArgument.findIn((CarpetContext) context, valueIterator, 0, acceptString, optional, anyString);
BlockArgument locator = BlockArgument.findIn((CarpetContext) context, valueIterator, 0, acceptString, optional, anyString);
return returnFunction.apply(locator);
}
}
@@ -205,7 +208,7 @@ public interface Locator
private final boolean optionalEntity;
private final boolean returnVec3d;
public Vec3dLocator(final Vec3d annotation, final Class<R> type)
public Vec3dLocator(Vec3d annotation, Class<R> type)
{
this.optionalDirection = annotation.optionalDirection();
this.optionalEntity = annotation.optionalEntity();
@@ -227,10 +230,10 @@ public interface Locator
}
@Override
public R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
final Vector3Argument locator = Vector3Argument.findIn(valueIterator, 0, optionalDirection, optionalEntity);
@SuppressWarnings("unchecked") final R ret = (R) (returnVec3d ? locator.vec : locator);
Vector3Argument locator = Vector3Argument.findIn(valueIterator, 0, optionalDirection, optionalEntity);
@SuppressWarnings("unchecked") R ret = (R) (returnVec3d ? locator.vec : locator);
return ret;
}
}
@@ -241,7 +244,7 @@ public interface Locator
private final boolean allowNone;
private final boolean checkArgs;
FunctionLocator(final Function annotation, final Class<R> type)
FunctionLocator(Function annotation, Class<R> type)
{
super();
this.returnFunctionValue = type == FunctionValue.class;
@@ -258,11 +261,11 @@ public interface Locator
}
@Override
public R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
final Module module = context.host.main;
final FunctionArgument locator = FunctionArgument.findIn(context, module, Lists.newArrayList(valueIterator), 0, allowNone, checkArgs);
@SuppressWarnings("unchecked") final R ret = (R) (returnFunctionValue ? locator.function : locator);
Module module = context.host.main;
FunctionArgument locator = FunctionArgument.findIn(context, module, Lists.newArrayList(valueIterator), 0, allowNone, checkArgs);
@SuppressWarnings("unchecked") R ret = (R) (returnFunctionValue ? locator.function : locator);
return ret;
}
@@ -276,7 +279,7 @@ public interface Locator
private abstract static class AbstractLocator<R> implements ValueConverter<R>, Locator
{
@Override
public R convert(final Value value, final Context context)
public R convert(Value value, @Nullable Context context)
{
throw new UnsupportedOperationException("Cannot call a locator in a parameter that doesn't contain a context!");
}
@@ -13,6 +13,8 @@ import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.Value;
import javax.annotation.Nullable;
/**
* <p>Converts a {@link MapValue} to a {@link Map}, converting all of its contents to their respective types.</p>
*
@@ -37,15 +39,15 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
}
@Override
public Map<K, V> convert(final Value value, final Context context)
public Map<K, V> convert(Value value, @Nullable Context context)
{
final Map<K, V> result = new HashMap<>();
Map<K, V> result = new HashMap<>();
if (value instanceof MapValue)
{
for (final Entry<Value, Value> entry : ((MapValue) value).getMap().entrySet())
for (Entry<Value, Value> entry : ((MapValue) value).getMap().entrySet())
{
final K key = keyConverter.convert(entry.getKey(), context);
final V val = valueConverter.convert(entry.getValue(), context);
K key = keyConverter.convert(entry.getKey(), context);
V val = valueConverter.convert(entry.getValue(), context);
if (key == null || val == null)
{
return null;
@@ -57,7 +59,7 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
return null;
}
private MapConverter(final AnnotatedType keyType, final AnnotatedType valueType)
private MapConverter(AnnotatedType keyType, AnnotatedType valueType)
{
super();
keyConverter = ValueConverter.fromAnnotatedType(keyType);
@@ -80,9 +82,9 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
* @param annotatedType The type to get generics information from
* @return A new {@link MapConverter} for the data specified in the {@link AnnotatedType}
*/
static MapConverter<?, ?> fromAnnotatedType(final AnnotatedType annotatedType)
static MapConverter<?, ?> fromAnnotatedType(AnnotatedType annotatedType)
{
final AnnotatedType[] annotatedGenerics = ((AnnotatedParameterizedType) annotatedType).getAnnotatedActualTypeArguments();
AnnotatedType[] annotatedGenerics = ((AnnotatedParameterizedType) annotatedType).getAnnotatedActualTypeArguments();
return annotatedType.isAnnotationPresent(Param.KeyValuePairs.class)
? new PairConverter<>(annotatedGenerics[0], annotatedGenerics[1], annotatedType.getAnnotation(Param.KeyValuePairs.class))
: new MapConverter<>(annotatedGenerics[0], annotatedGenerics[1]);
@@ -92,7 +94,7 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
{
private final boolean acceptMultiParam;
private PairConverter(final AnnotatedType keyType, final AnnotatedType valueType, final Param.KeyValuePairs config)
private PairConverter(AnnotatedType keyType, AnnotatedType valueType, Param.KeyValuePairs config)
{
super(keyType, valueType);
acceptMultiParam = config.allowMultiparam();
@@ -104,26 +106,28 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
return acceptMultiParam;
}
@Nullable
@Override
public Map<K, V> convert(final Value value, final Context context) {
public Map<K, V> convert(Value value, @Nullable Context context) {
return value instanceof MapValue ? super.convert(value, context)
: value instanceof ListValue ? convertList(((ListValue)value).getItems(), context)
: null; // Multiparam mode can only be used in evalAndConvert
}
private Map<K, V> convertList(final List<Value> valueList, final Context context)
@Nullable
private Map<K, V> convertList(List<Value> valueList, @Nullable Context context)
{
if (valueList.size() % 2 == 1)
{
return null;
}
final Map<K, V> map = new HashMap<>();
final Iterator<Value> val = valueList.iterator();
Map<K, V> map = new HashMap<>();
Iterator<Value> val = valueList.iterator();
while (val.hasNext())
{
final K key = keyConverter.convert(val.next(), context);
final V value = valueConverter.convert(val.next(), context);
K key = keyConverter.convert(val.next(), context);
V value = valueConverter.convert(val.next(), context);
if (key == null || value == null)
{
return null;
@@ -133,20 +137,21 @@ class MapConverter<K, V> implements ValueConverter<Map<K, V>>
return map;
}
@Nullable
@Override
public Map<K, V> checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public Map<K, V> checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
if (!valueIterator.hasNext())
{
return null;
}
final Value val = valueIterator.next();
Value val = valueIterator.next();
if (!acceptMultiParam || val instanceof MapValue || (val instanceof ListValue && !(keyConverter instanceof ListConverter)))
{
return convert(val, context); // @KeyValuePairs Map<List<Something>, Boolean> will not support list consumption
}
final Map<K, V> map = new HashMap<>();
Map<K, V> map = new HashMap<>();
K key = keyConverter.convert(val, context); //First pair is manual since we got it to check for a different conversion mode
V value = valueConverter.checkAndConvert(valueIterator, context, theLazyT);
if (key == null || value == null)
@@ -9,6 +9,8 @@ import java.util.Optional;
import carpet.script.Context;
import carpet.script.value.Value;
import javax.annotation.Nullable;
/**
* <p>{@link ValueConverter} that accepts a parameter to not be present on function call.</p>
*
@@ -49,14 +51,15 @@ final class OptionalConverter<R> implements ValueConverter<Optional<R>>
* @implNote Unlike most other converters, {@link OptionalConverter} will not call this method from
* {@link #checkAndConvert(Iterator, Context, Context.Type)} and is only used as a fallback in types that don't support it.
*/
@Nullable
@Override
public Optional<R> convert(final Value value, final Context context)
public Optional<R> convert(Value value, @Nullable Context context)
{
if (value.isNull())
{
return Optional.empty();
}
final R converted = typeConverter.convert(value, context);
R converted = typeConverter.convert(value, context);
if (converted == null)
{
return null;
@@ -64,15 +67,16 @@ final class OptionalConverter<R> implements ValueConverter<Optional<R>>
return Optional.of(converted);
}
@Nullable
@Override
public Optional<R> checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public Optional<R> checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
if (!valueIterator.hasNext() || valueIterator.next().isNull())
{
return Optional.empty();
}
((ListIterator<Value>) valueIterator).previous();
final R converted = typeConverter.checkAndConvert(valueIterator, context, theLazyT);
R converted = typeConverter.checkAndConvert(valueIterator, context, theLazyT);
if (converted == null)
{
return null;
@@ -106,10 +110,10 @@ final class OptionalConverter<R> implements ValueConverter<Optional<R>>
* @param annotatedType The type to get generics information from
* @return A new {@link OptionalConverter} for the data specified in the {@link AnnotatedType}
*/
static OptionalConverter<?> fromAnnotatedType(final AnnotatedType annotatedType)
static OptionalConverter<?> fromAnnotatedType(AnnotatedType annotatedType)
{
final AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType;
final AnnotatedType wrappedType = paramType.getAnnotatedActualTypeArguments()[0];
AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType;
AnnotatedType wrappedType = paramType.getAnnotatedActualTypeArguments()[0];
return new OptionalConverter<>(wrappedType);
}
}
@@ -23,6 +23,8 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import javax.annotation.Nullable;
/**
* <p>A converter from a given {@link Object} of type T into a {@link LazyValue}, used in order to convert the outputs of methods into usable Scarpet
* values.</p>
@@ -57,7 +59,7 @@ public final class OutputConverter<T>
private final Function<T, LazyValue> converter;
private OutputConverter(final Function<T, LazyValue> converter)
private OutputConverter(Function<T, LazyValue> converter)
{
this.converter = converter;
}
@@ -90,7 +92,7 @@ public final class OutputConverter<T>
* @param input The value to convert
* @return The converted value
*/
public LazyValue convert(final T input)
public LazyValue convert(@Nullable T input)
{
return input == null ? LazyValue.NULL : converter.apply(input);
}
@@ -103,9 +105,9 @@ public final class OutputConverter<T>
* @param inputType The class of T
* @param converter The function that converts the an instance of T to a {@link LazyValue}
*/
public static <T> void register(final Class<T> inputType, final Function<T, LazyValue> converter)
public static <T> void register(Class<T> inputType, Function<T, LazyValue> converter)
{
final OutputConverter<T> instance = new OutputConverter<>(converter);
OutputConverter<T> instance = new OutputConverter<>(converter);
if (byResult.containsKey(inputType))
{
throw new IllegalArgumentException(inputType + " already has a registered OutputConverter");
@@ -122,9 +124,9 @@ public final class OutputConverter<T>
* @param inputType The class of T
* @param converter The function that converts an instance of T to a {@link Value}
*/
public static <T> void registerToValue(final Class<T> inputType, final Function<T, Value> converter)
public static <T> void registerToValue(Class<T> inputType, Function<T, Value> converter)
{
final OutputConverter<T> instance = new OutputConverter<>(converter.andThen(v -> (c, t) -> v));
OutputConverter<T> instance = new OutputConverter<>(converter.andThen(v -> (c, t) -> v));
if (byResult.containsKey(inputType))
{
throw new IllegalArgumentException(inputType + " already has a registered OutputConverter");
@@ -24,6 +24,8 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import javax.annotation.Nullable;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@@ -143,18 +145,23 @@ public interface Param
* <p>A {@link ValueConverter} that outputs the {@link Context} in which the function has been called, and throws {@link UnsupportedOperationException} when trying to convert a {@link Value}
* directly.</p>
*/
static final ValueConverter<Context> CONTEXT_PROVIDER = new ValueConverter<Context>()
static final ValueConverter<Context> CONTEXT_PROVIDER = new ValueConverter<>()
{
@Override public String getTypeName() { return null; }
@Nullable
@Override
public String getTypeName()
{
return null;
}
@Override
public Context convert(final Value value, final Context context)
public Context convert(Value value, @Nullable Context context)
{
throw new UnsupportedOperationException("Called convert() with Value in Context Provider converter, where only checkAndConvert is supported");
}
@Override
public Context checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public Context checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
return context;
}
@@ -170,18 +177,23 @@ public interface Param
* <p>A {@link ValueConverter} that outputs the {@link Context.Type} which the function has been called, or throws {@link UnsupportedOperationException} when trying to convert a {@link Value}
* directly.</p>
*/
static final ValueConverter<Context.Type> CONTEXT_TYPE_PROVIDER = new ValueConverter<Context.Type>()
static final ValueConverter<Context.Type> CONTEXT_TYPE_PROVIDER = new ValueConverter<>()
{
@Override public String getTypeName() { return null; }
@Nullable
@Override
public String getTypeName()
{
return null;
}
@Override
public Context.Type convert(final Value value, final Context context)
public Context.Type convert(Value value, @Nullable Context context)
{
throw new UnsupportedOperationException("Called convert() with a Value in TheLazyT Provider, where only checkAndConvert is supported");
}
@Override
public Context.Type checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type theLazyT)
public Context.Type checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
{
return theLazyT;
}
@@ -214,12 +226,12 @@ public interface Param
* @throws IllegalArgumentException If the type doesn't accept the {@link Strict} annotation or if it has been used incorrectly (shallow in
* unsupported places)
*/
static ValueConverter<?> getStrictConverter(final AnnotatedType type)
static ValueConverter<?> getStrictConverter(AnnotatedType type)
{
final boolean shallow = type.getAnnotation(Strict.class).shallow();
final Class<?> clazz = (Class<?>) type.getType();
final StrictConverterInfo key = new StrictConverterInfo(clazz, shallow);
final ValueConverter<?> converter = strictParamsByClassAndShallowness.get(key);
boolean shallow = type.getAnnotation(Strict.class).shallow();
Class<?> clazz = (Class<?>) type.getType();
StrictConverterInfo key = new StrictConverterInfo(clazz, shallow);
ValueConverter<?> converter = strictParamsByClassAndShallowness.get(key);
if (converter != null)
{
return converter;
@@ -239,9 +251,9 @@ public interface Param
* @param shallow {@code true} if you are registering a shallow-strict parameter, {@code false} if a "fully" strict one
* @param converter The {@link ValueConverter} for the given type and shallowness.
*/
public static <T> void registerStrictConverter(final Class<T> type, final boolean shallow, final ValueConverter<T> converter)
public static <T> void registerStrictConverter(Class<T> type, boolean shallow, ValueConverter<T> converter)
{
final StrictConverterInfo key = new StrictConverterInfo(type, shallow);
StrictConverterInfo key = new StrictConverterInfo(type, shallow);
if (strictParamsByClassAndShallowness.containsKey(key))
{
throw new IllegalArgumentException(type + " already has a registered " + (shallow ? "" : "non-") + "shallow StrictConverter");
@@ -271,16 +283,16 @@ public interface Param
* avoid possible collisions with other extensions.
*/
@SuppressWarnings("unchecked") // this makes no sense... But I guess its preferable to enforce typesafety in callers
public static <T> void registerCustomConverterFactory(final BiFunction<AnnotatedType, Class<T>, ValueConverter<T>> factory)
public static <T> void registerCustomConverterFactory(BiFunction<AnnotatedType, Class<T>, ValueConverter<T>> factory)
{
customFactories.add((BiFunction<AnnotatedType, Class<?>, ValueConverter<?>>) (Object) factory);
}
@SuppressWarnings("unchecked") // Stored correctly
static <R> ValueConverter<R> getCustomConverter(final AnnotatedType annoType, final Class<R> type)
static <R> ValueConverter<R> getCustomConverter(AnnotatedType annoType, Class<R> type)
{
ValueConverter<R> result;
for (final BiFunction<AnnotatedType, Class<?>, ValueConverter<?>> factory : customFactories)
for (BiFunction<AnnotatedType, Class<?>, ValueConverter<?>> factory : customFactories)
{
if ((result = (ValueConverter<R>) factory.apply(annoType, type)) != null)
{
@@ -18,6 +18,8 @@ import carpet.script.value.NumericValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import javax.annotation.Nullable;
/**
* <p>A simple {@link ValueConverter} implementation that converts from a specified subclass of {@link Value} into {@code <R>} by using a given
* function.</p>
@@ -61,7 +63,7 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
*
* @see #SimpleTypeConverter(Class, BiFunction, String)
*/
public SimpleTypeConverter(final Class<T> inputType, final Function<T, R> converter, final String typeName)
public SimpleTypeConverter(Class<T> inputType, Function<T, R> converter, String typeName)
{
this(inputType, (v, c) -> converter.apply(v), typeName);
}
@@ -77,7 +79,7 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
* @param converter The function to convert an instance of inputType into R, with the context of the call.
* @param typeName The name of the type for error messages
*/
public SimpleTypeConverter(final Class<T> inputType, final BiFunction<T, Context, R> converter, final String typeName)
public SimpleTypeConverter(Class<T> inputType, BiFunction<T, Context, R> converter, String typeName)
{
super();
this.converter = converter;
@@ -99,14 +101,15 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
* @return The {@link SimpleTypeConverter} for the specified outputType
*/
@SuppressWarnings("unchecked") // T always extends Value, R is always the same as map's key, since map is private.
static <R> SimpleTypeConverter<Value, R> get(final Class<R> outputType)
static <R> SimpleTypeConverter<Value, R> get(Class<R> outputType)
{
return (SimpleTypeConverter<Value, R>) byResult.get(outputType);
}
@Nullable
@Override
@SuppressWarnings("unchecked") // more than checked. not using class.cast because then "method is too big" for inlining, because javac is useless
public R convert(final Value value, final Context context) // and adds millions of casts. This one is even removed
public R convert(Value value, @Nullable Context context) // and adds millions of casts. This one is even removed
{
return valueClass.isInstance(value) ? converter.apply((T)value, context) : null;
}
@@ -125,8 +128,8 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
*
* @see #registerType(Class, Class, BiFunction, String)
*/
public static <T extends Value, R> void registerType(final Class<T> requiredInputType, final Class<R> outputType,
final Function<T, R> converter, final String typeName)
public static <T extends Value, R> void registerType(Class<T> requiredInputType, Class<R> outputType,
Function<T, R> converter, String typeName)
{
registerType(requiredInputType, outputType, (val, ctx) -> converter.apply(val), typeName);
}
@@ -143,10 +146,10 @@ public final class SimpleTypeConverter<T extends Value, R> implements ValueConve
* can also throw an {@link InternalExpressionException} by itself if really necessary.
* @param typeName The name of the type, following the conventions of {@link ValueConverter#getTypeName()}
*/
public static <T extends Value, R> void registerType(final Class<T> requiredInputType, final Class<R> outputType,
final BiFunction<T, Context, R> converter, final String typeName)
public static <T extends Value, R> void registerType(Class<T> requiredInputType, Class<R> outputType,
BiFunction<T, Context, R> converter, String typeName)
{
final SimpleTypeConverter<T, R> type = new SimpleTypeConverter<>(requiredInputType, converter, typeName);
SimpleTypeConverter<T, R> type = new SimpleTypeConverter<>(requiredInputType, converter, typeName);
byResult.put(outputType, type);
}
}
@@ -18,6 +18,8 @@ import carpet.script.value.StringValue;
import carpet.script.value.ThreadValue;
import carpet.script.value.Value;
import javax.annotation.Nullable;
/**
* <p>Simple {@link ValueConverter} implementation that casts a {@link Value} into one of its subclasses, either for use directly in parameters or
* converters, or as an already working middle step.</p>
@@ -51,7 +53,7 @@ public final class ValueCaster<R> implements ValueConverter<R> // R always exten
private final Class<R> outputType;
private final String typeName;
private ValueCaster(final Class<R> outputType, final String typeName)
private ValueCaster(Class<R> outputType, String typeName)
{
super();
this.outputType = outputType;
@@ -73,14 +75,15 @@ public final class ValueCaster<R> implements ValueConverter<R> // R always exten
*/
@SuppressWarnings("unchecked") // Casters are stored with their exact class, for sure since the map is private (&& class has same generic as
// caster)
public static <R> ValueCaster<R> get(final Class<R> outputType)
public static <R> ValueCaster<R> get(Class<R> outputType)
{
return (ValueCaster<R>) byResult.get(outputType);
}
@Nullable
@Override
@SuppressWarnings("unchecked") // more than checked, see SimpleTypeConverter#converter for reasoning
public R convert(final Value value, final Context context)
public R convert(Value value, @Nullable Context context)
{
if (!outputType.isInstance(value))
{
@@ -98,9 +101,9 @@ public final class ValueCaster<R> implements ValueConverter<R> // R always exten
* required<!--, with the form //Outdated concept <code>(function name) requires a (typeName) to be passed as (argName, if
* available)</code>-->
*/
public static <R extends Value> void register(final Class<R> valueClass, final String typeName)
public static <R extends Value> void register(Class<R> valueClass, String typeName)
{
final ValueCaster<R> caster = new ValueCaster<>(valueClass, typeName);
ValueCaster<R> caster = new ValueCaster<>(valueClass, typeName);
byResult.putIfAbsent(valueClass, caster);
}
}
@@ -9,12 +9,13 @@ import java.util.Objects;
import java.util.Optional;
import org.apache.commons.lang3.ClassUtils;
import org.jetbrains.annotations.Nullable;
import carpet.script.Context;
import carpet.script.annotation.Param.Params;
import carpet.script.value.Value;
import javax.annotation.Nullable;
/**
* <p>Classes implementing this interface are able to convert {@link Value} instances into {@code <R>}, in order to easily use them in parameters for
* Scarpet functions created using the {@link ScarpetFunction} annotation.</p>
@@ -37,6 +38,7 @@ public interface ValueConverter<R>
* @apiNote This method is intended to only be called when an error has occurred and therefore there is a need to print a stacktrace with some
* helpful usage instructions.
*/
@Nullable
String getTypeName();
/**
@@ -63,7 +65,7 @@ public interface ValueConverter<R>
* <p>Even with the above reasons, {@link ValueConverter} users should try to implement {@link #convert(Value, Context)} whenever possible instead of
* {@link #checkAndConvert(Iterator, Context, Context.Type)}, since it allows its usage in generics of lists and maps.</p>
*/
@Nullable R convert(Value value, final Context context);
@Nullable R convert(Value value, @Nullable Context context);
/**
* Old version of {@link #convert(Value)} without taking a {@link Context}.<p>
@@ -75,8 +77,9 @@ public interface ValueConverter<R>
* @return A converted value
* @deprecated Calling this method instead of {@link #convert(Value, Context)} may not return values for some converters
*/
@Nullable
@Deprecated(forRemoval = true)
default R convert(final Value value)
default R convert(Value value)
{
try
{
@@ -130,7 +133,7 @@ public interface ValueConverter<R>
* @return A usable {@link ValueConverter} to convert from a {@link Value} to {@code <R>}
*/
@SuppressWarnings("unchecked")
static <R> ValueConverter<R> fromAnnotatedType(final AnnotatedType annoType)
static <R> ValueConverter<R> fromAnnotatedType(AnnotatedType annoType)
{
Class<R> type = annoType.getType() instanceof ParameterizedType ? // We are defining R here.
(Class<R>) ((ParameterizedType) annoType.getType()).getRawType() :
@@ -208,7 +211,8 @@ public interface ValueConverter<R>
* @implNote This method's default implementation runs the {@link #convert(Value, Context)} function in the next {@link Value} ignoring {@link Context} and
* {@code theLazyT}.
*/
default R checkAndConvert(final Iterator<Value> valueIterator, final Context context, final Context.Type contextType)
@Nullable
default R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type contextType)
{
return !valueIterator.hasNext() ? null : convert(valueIterator.next(), context);
}