diff --git a/processor/src/main/java/org/bsc/processor/TSType.java b/processor/src/main/java/org/bsc/processor/TSType.java new file mode 100644 index 0000000..f068b49 --- /dev/null +++ b/processor/src/main/java/org/bsc/processor/TSType.java @@ -0,0 +1,110 @@ +package org.bsc.processor; + +import java.util.HashMap; + +/** + * + * @author softphone + * + */ +@SuppressWarnings("serial") +public class TSType extends HashMap { + + protected TSType() { + super(3); + } + + public static TSType from( Class cl, boolean export ) { + return new TSType() {{ + put( "value", cl); + put( "export", export); + }}; + } + + public static TSType from( Class cl, String alias, boolean export ) { + return new TSType() {{ + put( "value", cl); + put( "export", export); + put( "alias", alias); + }}; + } + + protected static TSType from( Class cl ) { + return new TSType() {{ put( "value", cl); }}; + } + + /** + * + * @return + */ + public Class getValue() { + return getClassFrom(super.get("value")); + } + + /** + * + * @return + */ + public boolean isExport() { + return (boolean) super.getOrDefault("export", false); + } + + /** + * + * @return + */ + public boolean hasAlias() { + final String alias = (String) super.get("alias"); + return alias!=null && !alias.isEmpty(); + } + + /** + * + * @return + */ + public String getAlias() { + return (String) super.get("alias"); + } + + /** + * + * @return + */ + public final String getTypeName() { + return (hasAlias()) ? getAlias() : getValue().getName(); + } + + /** + * + * @return + */ + public final String getSimpleTypeName() { + return (hasAlias()) ? getAlias() : getValue().getSimpleName(); + } + + /** + * + * @param dt + * @return + */ + private Class getClassFrom( Object dt ) { + if( dt instanceof Class ) return (Class)dt; + + try { + return Class.forName(dt.toString()); + } catch (ClassNotFoundException e1) { + throw new RuntimeException(String.format("class not found [%s]",dt), e1); + } + } + + @Override + public boolean equals(Object o) { + return getValue().equals(((TSType)o).getValue()); + } + + @Override + public int hashCode() { + return getValue().hashCode(); + } + +} diff --git a/processor/src/main/java/org/bsc/processor/TypescriptHelper.java b/processor/src/main/java/org/bsc/processor/TypescriptHelper.java index 88792da..c448e15 100644 --- a/processor/src/main/java/org/bsc/processor/TypescriptHelper.java +++ b/processor/src/main/java/org/bsc/processor/TypescriptHelper.java @@ -2,8 +2,6 @@ import static java.lang.String.format; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; @@ -27,7 +25,7 @@ public class TypescriptHelper { /** * */ - public static BiPredicate, Class> isPackageMatch = (a, b ) -> + public static BiPredicate, Class> isPackageMatch = (a, b) -> a.getPackage().equals(b.getPackage()) ; /** @@ -35,7 +33,7 @@ public class TypescriptHelper { */ public static Predicate> isFunctionalInterface = type -> type.isInterface() && type.isAnnotationPresent(FunctionalInterface.class); - + /** * */ @@ -51,6 +49,28 @@ private final static void log( String fmt, Object ...args ) { System.out.println( format( fmt, (Object[])args)); } + /** + * + * @param type + * @param alias + * @return + */ + public static final String getAliasDeclaration( Class type, String alias ) { + Objects.requireNonNull(type, "argument 'type' is not defined!"); + Objects.requireNonNull(alias, "argument 'alias' is not defined!"); + + final TypeVariable[] typeParameters = type.getTypeParameters(); + + if( typeParameters!=null && typeParameters.length > 0 ) { + + final String pp = Arrays.stream(typeParameters).map( tp -> tp.getName() ).collect( Collectors.joining(",","<", ">")); + return format( "type %s%s = %s%s;\n\n", alias, pp, type.getName(), pp ); + + } + + return format( "type %s = %s;\n\n", alias, type.getName() ); + } + /** * * @param p @@ -66,21 +86,7 @@ public static final String getParameterName( Parameter p ) { return name; } } - - - /** - * - * @param type - * @return - */ - static BeanInfo getBeanInfo(final Class type) { - try { - return java.beans.Introspector.getBeanInfo(type); - } catch (IntrospectionException e) { - throw new Error(e); - } - } - + /** * * @param m @@ -120,50 +126,49 @@ static boolean isPropertyValid( PropertyDescriptor pd ) { * @param isSuperclassValid * @return */ - static String getClassDecl( Class type, - java.util.Map> declaredClassMap ) + static String getClassDecl( TSType tstype, + java.util.Map declaredClassMap ) { final StringBuilder statement = new StringBuilder(); final StringBuilder inherited = new StringBuilder(); - if( type.isInterface() ) { + if( tstype.getValue().isInterface() ) { statement.append( "interface "); } else { - if( type.isEnum() ) statement.append( "/* enum */" ); + if( tstype.getValue().isEnum() ) statement.append( "/* enum */" ); statement.append( "class "); - final Class superclass = type.getSuperclass(); + final TSType superclass = TSType.from(tstype.getValue().getSuperclass()); if( superclass!=null ) { inherited .append( " extends ") - .append( getTypeName(superclass, type, true) ) + .append( getTypeName(superclass, tstype, true) ) ; } } - final Class[] interfaces = type.getInterfaces(); + final Class[] interfaces = tstype.getValue().getInterfaces(); if(interfaces.length > 0 ) { final String ifc = Arrays.stream(interfaces) - .map( (c) -> getTypeName(c,type, true) ) + .map( c -> TSType.from(c) ) + .map( t -> getTypeName(t, tstype, true) ) .collect( Collectors.joining(", ")) ; inherited - .append( getSimpleName(type) ) - .append( (type.isInterface()) ? " extends " : " implements ") + .append( (tstype.getValue().isInterface()) ? " extends " : " implements ") .append( ifc ) ; } - statement.append( getSimpleName(type) ); + statement.append( getTypeName(tstype, tstype, true) ); if( inherited.length()>0 ) { @@ -194,91 +199,41 @@ static String getClassParametersDecl( java.util.List type_parameters_lis /** * * @param type + * @param declaringType * @return */ - static String getClassParametersDecl( Class type ) { - - return getClassParametersDecl( - Arrays.stream(type.getTypeParameters()) - .map( (tp) -> tp.getName() ) - .collect(Collectors.toList()) - ); - } - - /** - * - * @param type - * @return - */ - static String getSimpleName( Class type ) { - return type.getSimpleName().concat(getClassParametersDecl(type)); - } - - /** - * - * @param type - * @return - */ - static String getTypeName( Class type ) { - return type.getName().concat(getClassParametersDecl(type)); - } - - /** - * - * @param type - * @param declaringClass - * @return - * @throws ClassNotFoundException - */ - static String getTypeName( Type type, Class declaringClass, boolean packageResolution ) throws ClassNotFoundException { - - final Class clazz = Class.forName(type.getTypeName()); - - return getTypeName( clazz, declaringClass, packageResolution ); - - } - - /** - * - * @param type - * @param declaringClass - * @return - */ - static String getTypeName( Class type, Class declaringClass, boolean packageResolution ) { + static String getTypeName( TSType type, TSType declaringType, boolean packageResolution ) { final java.util.List dc_parameters_list = - Arrays.stream(declaringClass.getTypeParameters()) + Arrays.stream(declaringType.getValue().getTypeParameters()) .map( (tp) -> tp.getName()) .collect(Collectors.toList()); final java.util.List type_parameters_list = - Arrays.stream(type.getTypeParameters()) + Arrays.stream(type.getValue().getTypeParameters()) .map( tp -> (dc_parameters_list.contains(tp.getName()) ) ? tp.getName() : "any" ) .collect(Collectors.toList()); final java.util.List parameters = dc_parameters_list.size() == type_parameters_list.size() ? dc_parameters_list : type_parameters_list ; - //boolean isFunctionalInterface = ( type.isInterface() && type.isAnnotationPresent(FunctionalInterface.class)); - - final Package currentNS = (packageResolution) ? declaringClass.getPackage() : null; + final Package currentNS = (packageResolution) ? declaringType.getValue().getPackage() : null; return new StringBuilder() .append( - type.getPackage().equals(currentNS) || isFunctionalInterface.test(type) ? - type.getSimpleName() : - type.getName() + type.getValue().getPackage().equals(currentNS) || isFunctionalInterface.test(type.getValue()) ? + type.getSimpleTypeName() : + type.getTypeName() ) .append( getClassParametersDecl(parameters) ) .toString(); } - /** * * @param type * @param declaringMethod - * @param declaredClassMap + * @param declaredTypeMap * @param packageResolution * @param typeMatch * @param onTypeMismatch @@ -286,15 +241,15 @@ static String getTypeName( Class type, Class declaringClass, boolean packa */ public static String convertJavaToTS( Type type, Method declaringMethod, - Class declaringClass, - java.util.Map> declaredClassMap, + TSType declaringType, + java.util.Map declaredTypeMap, boolean packageResolution, Optional>> onTypeMismatch) { Objects.requireNonNull(type, "Type argument is null!"); Objects.requireNonNull(declaringMethod, "declaringMethod argument is null!"); - Objects.requireNonNull(declaringClass, "declaringClass argument is null!"); - Objects.requireNonNull(declaredClassMap, "declaredClassMap argument is null!"); + Objects.requireNonNull(declaringType, "declaringType argument is null!"); + Objects.requireNonNull(declaredTypeMap, "declaredTypeMap argument is null!"); if( type instanceof ParameterizedType ) { @@ -302,13 +257,16 @@ public static String convertJavaToTS( Type type, final Class rawType = (Class)pType.getRawType(); - if( !declaredClassMap.containsKey(rawType.getName()) ) { + final TSType tstype = declaredTypeMap.get(rawType.getName()); + if( tstype==null ) { return format("any /*%s*/",rawType.getName()); } + + String result = pType.getTypeName() + .replace( rawType.getName(), tstype.getTypeName()) // use Alias + ; - String result = pType.getTypeName(); - - if( isFunctionalInterface.test(rawType) || (packageResolution && isPackageMatch.test(rawType, declaringClass)) ) { + if( isFunctionalInterface.test(rawType) || (packageResolution && isPackageMatch.test(rawType, declaringType.getValue())) ) { result = result.replace( rawType.getName(), rawType.getSimpleName()); } @@ -319,8 +277,8 @@ public static String convertJavaToTS( Type type, final String typeName = convertJavaToTS( t, declaringMethod, - declaringClass, - declaredClassMap, + declaringType, + declaredTypeMap, packageResolution, onTypeMismatch); log( "Parameterized Type %s - %s", t, typeName ); @@ -333,7 +291,7 @@ else if( t instanceof TypeVariable ) { final TypeVariable tv = (TypeVariable)t; - if( isStaticMethod(declaringMethod) || !typeParameterMatch.apply(declaringClass, tv )) { + if( isStaticMethod(declaringMethod) || !typeParameterMatch.apply(declaringType.getValue(), tv )) { if( onTypeMismatch.isPresent() ) { onTypeMismatch.get().accept(tv); @@ -351,7 +309,7 @@ else if( t instanceof TypeVariable ) { else if( t instanceof Class ) { log( "class: %s", t.getTypeName() ); - final String name = convertJavaToTS( (Class)t, declaringClass, declaredClassMap, packageResolution); + final String name = convertJavaToTS( (Class)t, declaringType, declaredTypeMap, packageResolution); final String commented = format("/*%s*/", t.getTypeName()); result = result.replace( commented, "/*@*/") @@ -372,8 +330,8 @@ else if( t instanceof WildcardType ) { result = result.replace( wt.getTypeName(), convertJavaToTS( tt, declaringMethod, - declaringClass, - declaredClassMap, + declaringType, + declaredTypeMap, packageResolution, onTypeMismatch)); } @@ -394,7 +352,7 @@ else if( type instanceof TypeVariable ) { final TypeVariable tv = (TypeVariable)type; - if( isStaticMethod(declaringMethod) || !typeParameterMatch.apply(declaringClass, tv )) { + if( isStaticMethod(declaringMethod) || !typeParameterMatch.apply(declaringType.getValue(), tv )) { final String name = tv.getName(); @@ -411,7 +369,7 @@ else if( type instanceof TypeVariable ) { else if( type instanceof Class ) { log( "class: %s", type.getTypeName() ); - final String name = convertJavaToTS( (Class)type, declaringClass, declaredClassMap, packageResolution); + final String name = convertJavaToTS( (Class)type, declaringType, declaredTypeMap, packageResolution); return name; } else if( type instanceof WildcardType ) { @@ -423,7 +381,7 @@ else if( type instanceof GenericArrayType ) { log( "generic array type: %s", t.getGenericComponentType().getTypeName() ); //throw new IllegalArgumentException( format("type <%s> 'GenericArrayType' is a not supported yet!", type)); - return ( typeParameterMatch.apply(declaringClass, t.getGenericComponentType() )) ? + return ( typeParameterMatch.apply(declaringType.getValue(), t.getGenericComponentType() )) ? format("[%s]", t.getGenericComponentType() ) : format("[any/*%s*/]", t.getGenericComponentType() ); } @@ -434,14 +392,14 @@ else if( type instanceof GenericArrayType ) { /** * * @param type - * @param declaringClass - * @param declaredClassMap + * @param declaringType + * @param declaredTypeMap * @param packageResolution * @return */ private static String convertJavaToTS( Class type, - Class declaringClass, - java.util.Map> declaredClassMap, + TSType declaringType, + java.util.Map declaredTypeMap, boolean packageResolution ) { @@ -460,12 +418,12 @@ private static String convertJavaToTS( Class type, if( byte[].class.equals(type) ) return "bytearray"; if( type.isArray()) { - //return format("[any] /* %s */",type.getName()); - return format( "[%s]", convertJavaToTS(type.getComponentType(), declaringClass, declaredClassMap,packageResolution)); + return format( "[%s]", convertJavaToTS(type.getComponentType(), declaringType, declaredTypeMap,packageResolution)); } - if( declaredClassMap.containsKey(type.getName()) ) { - return getTypeName(type, declaringClass, packageResolution); + final TSType tt = declaredTypeMap.get( type.getName() ); + if( tt!=null ) { + return getTypeName(tt, declaringType, packageResolution); } return format("any /*%s*/",type.getName()); diff --git a/processor/src/main/java/org/bsc/processor/TypescriptProcessor.java b/processor/src/main/java/org/bsc/processor/TypescriptProcessor.java index b606a68..8e2348f 100644 --- a/processor/src/main/java/org/bsc/processor/TypescriptProcessor.java +++ b/processor/src/main/java/org/bsc/processor/TypescriptProcessor.java @@ -3,7 +3,6 @@ import static org.bsc.processor.TypescriptHelper.convertJavaToTS; import static org.bsc.processor.TypescriptHelper.getClassDecl; import static org.bsc.processor.TypescriptHelper.getParameterName; -import static org.bsc.processor.TypescriptHelper.getSimpleName; import static org.bsc.processor.TypescriptHelper.isStaticMethod; import java.io.Closeable; @@ -17,7 +16,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.RandomAccess; @@ -51,32 +49,32 @@ public class TypescriptProcessor extends AbstractProcessorEx { final static String ENDL = ";\n"; - static final List> PREDEFINED_CLASSES = Arrays.asList( - Class.class, - Serializable.class, - Closeable.class, - AutoCloseable.class, - Comparable.class, - Cloneable.class, - RandomAccess.class, - Consumer.class, - UnaryOperator.class, - Supplier.class, - Predicate.class, - Runnable.class + static final List PREDEFINED_TYPES = Arrays.asList( + TSType.from(Class.class), + TSType.from(Serializable.class), + TSType.from(Closeable.class), + TSType.from(AutoCloseable.class), + TSType.from(Comparable.class), + TSType.from(Cloneable.class), + TSType.from(RandomAccess.class), + TSType.from(Consumer.class), + TSType.from(UnaryOperator.class), + TSType.from(Supplier.class), + TSType.from(Predicate.class), + TSType.from(Runnable.class) ); - static final List REQUIRED_CLASSES = Arrays.asList( - new TSType(java.lang.String.class,true), - new TSType(java.lang.Iterable.class,true), - new TSType(java.util.Iterator.class,true), - new TSType(java.util.Collection.class), - new TSType(java.util.Collections.class, true), - new TSType(java.util.List.class), - new TSType(java.util.Set.class), - new TSType(java.util.Map.class), - new TSType(java.util.stream.Stream.class, true), - new TSType(java.util.Optional.class, true) + static final List REQUIRED_TYPES = Arrays.asList( + TSType.from(java.lang.String.class,true), + TSType.from(java.lang.Iterable.class,true), + TSType.from(java.util.Iterator.class,true), + TSType.from(java.util.Collection.class), + TSType.from(java.util.Collections.class, true), + TSType.from(java.util.List.class), + TSType.from(java.util.Set.class), + TSType.from(java.util.Map.class), + TSType.from(java.util.stream.Stream.class, true), + TSType.from(java.util.Optional.class, true) ); /** @@ -108,53 +106,62 @@ private java.io.Writer openFile( Path file, String header ) throws IOException { @Override public boolean process( Context processingContext ) throws Exception { - final String targetDefinitionFile = processingContext.getOptionMap().getOrDefault("ts.outfile", "out"); + final String targetDefinitionFile = processingContext.getOptionMap().getOrDefault("ts.outfile", "out"); //final String compatibility = processingContext.getOptionMap().getOrDefault("compatibility", "nashorn"); final String definitionsFile = targetDefinitionFile.concat(".d.ts"); - final String typesFile = targetDefinitionFile.concat("-types.ts"); + final String typesFile = targetDefinitionFile.concat("-types.ts"); try( final java.io.Writer wD = openFile( Paths.get(definitionsFile), "headerD.ts" ); final java.io.Writer wT = openFile( Paths.get(typesFile), "headerT.ts" ); ) { + final Consumer wD_append = s -> { + try { + wD.append( s ); + } catch (IOException e) { + error( "error adding [%s]", s); + } + }; + final Consumer wT_append = s -> { + try { + wT.append( s ); + } catch (IOException e) { + error( "error adding [%s]", s); + } + }; + final Set types = enumerateDeclaredPackageAndClass( processingContext ); - types.addAll(REQUIRED_CLASSES); + types.addAll(REQUIRED_TYPES); - final Set> classes = types.stream() - .map( t -> t.getValue() ) - .collect( Collectors.toSet()); - - final java.util.Map> declaredClasses = - classes.stream().collect( Collectors.toMap( clazz -> clazz.getName() , clazz -> clazz )); + final java.util.Map declaredTypes = + types.stream().collect( Collectors.toMap( tt -> tt.getValue().getName() , tt -> tt )); - PREDEFINED_CLASSES.forEach( clazz -> declaredClasses.put( clazz.getName(), clazz) ); + PREDEFINED_TYPES.forEach( tt -> declaredTypes.put( tt.getValue().getName(), tt) ); + + // Generate Alias + wD.append("//\n") + .append("// TYPE ALIASES\n") + .append("//\n\n"); + types.stream() + .filter( t -> t.hasAlias() ) + .map( t -> TypescriptHelper.getAliasDeclaration(t.getValue(), t.getAlias()) ) + .forEach( wD_append ); + + types.stream() - .filter( t -> !PREDEFINED_CLASSES.contains(t.getValue()) ) - .map( t -> processClass( t, declaredClasses)) - .forEach( s -> { - try { - wD.append( s ); - } catch (IOException e) { - error( "error adding [%s]", s); - } - } ); + .filter( tt -> !PREDEFINED_TYPES.contains(tt) ) + .map( tt -> processClass( tt, declaredTypes)) + .forEach( wD_append ); - wT.append( String.format("/// ", definitionsFile) ).append( "\n\n"); + wT.append( "/// " ).append( "\n\n"); types.stream() .filter( t -> t.isExport() ) - .map( t -> t.getValue() ) - .map( clazz -> processStatic( clazz, declaredClasses)) - .forEach( s -> { - try { - wT.append( s ); - } catch (IOException e) { - error( "error adding [%s]", s); - } - } ); + .map( t -> processStatic( t, declaredTypes)) + .forEach( wT_append ); } // end try-with-resources @@ -163,13 +170,13 @@ public boolean process( Context processingContext ) throws Exception { /** * * @param m - * @param declaringClass - * @param declaredClassMap + * @param declaringType + * @param declaredTypeMap * @return */ protected String getMethodParametersAndReturnDecl( Method m, - Class declaringClass, - java.util.Map> declaredClassMap, + TSType declaringType, + java.util.Map declaredTypeMap, boolean packageResolution ) { final java.util.Set TypeVarSet = new java.util.HashSet<>(5); @@ -188,16 +195,16 @@ protected String getMethodParametersAndReturnDecl( Method m, if( tp.isVarArgs() ) { final String type = convertJavaToTS( tp.getType().getComponentType(), m, - declaringClass, - declaredClassMap, + declaringType, + declaredTypeMap, packageResolution, Optional.of( addTypeVar )) ; return String.format( "...%s:%s[]", name, type ); } final String type = convertJavaToTS( tp.getParameterizedType(), m, - declaringClass, - declaredClassMap, + declaringType, + declaredTypeMap, packageResolution, Optional.of( addTypeVar )) ; return String.format( "%s:%s", name, type ); @@ -210,8 +217,8 @@ protected String getMethodParametersAndReturnDecl( Method m, final String tsType = convertJavaToTS( returnType, m, - declaringClass, - declaredClassMap, + declaringType, + declaredTypeMap, packageResolution, Optional.of( addTypeVar )); @@ -234,19 +241,17 @@ protected String getMethodParametersAndReturnDecl( Method m, /** * * @param m - * @param declaringClass - * @param declaredClassMap + * @param declaringType + * @param declaredTypeMap * @return */ - private String getFactoryMethodDecl( final Method m, Class declaringClass, java.util.Map> declaredClassMap ) { + private String getFactoryMethodDecl( final Method m, TSType declaringType, java.util.Map declaredTypeMap ) { final StringBuilder sb = new StringBuilder(); sb.append(m.getName()); - //appendStaticMethodTypeParameters(sb, m).append( getMethodParametersAndReturnDecl(m, declaringClass, declaredClassMap, false) ); - - sb.append( getMethodParametersAndReturnDecl(m, declaringClass, declaredClassMap, false) ); + sb.append( getMethodParametersAndReturnDecl(m, declaringType, declaredTypeMap, false) ); return sb.toString(); @@ -259,19 +264,17 @@ private String getFactoryMethodDecl( final Method m, Class declaringClass, ja * @param declaredClassMap * @return */ - private String getMethodDecl( final Method m, Class declaringClass, java.util.Map> declaredClassMap ) { + private String getMethodDecl( final Method m, TSType declaringClass, java.util.Map declaredClassMap ) { final StringBuilder sb = new StringBuilder(); if( Modifier.isStatic(m.getModifiers()) ) { - if( declaringClass.isInterface() ) { + if( declaringClass.getValue().isInterface() ) { sb.append( "// "); } sb.append("static ").append(m.getName()); - - //appendStaticMethodTypeParameters(sb, m); } else { @@ -292,7 +295,7 @@ private String getMethodDecl( final Method m, Class declaringClass, java.util * @param type * @return */ - private Set getMethods( final Class type) { + private Set getMethods( final TSType type) { final Predicate include = m -> !m.isBridge() && !m.isSynthetic() && @@ -300,7 +303,7 @@ private Set getMethods( final Class type) { Character.isJavaIdentifierStart(m.getName().charAt(0)) && m.getName().chars().skip(1).allMatch(Character::isJavaIdentifierPart); - return Stream.concat( Stream.of(type.getMethods()), Stream.of(type.getDeclaredMethods()) ) + return Stream.concat( Stream.of(type.getValue().getMethods()), Stream.of(type.getValue().getDeclaredMethods()) ) .filter(include) .collect( Collectors.toSet( ) ); @@ -310,28 +313,26 @@ private Set getMethods( final Class type) { * * @param sb * @param type - * @param declaredClassMap + * @param declaredTypeMap */ - private void processNestedClasses( StringBuilder sb, TSType tstype, java.util.Map> declaredClassMap ) { + private void processNestedClasses( StringBuilder sb, TSType tstype, java.util.Map declaredTypeMap ) { - final Class type = tstype.getValue(); - - final Class nestedClasses[] = type.getClasses(); + final Class nestedClasses[] = tstype.getValue().getClasses(); if( nestedClasses.length == 0 ) return; sb.append( "export module " ) - .append(type.getSimpleName()) + .append(tstype.getSimpleTypeName()) .append(" {\n\n") ; Arrays.stream(nestedClasses) - .map( cl -> new TSType(cl) ) - .map( t -> processClass(t, declaredClassMap) ) - .forEach( (decl) -> sb.append(decl) ); + .map( cl -> TSType.from(cl) ) + .map( t -> processClass(t, declaredTypeMap) ) + .forEach( decl -> sb.append(decl) ); sb.append("\n} // end module ") - .append(type.getSimpleName()) + .append(tstype.getSimpleTypeName()) .append('\n') ; } @@ -342,16 +343,16 @@ private void processNestedClasses( StringBuilder sb, TSType tstype, java.util.Ma * @param type * @param declaredClassMap */ - private void processEnum( StringBuilder sb, Class type, java.util.Map> declaredClassMap ) { - if( !type.isEnum() ) return ; + private void processEnum( StringBuilder sb, TSType type, java.util.Map declaredClassMap ) { + if( !type.getValue().isEnum() ) return ; - Arrays.stream( type.getEnumConstants() ) + Arrays.stream( type.getValue().getEnumConstants() ) .forEach( (c) -> { sb.append( '\t' ) .append( "static ") .append( c.toString() ) .append( ':') - .append( type.getSimpleName() ) + .append( type.getSimpleTypeName() ) .append( ';' ) .append( '\n' ) ; @@ -367,7 +368,7 @@ private void processEnum( StringBuilder sb, Class type, java.util.Map type, java.util.Map> declaredClassMap ) { + private String processStatic( TSType type, java.util.Map declaredClassMap ) { final StringBuilder sb = new StringBuilder(); @@ -378,7 +379,7 @@ private String processStatic( Class type, java.util.Map> dec .collect( Collectors.toCollection(() -> new java.util.LinkedHashSet() )); sb.append("interface ") - .append( type.getSimpleName() ) + .append( type.getSimpleTypeName() ) .append("Static {\n\n") //Append class property .append("\treadonly class:any;\n"); @@ -396,11 +397,11 @@ private String processStatic( Class type, java.util.Map> dec sb.append( "}\n\n" ) .append("export const ") - .append(type.getSimpleName()) + .append(type.getSimpleTypeName()) .append(": ") - .append(type.getSimpleName()) + .append(type.getSimpleTypeName()) .append("Static = Java.type(\"") - .append( type.getName() ) + .append( type.getTypeName() ) .append("\")") .append( ENDL ) .append("\n\n") @@ -416,33 +417,24 @@ private String processStatic( Class type, java.util.Map> dec * @param declaredClassMap * @return */ - private String processClass( TSType tstype, java.util.Map> declaredClassMap ) { + private String processClass( TSType tstype, java.util.Map declaredClassMap ) { final StringBuilder sb = new StringBuilder(); - final Class type = tstype.getValue(); - - final String namespace = type.getPackage().getName(); + final String namespace = tstype.getValue().getPackage().getName(); - if( !type.isMemberClass() ) + if( !tstype.getValue().isMemberClass() ) sb.append( "declare namespace " ) .append(namespace) .append(" {\n\n") ; - sb.append( getClassDecl(type, declaredClassMap) ) - .append("\n\n"); - - processEnum(sb, type, declaredClassMap); + sb.append( getClassDecl(tstype, declaredClassMap) ).append("\n\n"); - /* - final BeanInfo bi = getBeanInfo(type); - - final PropertyDescriptor[] pds = bi.getPropertyDescriptors(); + processEnum(sb, tstype, declaredClassMap); - */ final java.util.Set methodSet = - getMethods( type ) + getMethods( tstype ) .stream() .filter( md -> (tstype.isExport() && isStaticMethod(md))==false ) .filter( (md) -> { @@ -454,41 +446,10 @@ private String processClass( TSType tstype, java.util.Map> decl name.equals("notify") || name.equals("notifyAll") ); }) - /* - .filter( md -> {// Remove setter and getter - - final boolean match = Arrays.asList(pds) - .stream() - .noneMatch( pd -> (md.equals(pd.getReadMethod()) || md.equals(pd.getWriteMethod())) ); - - return match; - }) - */ .collect( Collectors.toCollection(() -> new java.util.LinkedHashSet() )); - /* - final java.util.Set propertySet = - Arrays.stream(pds) - .filter( TypescriptHelper::isPropertyValid ) - .collect( Collectors.toCollection(() -> new java.util.LinkedHashSet(pds.length) )) - ; - - propertySet.stream() - .map( pd -> { - final boolean duplicate = methodSet.stream().anyMatch( m -> m.getName().equals(pd.getName())); - final String decl = getPropertyDecl( type, pd, declaredClassMap); - return ( duplicate ) ? "// ".concat(decl) : decl; - }) - .sorted() - .forEach((decl) -> - sb.append( '\t' ) - .append(decl) - .append( ENDL )) - ; - */ - methodSet.stream() - .map( md -> getMethodDecl(md, type, declaredClassMap) ) + .map( md -> getMethodDecl(md, tstype, declaredClassMap) ) .sorted().forEach( (decl) -> sb.append( '\t' ) .append(decl) @@ -496,13 +457,13 @@ private String processClass( TSType tstype, java.util.Map> decl ; sb.append("\n} // end ") - .append(getSimpleName(type)) + .append(tstype.getSimpleTypeName()) .append('\n'); // NESTED CLASSES processNestedClasses(sb, tstype, declaredClassMap); - if( !type.isMemberClass() ) + if( !tstype.getValue().isMemberClass() ) sb.append("\n} // end namespace ") .append( namespace ) .append('\n'); @@ -525,60 +486,7 @@ private List getAnnotationValueValue( return (List)av.getValue(); } - - - @SuppressWarnings("serial") - static class TSType extends HashMap{ - - public TSType() { - super(2); - } - public TSType( Class cl ) { - this(); - put( "value", cl); - } - public TSType( Class cl, boolean export ) { - this(); - put( "value", cl); - put( "export", export); - - } - - public Class getValue() { - return getClassFrom(super.get("value")); - } - - public boolean isExport() { - return (boolean) super.getOrDefault("export", false); - } - - /** - * - * @param dt - * @return - */ - private Class getClassFrom( Object dt ) { - if( dt instanceof Class ) return (Class)dt; - - try { - return Class.forName(dt.toString()); - } catch (ClassNotFoundException e1) { - throw new RuntimeException(String.format("class not found [%s]",dt), e1); - } - } - @Override - public boolean equals(Object o) { - return getValue().equals(((TSType)o).getValue()); - } - - @Override - public int hashCode() { - return getValue().hashCode(); - } - - } - - + /** * * @param processingContext diff --git a/processor/src/main/java/org/bsc/processor/annotation/Type.java b/processor/src/main/java/org/bsc/processor/annotation/Type.java index 2d85eb7..7cc357c 100644 --- a/processor/src/main/java/org/bsc/processor/annotation/Type.java +++ b/processor/src/main/java/org/bsc/processor/annotation/Type.java @@ -10,4 +10,5 @@ public @interface Type { Class value(); boolean export() default false ; + String alias() default ""; } diff --git a/processor/src/test/java/org/bsc/processor/RefrectionTest.java b/processor/src/test/java/org/bsc/processor/ProcessorTest.java similarity index 74% rename from processor/src/test/java/org/bsc/processor/RefrectionTest.java rename to processor/src/test/java/org/bsc/processor/ProcessorTest.java index 149ccd0..9362a28 100644 --- a/processor/src/test/java/org/bsc/processor/RefrectionTest.java +++ b/processor/src/test/java/org/bsc/processor/ProcessorTest.java @@ -3,6 +3,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.ArrayList; import java.util.Collections; import java.util.Optional; import java.util.function.Consumer; @@ -15,15 +16,62 @@ import org.junit.Assert; import org.junit.Test; -public class RefrectionTest { +public class ProcessorTest { final TypescriptProcessor processor = new TypescriptProcessor(); - private java.util.Map> declaredClassMap( Class ... classes) { + private java.util.Map declaredClassMap( Class ... classes) { return Stream.of( classes ) - .collect( Collectors.toMap( c -> c.getName(), c -> c) ) + .collect( Collectors.toMap( c -> c.getName(), c -> TSType.from(c) )) ; } + private java.util.Map declaredTypeMap( TSType ... types) { + return Stream.of( types ) + .collect( Collectors.toMap( t -> t.getValue().getName(), t -> t )) + ; + } + + @Test + public void testClassDecl() throws Exception { + + { + final String result = TypescriptHelper.getClassDecl( TSType.from(ArrayList.class), Collections.emptyMap()); + + Assert.assertThat( result, IsNull.notNullValue()); + Assert.assertThat( result, IsEqual.equalTo("class ArrayList/* extends AbstractList implements List, RandomAccess, java.lang.Cloneable, java.io.Serializable*/ {")); + } + + } + + @Test + public void testAlias() throws Exception { + + final Class type = Sample1.class; + + { + final Method m = type.getMethod("getAttributeList"); + final Type rType = m.getGenericReturnType(); + final String result = TypescriptHelper.convertJavaToTS(rType, m, + TSType.from(type), + declaredTypeMap( TSType.from(String.class), TSType.from(java.util.List.class, "List", true) ), + true, + Optional.empty()); + Assert.assertThat( result, IsNull.notNullValue()); + Assert.assertThat( result, IsEqual.equalTo("List")); + } + { + final Method m = type.getMethod("getAttributeList", java.util.List.class); + + final String result = processor.getMethodParametersAndReturnDecl( m, + TSType.from(type), + declaredTypeMap( TSType.from(String.class), TSType.from(java.util.List.class, "List", true) ), + true) ; + + Assert.assertThat( result, IsNull.notNullValue()); + Assert.assertThat( result, IsEqual.equalTo("( arg0:List ):List")); + } + + } @Test public void testSample1() throws Exception { @@ -40,7 +88,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method4"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), Collections.emptyMap(), true, Optional.empty()); @@ -51,7 +99,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method5"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), Collections.emptyMap(), true, Optional.empty()); @@ -62,7 +110,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method1_1"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class), true, Optional.empty()); @@ -73,7 +121,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method1_2"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class,java.lang.Comparable.class), true, Optional.empty()); @@ -85,7 +133,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method1_3"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap(java.util.function.BiPredicate.class), true, Optional.of(addTypeVar)); @@ -99,7 +147,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method1_3"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), Collections.emptyMap(), true, Optional.empty()); @@ -110,7 +158,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method1"); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap(java.util.Map.class), true, Optional.empty()); @@ -122,7 +170,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method2", Sample2.class); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), Collections.emptyMap(), true, Optional.empty()); @@ -131,7 +179,7 @@ public void testSample1() throws Exception { final Type pType = m.getParameters()[0].getParameterizedType(); final String rresult = TypescriptHelper.convertJavaToTS(pType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class), true, Optional.empty()); @@ -143,7 +191,7 @@ public void testSample1() throws Exception { final Method m = type.getMethod("method2_1", Sample2.class); final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class, CharSequence.class), true, Optional.empty()); @@ -152,7 +200,7 @@ public void testSample1() throws Exception { final Type pType = m.getParameters()[0].getParameterizedType(); final String rresult = TypescriptHelper.convertJavaToTS(pType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class), true, Optional.empty()); @@ -172,7 +220,7 @@ public void testSample1() throws Exception { final Type pType = m.getParameters()[0].getParameterizedType(); final String rresult = TypescriptHelper.convertJavaToTS(pType, m, - type, + TSType.from(type), declaredClassMap(Sample2.class, Consumer.class), true, Optional.empty()); @@ -194,7 +242,7 @@ public void testSample1() throws Exception { final String[] arr = {}; final Method m = type.getMethod("method6", arr.getClass()); - final String result = processor.getMethodParametersAndReturnDecl( m, type, Collections.emptyMap(), true) ; + final String result = processor.getMethodParametersAndReturnDecl( m, TSType.from(type), Collections.emptyMap(), true) ; Assert.assertThat( result, IsNull.notNullValue()); Assert.assertThat( result, IsEqual.equalTo("( ...arg0:string[] ):void")); @@ -216,17 +264,17 @@ String getReturnType( Class type, String methonName, Class ...args ) throw return getReturnType(Collections.emptyMap(), type, methonName, (Class[])args); } - String getReturnType( java.util.Map> declaredClassMap, Class type, String methodName, Class ...args ) throws Exception + String getReturnType( java.util.Map declaredClassMap, Class type, String methodName, Class ...args ) throws Exception { final Method m = type.getMethod(methodName, (Class[])args); return getReturnType( declaredClassMap, type, m); } - String getReturnType( java.util.Map> declaredClassMap, Class type, Method m ) throws Exception + String getReturnType( java.util.Map declaredClassMap, Class type, Method m ) throws Exception { final Type rType = m.getGenericReturnType(); final String result = TypescriptHelper.convertJavaToTS(rType, m, - type, + TSType.from(type), declaredClassMap, true, Optional.empty()); diff --git a/processor/src/test/java/org/bsc/processor/Sample1.java b/processor/src/test/java/org/bsc/processor/Sample1.java index 2110d1e..aa8d0dc 100644 --- a/processor/src/test/java/org/bsc/processor/Sample1.java +++ b/processor/src/test/java/org/bsc/processor/Sample1.java @@ -29,4 +29,8 @@ public interface Sample1 { void method6( String ...args ); java.util.Map getAttributeMap(); + + java.util.List getAttributeList(); + + java.util.List getAttributeList( java.util.List intList); } diff --git a/sample/src/main/java/org/bsc/java2ts/jdk8/package-info.java b/sample/src/main/java/org/bsc/java2ts/jdk8/package-info.java index eeb4ce3..c764f0a 100644 --- a/sample/src/main/java/org/bsc/java2ts/jdk8/package-info.java +++ b/sample/src/main/java/org/bsc/java2ts/jdk8/package-info.java @@ -18,7 +18,7 @@ @Type(java.util.Comparator.class), @Type(java.util.Collection.class), @Type(java.util.Map.class), - @Type(java.util.List.class ), + @Type(value=java.util.List.class, alias="List" ), @Type(java.util.Set.class), @Type(value=java.util.Arrays.class, export=true), @Type(java.util.HashMap.class),