Files
fabric-carpet/src/main/java/carpet/script/annotation/ListConverter.java
T
altrisi cc7a9c01be Annotated Scarpet (#772)
* Progress by now.

* Output conversions plus a few extra random things

* More progress, mostly list converting and a way to get converters

* Apply ValueConverters, refactor valueconverter getter to

accept types with annotations and generics, made listconverter pass
those params and annotations recursively. And probably more things.

* Some extra docs, the 100% most important thing

* Added MapConverter, strict Strings and Texts, some docs additions

and commented out heuristics

* Rework StrictParam to use SimpleTypeConverters and be saved in a map

* Minor changes and docs & added non-fully-functional context "converter"

* Added support for variable value count converters, multi-value eaters &

0 value eaters (Context).

* Docs update, enable Context converter, fix minor TODOs

* Move (most) parameter annotations into a single class,

remove deprecated ValueCaster#cast, update some docs.

* Small refactor of Param.Strict registering, added boolean to it

* Added PairConverter, moved Context and LV ValueConverters to Params

* Document public methods of AnnotationParser

* Add a lot more docs, make it ready for the first preview PR

* Move ValueConverter population outside of makeFunction,

check lv size for > max arguments, minor doc updates and workaround for
Mercury#28 until released

* Added optional parameters (declared using Java's Optional),

made evalAndConvert check for the presence of the next iteration,
updated test class

* Generalize Value OutputConverter

* ListConverter and MapConverter now follow ValueConverter contract of

incorrect value handling, returning a complete null for an incorrect
value anywhere. Also small fix to OptionalConverter and docs.
Getting ready for checking null in AnnotationParser!

* Change reflection's #invoke to a MethodHandle to boost speed by a lot

Commented

* Dedupe code, update and remove outdated todos, add 2 new ValueCasters

* Merge lambdas in display_title2 test function to be more accurate

* Check nulls somehow, I guess

* Move base function logic into a class to stop

passing hundreds of parameters into static functions and therefore simplify it

* Reduce visibility and fix a bug with PairConverter

* Hide Context provider in usage report

* Add support for primitive varargs

* Added TheLazyT converter

* Drop #getPrefixedTypeName and use 'something' as name of values

* Use value again because of varargs, document that

* Remove a completed TODO

* Remove old disabled heuristic value type name getter

* Fix TheLazyT

* Preparing locators before touching current Carpet infrastructure

* Add notes about non-implementedness of remaining locators

* Added APIs to register custom ValueConverters

* Mention new APIs in javadocs

* Adapt to new Carpet changes and deprecated non-implemented annotations

* Update example function for display_title()

* Better implementation for player_list example

* Fix example error message

* FunctionArgument no longer has generics

* Modernize Text converters

* OutputConverter is final, plus other small changes

* Few non-behavioural changes

* Rename LazyFunction to ScarpetFunction

* Drop LazyValue in parameters, not in return

Updating docs was a nightmare

* CARPET CHANGE - Make Fluff.AbstractLazyFunction.unpackArgs call unpackLazy (was duped)

* Make errors more like current Scarpet errors

* Allow customizing ContextType when evaluating arguments

* Add a few missing docs, comment out outdated ValueCaster doc

It's been a while, wow

* Fix for new Carpet signature :irritatered:

Please don't break API methods! Extensions may be using them, and they
will just crash the game or behave in unexpected ways else!

* Format all code to Carpet's. Powered by Eclipse

Reviewed to be sure it's ok. No functional changes, except from a small correction

* Always use full name for Context.Type

* Add parsing for all current Scarpet api and language classes

And remove test functions

* Allow void return type

* Fix no param methods

Whoops!

* Remove outdated comment and fix small javadoc linting problem

* Drop Param.TheLazyT in favour of just Context.Type type

And small performance improvement to varargs varargs since fastutil's toArray is crap

* Quote functions in error messages

* Make SimpleTypeConverter independent of ValueCaster

'Real world' usage demonstrated it can be annoying else, mostly for wrapper only values where you just want the wrapped object
2021-05-21 01:33:00 -03:00

91 lines
3.5 KiB
Java

package carpet.script.annotation;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import carpet.script.value.ListValue;
import carpet.script.value.Value;
/**
* <p>Converts a given {@link ListValue} into a {@link List} of values converted to {@code <T>}.</p>
*
* <p>If the {@link Param.AllowSingleton} annotation is specified, allows creating a singleton from
* a loose element compatible with the type conversion.</p>
*
* <p>Lists provided by this converter are <b>not</b> linked to the initial list, and therefore will not
* reflect changes in either of them</p>
*
* @param <T> The type of the element that will be inside the list
*/
final class ListConverter<T> implements ValueConverter<List<T>>
{
private final ValueConverter<T> itemConverter;
private final boolean allowSingletonCreation;
@Override
public String getTypeName()
{
return (allowSingletonCreation ? itemConverter.getTypeName() + " or " : "") + "list of " + itemConverter.getTypeName() + "s";
}
@Override
public List<T> convert(Value value)
{
return value instanceof ListValue ? convertListValue((ListValue) value) : allowSingletonCreation ? convertSingleton(value) : null;
}
private List<T> convertListValue(ListValue values)
{
List<T> list = new ArrayList<>(values.getItems().size());
for (Value value : values)
{
T converted = itemConverter.convert(value);
if (converted == null)
return null;
list.add(converted);
}
return list;
}
private List<T> convertSingleton(Value val)
{
T converted = itemConverter.convert(val);
if (converted == null)
return null;
return Collections.singletonList(converted);
}
private ListConverter(AnnotatedType itemType, boolean allowSingletonCreation)
{
itemConverter = ValueConverter.fromAnnotatedType(itemType);
this.allowSingletonCreation = allowSingletonCreation;
}
/**
* <p>Returns a new {@link ListConverter} to convert to the given {@link AnnotatedType}.</p>
*
* <p>The returned {@link ValueConverter} will convert the objects inside the list to the
* generics specified in the {@link AnnotatedType}, and the {@link ValueConverter} will
* be set to accept non-list (but correct) items and make a singleton out of them
* if the {@link Param.AllowSingleton} annotation has been specified.</p>
*
* @apiNote This method expects the {@link AnnotatedType} to already be of {@link List} type, and, while it will
* technically accept a non-{@link List} {@link AnnotatedType}, it will fail with an {@link ArrayIndexOutOfBoundsException}
* if it doesn't has at least one generic parameter.
* @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(AnnotatedType annotatedType)
{
AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType;
AnnotatedType itemType = paramType.getAnnotatedActualTypeArguments()[0];
boolean allowSingletonCreation = annotatedType.isAnnotationPresent(Param.AllowSingleton.class);
return new ListConverter<>(itemType, allowSingletonCreation);
}
}