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 { ...@@ -67,9 +67,16 @@ generateTypeScript {
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.**', // '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.property.**',
// 'ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.**', // '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.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.**", excludeClassPatterns = ["**.v1.**",
"**.generic.shared.**", "**.generic.shared.**",
...@@ -78,11 +85,9 @@ generateTypeScript { ...@@ -78,11 +85,9 @@ generateTypeScript {
"ch.ethz.sis.openbis.generic.asapi.v3.dto.externaldms.search.ExternalDmsSearchCriteria"] "ch.ethz.sis.openbis.generic.asapi.v3.dto.externaldms.search.ExternalDmsSearchCriteria"]
outputKind = 'module' outputKind = 'module'
outputFileType = 'declarationFile' outputFileType = 'declarationFile'
//customTypeProcessor = "ch.empa.tsprocessor.CustomTypeProcessor" 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: ['asnycClasses':['ch.ethz.sis.openbis.generic.OpenBIS']])] extensionsWithConfiguration = [ new ConfiguredExtension(className:'ch.empa.tsprocessor.MethodExtension', configuration: ['asyncClasses':"[\"ch.ethz.sis.openbis.generic.OpenBIS\"]"])]
jackson2ModuleDiscovery = true jackson2ModuleDiscovery = true
outputFile = file('../api-openbis-javascript/src/v3/openbis.d.ts') outputFile = file('../api-openbis-javascript/src/v3/openbis.d.ts')
//module = 'dto'
} }
package ch.empa.tsprocessor; 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.*;
import cz.habarta.typescript.generator.compiler.ModelCompiler; 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.SymbolTable;
import cz.habarta.typescript.generator.compiler.TsModelTransformer; import cz.habarta.typescript.generator.compiler.TsModelTransformer;
import cz.habarta.typescript.generator.emitter.*; 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.io.IOException;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.fasterxml.jackson.databind.ObjectMapper;// in play 2.3 import com.fasterxml.jackson.databind.ObjectMapper;// in play 2.3
interface MethodProcessor { interface MethodProcessor {
TsPropertyModel makeFunction(Method method, TsModelTransformer.Context context, SymbolTable symbolTable); TsPropertyModel makeFunction(Method method, SymbolTable symbolTable);
} }
public class MethodExtension extends Extension { public class MethodExtension extends Extension {
static final ObjectMapper mapper = new ObjectMapper();
public static final String CFG_ASYNC_CLASSES = "asyncClasses"; public static final String CFG_ASYNC_CLASSES = "asyncClasses";
static final ObjectMapper mapper = new ObjectMapper();
private List<String> asnycClasses = new ArrayList<>(); private List<String> asnycClasses = new ArrayList<>();
public MethodExtension() { public MethodExtension() {
} }
public MethodExtension(List<String> asyncClasses) { public MethodExtension(List<String> asyncClasses) {
this.asnycClasses = 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) { private static boolean filterMethods(Method method) {
System.out.println("MethodExtension.filterMethods"); return !((method.getDeclaringClass() == Object.class) || (method.getName().matches("hashCode|toString|equals")));
return !((method.getDeclaringClass() == Object.class) || (method.getName().matches("^(set|get|is).*|hashCode|toString|equals")));
} }
private static List<TsParameter> getMethodParameters(Method method, SymbolTable symbolTable) { 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()); 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 { ...@@ -79,8 +50,16 @@ public class MethodExtension extends Extension {
// Manually map List<T> to Array<T> // Manually map List<T> to Array<T>
TsType elementType = ResolveGenericType(parameterizedType.getActualTypeArguments()[0], symbolTable); TsType elementType = ResolveGenericType(parameterizedType.getActualTypeArguments()[0], symbolTable);
return new TsType.GenericReferenceType(symbolTable.getSymbol(Array.class), Collections.singletonList(elementType)); 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 { } else {
Class<?> rawClass = (Class<?>) parameterizedType.getRawType(); 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); TsType[] typeArguments = Arrays.stream(parameterizedType.getActualTypeArguments()).map(typeArgument -> ResolveGenericType(typeArgument, symbolTable)).toArray(TsType[]::new);
return new TsType.GenericReferenceType(symbolTable.getSymbol(rawClass), Arrays.asList(typeArguments)); return new TsType.GenericReferenceType(symbolTable.getSymbol(rawClass), Arrays.asList(typeArguments));
} }
...@@ -93,32 +72,27 @@ public class MethodExtension extends Extension { ...@@ -93,32 +72,27 @@ public class MethodExtension extends Extension {
} else if (type instanceof WildcardType) { } else if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type; WildcardType wildcardType = (WildcardType) type;
final Type[] upperBounds = wildcardType.getUpperBounds(); 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 { } else {
// Handle TypeVariable case // Handle TypeVariable case
return TsType.Any; return TsType.Any;
} }
} }
private static TsType getReturnType(Method method, TsModelTransformer.Context context, SymbolTable symbolTable) { private static TsType getReturnType(Method method, SymbolTable symbolTable) {
System.out.println("MethodExtension.getReturnType"); return ResolveGenericType(method.getGenericReturnType(), symbolTable);
TsType typeParams = ResolveGenericType(method.getGenericReturnType(), symbolTable);
return typeParams;
} }
private static TsPropertyModel makeFunction(Method method, SymbolTable symbolTable) {
private static TsPropertyModel makeFunction(Method method, TsModelTransformer.Context context, SymbolTable symbolTable) {
//System.out.println("MethodExtension.makeFunction");
List<TsParameter> params = getMethodParameters(method, 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); 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) { private static TsPropertyModel makeCallBackFunction(Method method, SymbolTable symbolTable) {
//System.out.println("MethodExtension.makeCallBackFunction");
List<TsParameter> params = getMethodParameters(method, symbolTable); List<TsParameter> params = getMethodParameters(method, symbolTable);
TsType returnType = getReturnType(method, context, symbolTable); TsType returnType = getReturnType(method, symbolTable);
TsParameter callbackParam = new TsParameter("callback", returnType); TsParameter callbackParam = new TsParameter("callback", returnType);
TsType.FunctionType arrowFunction = new TsType.FunctionType(List.of(callbackParam), TsType.Null); TsType.FunctionType arrowFunction = new TsType.FunctionType(List.of(callbackParam), TsType.Null);
TsParameter callback = new TsParameter("callback", arrowFunction); TsParameter callback = new TsParameter("callback", arrowFunction);
...@@ -126,15 +100,39 @@ public class MethodExtension extends Extension { ...@@ -126,15 +100,39 @@ public class MethodExtension extends Extension {
return new TsPropertyModel(method.getName(), new TsType.FunctionType(paramsWithCallback, TsType.Null), TsModifierFlags.None, false, null); 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) { private static TsBeanModel addFunctions(TsBeanModel bean, TsModelTransformer.Context context, SymbolTable symbolTable, MethodProcessor processor) {
//System.out.println("MethodExtension.addFunction");
Class<?> origin = bean.getOrigin(); 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()); List<TsPropertyModel> allProps = Stream.concat(params, bean.getProperties().stream()).collect(Collectors.toList());
return bean.withProperties(allProps); 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 @Override
public EmitterExtensionFeatures getFeatures() { public EmitterExtensionFeatures getFeatures() {
final EmitterExtensionFeatures features = new EmitterExtensionFeatures(); final EmitterExtensionFeatures features = new EmitterExtensionFeatures();
...@@ -148,29 +146,17 @@ public class MethodExtension extends Extension { ...@@ -148,29 +146,17 @@ public class MethodExtension extends Extension {
@Override @Override
public List<TransformerDefinition> getTransformers() { public List<TransformerDefinition> getTransformers() {
return List.of(new TransformerDefinition(ModelCompiler.TransformationPhase.BeforeSymbolResolution, (TsModelTransformer) (context, model) -> { return List.of(new TransformerDefinition(ModelCompiler.TransformationPhase.BeforeSymbolResolution, (TsModelTransformer) (context, model) -> {
//System.out.println("MethodExtension.getTransformers"); Stream<TsBeanModel> processedBeans = model.getBeans().stream().map(bean -> {
Stream<TsBeanModel> processedBeans = model.getBeans().stream().map(bean -> { if (asnycClasses.contains(bean.getOrigin().getName())) {
System.out.printf("bean: %s\n", (bean.getOrigin().getName())); return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makePromiseReturningFunction);
if (asnycClasses.contains(bean.getOrigin().getName())){
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeCallBackFunction);
} else { } else {
return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeFunction); return addFunctions(bean, context, context.getSymbolTable(), MethodExtension::makeFunction);
} }
} ); });
return model.withBeans(processedBeans.collect(Collectors.toList())); 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