Skip to content
Snippets Groups Projects
Commit 27783c97 authored by sbaffelli's avatar sbaffelli Committed by piotr.kupczyk@id.ethz.ch
Browse files

Improved resolution of generics

parent 8dfa082a
No related branches found
No related tags found
1 merge request!40SSDM-13578 : 2PT : Database and V3 Implementation - include the new AFS "free"...
......@@ -67,9 +67,16 @@ generateTypeScript {
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.property.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.datastore.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.project.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.person.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.**',
'ch.ethz.sis.openbis.generic.OpenBIS'
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.material.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.space.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.common.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.**',
// 'ch.ethz.sis.openbis.generic.OpenBIS',
'ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.archive.ArchiveDataSetsOperation'
]
excludeClassPatterns = ["**.v1.**",
"**.generic.shared.**",
......@@ -78,11 +85,9 @@ generateTypeScript {
"ch.ethz.sis.openbis.generic.asapi.v3.dto.externaldms.search.ExternalDmsSearchCriteria"]
outputKind = 'module'
outputFileType = 'declarationFile'
//customTypeProcessor = "ch.empa.tsprocessor.CustomTypeProcessor"
extensionsWithConfiguration = [ new ConfiguredExtension(className:'ch.empa.tsprocessor.MethodExtension', configuration: ['asnycClasses':['ch.ethz.sis.openbis.generic.OpenBIS']])]
customTypeNaming = ["ch.ethz.sis.openbis.generic.asapi.v3.dto.externaldms.search.ExternalDmsSearchCriteria:ExternalDmsSearchCriteria", "ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.ExternalDmsSearchCriteria:DSExternalDmsSearchCriteria"]
extensionsWithConfiguration = [ new ConfiguredExtension(className:'ch.empa.tsprocessor.MethodExtension', configuration: ['asyncClasses':"[\"ch.ethz.sis.openbis.generic.OpenBIS\"]"])]
jackson2ModuleDiscovery = true
outputFile = file('../api-openbis-javascript/src/v3/openbis.d.ts')
//module = 'dto'
}
package ch.empa.tsprocessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import cz.habarta.typescript.generator.*;
import cz.habarta.typescript.generator.compiler.ModelCompiler;
import cz.habarta.typescript.generator.compiler.Symbol;
import cz.habarta.typescript.generator.compiler.SymbolTable;
import cz.habarta.typescript.generator.compiler.TsModelTransformer;
import cz.habarta.typescript.generator.emitter.*;
import cz.habarta.typescript.generator.parser.BeanModel;
import cz.habarta.typescript.generator.util.Utils;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.fasterxml.jackson.databind.ObjectMapper;// in play 2.3
interface MethodProcessor {
TsPropertyModel makeFunction(Method method, TsModelTransformer.Context context, SymbolTable symbolTable);
TsPropertyModel makeFunction(Method method, SymbolTable symbolTable);
}
public class MethodExtension extends Extension {
static final ObjectMapper mapper = new ObjectMapper();
public static final String CFG_ASYNC_CLASSES = "asyncClasses";
static final ObjectMapper mapper = new ObjectMapper();
private List<String> asnycClasses = new ArrayList<>();
public MethodExtension() {
}
public MethodExtension(List<String> asyncClasses) {
this.asnycClasses = asyncClasses;
}
@Override
public void setConfiguration(Map<String, String> configuration) throws RuntimeException {
if (configuration.containsKey(CFG_ASYNC_CLASSES)) {
String classString = configuration.get(CFG_ASYNC_CLASSES);
try {
String[] classes = mapper.readValue(classString, String[].class);
asnycClasses = Arrays.asList(classes);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println(classString);
}
}
private static String formatAllMethods(TsBeanModel bean) {
System.out.println("MethodExtension.formatAllMethos");
Class<?> origin = bean.getOrigin();
return Arrays.stream(origin.getMethods()).map(method -> method.getName()).collect(Collectors.joining("\n"));
}
private static boolean filterMethods(Method method) {
System.out.println("MethodExtension.filterMethods");
return !((method.getDeclaringClass() == Object.class) || (method.getName().matches("^(set|get|is).*|hashCode|toString|equals")));
return !((method.getDeclaringClass() == Object.class) || (method.getName().matches("hashCode|toString|equals")));
}
private static List<TsParameter> getMethodParameters(Method method, SymbolTable symbolTable) {
System.out.println("MethodExtension.getMethodParameters");
return Arrays.stream(method.getParameters()).map(parameter -> new TsParameter(method.getName(), ResolveGenericType(parameter.getParameterizedType(), symbolTable))).collect(Collectors.toList());
}
......@@ -79,8 +50,16 @@ public class MethodExtension extends Extension {
// Manually map List<T> to Array<T>
TsType elementType = ResolveGenericType(parameterizedType.getActualTypeArguments()[0], symbolTable);
return new TsType.GenericReferenceType(symbolTable.getSymbol(Array.class), Collections.singletonList(elementType));
} else if (Set.class.isAssignableFrom(rawType)) {
// Manually map List<T> to Array<T>
TsType elementType = ResolveGenericType(parameterizedType.getActualTypeArguments()[0], symbolTable);
return new TsType.GenericReferenceType(symbolTable.getSymbol(Set.class), Collections.singletonList(elementType));
} else if (ArrayList.class.isAssignableFrom(rawType)) {
TsType elementType = ResolveGenericType(parameterizedType.getActualTypeArguments()[0], symbolTable);
return new TsType.GenericReferenceType(symbolTable.getSymbol(ArrayList.class), Collections.singletonList(elementType));
} else {
Class<?> rawClass = (Class<?>) parameterizedType.getRawType();
System.out.printf("Other type %s\n", rawClass.getName());
TsType[] typeArguments = Arrays.stream(parameterizedType.getActualTypeArguments()).map(typeArgument -> ResolveGenericType(typeArgument, symbolTable)).toArray(TsType[]::new);
return new TsType.GenericReferenceType(symbolTable.getSymbol(rawClass), Arrays.asList(typeArguments));
}
......@@ -93,32 +72,27 @@ public class MethodExtension extends Extension {
} else if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
final Type[] upperBounds = wildcardType.getUpperBounds();
return upperBounds.length > 0 ? new TsType.ReferenceType(symbolTable.getSymbol(upperBounds[0].getClass())) : TsType.Any;
return upperBounds.length > 0 ? ResolveGenericType(upperBounds[0], symbolTable) : TsType.Any;
} else {
// Handle TypeVariable case
return TsType.Any;
}
}
private static TsType getReturnType(Method method, TsModelTransformer.Context context, SymbolTable symbolTable) {
System.out.println("MethodExtension.getReturnType");
TsType typeParams = ResolveGenericType(method.getGenericReturnType(), symbolTable);
return typeParams;
private static TsType getReturnType(Method method, SymbolTable symbolTable) {
return ResolveGenericType(method.getGenericReturnType(), symbolTable);
}
private static TsPropertyModel makeFunction(Method method, TsModelTransformer.Context context, SymbolTable symbolTable) {
//System.out.println("MethodExtension.makeFunction");
private static TsPropertyModel makeFunction(Method method, SymbolTable symbolTable) {
List<TsParameter> params = getMethodParameters(method, symbolTable);
TsType returnType = getReturnType(method, context, symbolTable);
TsType returnType = getReturnType(method, symbolTable);
return new TsPropertyModel(method.getName(), new TsType.FunctionType(params, returnType), TsModifierFlags.None, false, null);
}
private static TsPropertyModel makeCallBackFunction(Method method, TsModelTransformer.Context context, SymbolTable symbolTable) {
//System.out.println("MethodExtension.makeCallBackFunction");
private static TsPropertyModel makeCallBackFunction(Method method, SymbolTable symbolTable) {
List<TsParameter> params = getMethodParameters(method, symbolTable);
TsType returnType = getReturnType(method, context, symbolTable);
TsType returnType = getReturnType(method, symbolTable);
TsParameter callbackParam = new TsParameter("callback", returnType);
TsType.FunctionType arrowFunction = new TsType.FunctionType(List.of(callbackParam), TsType.Null);
TsParameter callback = new TsParameter("callback", arrowFunction);
......@@ -126,15 +100,39 @@ public class MethodExtension extends Extension {
return new TsPropertyModel(method.getName(), new TsType.FunctionType(paramsWithCallback, TsType.Null), TsModifierFlags.None, false, null);
}
private static TsPropertyModel makePromiseReturningFunction(Method method, SymbolTable symbolTable) {
List<TsParameter> params = getMethodParameters(method, symbolTable);
List<TsType> returnType = List.of(getReturnType(method, symbolTable));
TsType promiseType = new TsType.GenericReferenceType(new Symbol("Promise"), returnType);
return new TsPropertyModel(method.getName(), new TsType.FunctionType(params, promiseType), TsModifierFlags.None, false, null);
}
private static TsBeanModel addFunctions(TsBeanModel bean, TsModelTransformer.Context context, SymbolTable symbolTable, MethodProcessor processor) {
//System.out.println("MethodExtension.addFunction");
Class<?> origin = bean.getOrigin();
Stream<TsPropertyModel> params = Arrays.stream(origin.getMethods()).filter(mt -> filterMethods(mt)).map(method -> processor.makeFunction(method, context, symbolTable));
Stream<TsPropertyModel> params = Arrays.stream(origin.getMethods()).filter(MethodExtension::filterMethods).map(method -> processor.makeFunction(method, symbolTable));
List<TsPropertyModel> allProps = Stream.concat(params, bean.getProperties().stream()).collect(Collectors.toList());
return bean.withProperties(allProps);
}
@Override
public void setConfiguration(Map<String, String> configuration) throws RuntimeException {
if (configuration.containsKey(CFG_ASYNC_CLASSES)) {
String classString = configuration.get(CFG_ASYNC_CLASSES);
try {
TypeScriptGenerator.getLogger().info(String.format("MethodExtension: setConfiguration, %s, %s", configuration, classString));
ArrayList<String> classes = mapper.readValue(classString, new TypeReference<ArrayList<String>>() {
});
asnycClasses = classes;
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println(classString);
}
}
@Override
public EmitterExtensionFeatures getFeatures() {
final EmitterExtensionFeatures features = new EmitterExtensionFeatures();
......@@ -148,29 +146,17 @@ public class MethodExtension extends Extension {
@Override
public List<TransformerDefinition> getTransformers() {
return List.of(new TransformerDefinition(ModelCompiler.TransformationPhase.BeforeSymbolResolution, (TsModelTransformer) (context, model) -> {
//System.out.println("MethodExtension.getTransformers");
Stream<TsBeanModel> processedBeans = model.getBeans().stream().map(bean -> {
System.out.printf("bean: %s\n", (bean.getOrigin().getName()));
if (asnycClasses.contains(bean.getOrigin().getName())){
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeCallBackFunction);
Stream<TsBeanModel> processedBeans = model.getBeans().stream().map(bean -> {
if (asnycClasses.contains(bean.getOrigin().getName())) {
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makePromiseReturningFunction);
} else {
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeFunction);
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeFunction);
}
} );
});
return model.withBeans(processedBeans.collect(Collectors.toList()));
}));
}
public void emitElements(Writer writer, Settings settings, boolean exportKeyword, TsModel model) {
System.out.println("MethodExtension.emitElements");
for (TsBeanModel bean : model.getBeans()) {
//System.out.printf("bean: %s\n", formatAllMethods(bean));
if (bean.isJaxrsApplicationClientBean()) {
final String clientName = bean.getName().getSimpleName();
final String clientFullName = settings.mapPackagesToNamespaces ? bean.getName().getFullName() : bean.getName().getSimpleName();
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment