From 4f15c19f0dd4cf05b71da463b54cd6790276a607 Mon Sep 17 00:00:00 2001 From: pkupczyk <piotr.kupczyk@id.ethz.ch> Date: Fri, 8 Dec 2023 14:02:01 +0100 Subject: [PATCH] BIS-757 : Write Translator to TypeScript - resolve correct generic types --- api-openbis-java/build.gradle | 1 + build/repository.gradle | 7 ++-- lib-typescriptprocessor/build.gradle | 2 +- .../empa/tsprocessor/AddMethodsExtension.java | 39 ++++++++++--------- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/api-openbis-java/build.gradle b/api-openbis-java/build.gradle index 65d444cc040..0dd6e63bc0e 100644 --- a/api-openbis-java/build.gradle +++ b/api-openbis-java/build.gradle @@ -42,6 +42,7 @@ dependencies { 'sis:sis-file-transfer:19.03.1', 'fasterxml:jackson-core:2.9.10', 'fasterxml:jackson-annotations:2.9.10', + 'com.google.guava:guava:31.1-jre', "cz.habarta.typescript-generator:typescript-generator-core:3.2.1263" diff --git a/build/repository.gradle b/build/repository.gradle index bedda7cc8d1..c37241a890c 100644 --- a/build/repository.gradle +++ b/build/repository.gradle @@ -3,7 +3,8 @@ ext.repositoryConfig = { ivyPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/ivy.xml" artifactPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" } - maven { - url "https://plugins.gradle.org/m2/" - } + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } } diff --git a/lib-typescriptprocessor/build.gradle b/lib-typescriptprocessor/build.gradle index 6674407f654..d26bcca80cc 100644 --- a/lib-typescriptprocessor/build.gradle +++ b/lib-typescriptprocessor/build.gradle @@ -1,6 +1,6 @@ apply from: '../build/javaproject.gradle' dependencies { - implementation 'fasterxml:jackson-core:2.9.10', 'fasterxml:jackson-databind:2.9.10.8', 'cz.habarta.typescript-generator:typescript-generator-core:3.2.1263' + implementation 'fasterxml:jackson-core:2.9.10', 'fasterxml:jackson-databind:2.9.10.8', 'com.google.guava:guava:31.1-jre', 'cz.habarta.typescript-generator:typescript-generator-core:3.2.1263' testImplementation 'testng:testng:6.8-CISD', 'javax.activation:javax.activation-api:1.2.0' } diff --git a/lib-typescriptprocessor/source/java/ch/empa/tsprocessor/AddMethodsExtension.java b/lib-typescriptprocessor/source/java/ch/empa/tsprocessor/AddMethodsExtension.java index 5eb0483cc34..664cff7b0de 100644 --- a/lib-typescriptprocessor/source/java/ch/empa/tsprocessor/AddMethodsExtension.java +++ b/lib-typescriptprocessor/source/java/ch/empa/tsprocessor/AddMethodsExtension.java @@ -22,6 +22,9 @@ package ch.empa.tsprocessor; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; + +import com.google.common.reflect.TypeToken; + import cz.habarta.typescript.generator.*; import cz.habarta.typescript.generator.compiler.ModelCompiler; import cz.habarta.typescript.generator.compiler.SymbolTable; @@ -42,7 +45,7 @@ import java.util.stream.Stream; * implementations depending on whether the method returns a promise or not. */ interface MethodProcessor { - TsPropertyModel makeFunction(Method method, TsModel model, ProcessingContext processingContext); + TsPropertyModel makeFunction(TsBeanModel bean, Method method, TsModel model, ProcessingContext processingContext); } /** @@ -111,36 +114,36 @@ public class AddMethodsExtension extends Extension { } - private static List<TsParameter> getMethodParameters(Executable method, TsModel model, ProcessingContext processingContext) { - return Arrays.stream(method.getParameters()).map(parameter -> new TsParameter(parameter.getName(), resolveGenericType(parameter.getParameterizedType(), model, processingContext))).collect(Collectors.toList()); + private static List<TsParameter> getMethodParameters(TsBeanModel bean, Executable method, TsModel model, ProcessingContext processingContext) { + return Arrays.stream(method.getParameters()).map(parameter -> new TsParameter(parameter.getName(), resolveGenericType(bean.getOrigin(), parameter.getParameterizedType(), model, processingContext))).collect(Collectors.toList()); } - private static TsType resolveGenericType(Type type, TsModel model, ProcessingContext processingContext) { + private static TsType resolveGenericType(Class<?> clazz, Type type, TsModel model, ProcessingContext processingContext) { + TypeToken<?> typeToken = TypeToken.of(clazz).resolveType(type); //This is not very elegant because we are calling again the type processor. Maybe later on we can find a way to get the types from the model TypeProcessor.Context context = new TypeProcessor.Context(processingContext.getSymbolTable(), processingContext.getLocalProcessor(), null); - return context.processType(type).getTsType(); + return context.processType(typeToken.getType()).getTsType(); } - private static TsType getReturnType(Method method, TsModel model, ProcessingContext processingContext) { - return resolveGenericType(method.getGenericReturnType(), model, processingContext); - + private static TsType getReturnType(TsBeanModel bean, Method method, TsModel model, ProcessingContext processingContext) { + return resolveGenericType(bean.getOrigin(), method.getGenericReturnType(), model, processingContext); } - private static TsType.FunctionType makeFunctionType(Method method, TsModel model, ProcessingContext processingContext) { + private static TsType.FunctionType makeFunctionType(TsBeanModel bean, Method method, TsModel model, ProcessingContext processingContext) { logger.info(String.format("Processing method %s, with params %s and return type %s", method, method.getParameters(), method.getGenericReturnType())); - List<TsParameter> params = getMethodParameters(method, model, processingContext); - TsType returnType = getReturnType(method, model, processingContext); + List<TsParameter> params = getMethodParameters(bean, method, model, processingContext); + TsType returnType = getReturnType(bean, method, model, processingContext); return new TsType.FunctionType(params, returnType); } - private static TsPropertyModel makeFunction(Method method, TsModel model, ProcessingContext processingContext) { - return new TsPropertyModel(method.getName(), makeFunctionType(method, model, processingContext), TsModifierFlags.None, false, null); + private static TsPropertyModel makeFunction(TsBeanModel bean, Method method, TsModel model, ProcessingContext processingContext) { + return new TsPropertyModel(method.getName(), makeFunctionType(bean, method, model, processingContext), TsModifierFlags.None, false, null); } - private static TsPropertyModel makePromiseReturningFunction(Method method, TsModel model, ProcessingContext processingContext) { - TsType.FunctionType syncFunction = makeFunctionType(method, model, processingContext); + private static TsPropertyModel makePromiseReturningFunction(TsBeanModel bean, Method method, TsModel model, ProcessingContext processingContext) { + TsType.FunctionType syncFunction = makeFunctionType(bean, method, model, processingContext); TsType promiseType = new TsType.GenericBasicType("Promise", List.of(syncFunction.type)); return new TsPropertyModel(method.getName(), new TsType.FunctionType(syncFunction.parameters, promiseType), TsModifierFlags.None, false, null); } @@ -167,9 +170,9 @@ public class AddMethodsExtension extends Extension { * @return the typescript constructor signature or null if the constructor is not public */ private static TsMethodModel makeConstructor(Constructor<?> constructor, TsBeanModel beanModel, TsModel model, ProcessingContext processingContext) { - List<TsParameter> params = getMethodParameters(constructor, model, processingContext); + List<TsParameter> params = getMethodParameters(beanModel, constructor, model, processingContext); List<TsParameter> paramsWithoutDeclaringClass = params.stream().collect(Collectors.toList()); - TsType returnType = resolveGenericType(constructor.getDeclaringClass(), model, processingContext); + TsType returnType = resolveGenericType(constructor.getDeclaringClass(), constructor.getDeclaringClass(), model, processingContext); logger.info(String.format("Processing constructor %s, with params %s and return type %s", constructor, params, returnType)); TsType.FunctionType functionType = new TsType.FunctionType(paramsWithoutDeclaringClass, returnType); TsPropertyModel propertyModel = new TsPropertyModel("new ", functionType, TsModifierFlags.None, false, null); @@ -178,7 +181,7 @@ public class AddMethodsExtension extends Extension { private static TsBeanModel addFunctions(TsBeanModel bean, TsModel model, ProcessingContext processingContext, MethodProcessor processor) { Class<?> origin = bean.getOrigin(); - Stream<TsMethodModel> params = Arrays.stream(origin.getMethods()).filter(AddMethodsExtension::filterMethods).map(method -> propertyModelToMethodModel(processor.makeFunction(method, model, processingContext))).flatMap(it -> it.map(Stream::of).orElse(Stream.empty())); + Stream<TsMethodModel> params = Arrays.stream(origin.getMethods()).filter(AddMethodsExtension::filterMethods).map(method -> propertyModelToMethodModel(processor.makeFunction(bean, method, model, processingContext))).flatMap(it -> it.map(Stream::of).orElse(Stream.empty())); Stream<TsMethodModel> constructors = Arrays.stream(origin.getDeclaredConstructors()).map(constructor -> makeConstructor(constructor, bean, model, processingContext)); List<TsMethodModel> allMethods = Stream.of(params, constructors).flatMap(it -> it).collect(Collectors.toList()); return bean.withProperties(Collections.emptyList()).withMethods(allMethods); -- GitLab