From 3d6b9175f8883278808e58f52c6d8207e09a12c7 Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Wed, 12 Aug 2020 15:49:10 +0530 Subject: [PATCH] FISH-48 Generic types nested signature parser Signed-off-by: Gaurav Gupta --- .../hk2/classmodel/reflect/FieldModel.java | 8 --- .../hk2/classmodel/reflect/Parameter.java | 6 --- .../classmodel/reflect/ParameterizedType.java | 37 ++++++++++++-- .../reflect/impl/ExtensibleTypeImpl.java | 1 + .../reflect/impl/FieldModelImpl.java | 46 ++++++++++------- .../impl/FieldSignatureVisitorImpl.java | 49 ++++++++++++++++--- .../impl/MethodSignatureVisitorImpl.java | 26 ++++++++-- .../reflect/impl/ModelClassVisitor.java | 14 +++--- .../reflect/impl/ParameterImpl.java | 26 ++++++++-- .../reflect/impl/ParameterizedTypeImpl.java | 34 ++++++++++--- .../classmodel/reflect/impl/TypeBuilder.java | 1 - .../reflect/test/method/MethodTest.java | 12 ++--- 12 files changed, 191 insertions(+), 69 deletions(-) diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/FieldModel.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/FieldModel.java index 98ad842fac..abcbf61a64 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/FieldModel.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/FieldModel.java @@ -16,8 +16,6 @@ package org.glassfish.hk2.classmodel.reflect; -import java.util.List; - /** * Model that represent the field of a class * @@ -59,10 +57,4 @@ public interface FieldModel extends Member, AnnotatedElement, ParameterizedType */ boolean isTransient(); - /** - * The list of raw generic types - * - * @return - */ - List getFormalTypeVariable(); } diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/Parameter.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/Parameter.java index f0918caf2d..c3ddb0c6e3 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/Parameter.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/Parameter.java @@ -31,12 +31,6 @@ public interface Parameter extends AnnotatedElement, ParameterizedType { */ public MethodModel getMethod(); - /** - * Returns the parameter type - * @return parameter type - */ - public Type getType(); - /** * Returns the parameter index * diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/ParameterizedType.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/ParameterizedType.java index 045cc1286e..f538399d44 100644 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/ParameterizedType.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/ParameterizedType.java @@ -18,17 +18,48 @@ import java.util.List; /** - * Denote a Generic type that is parameterized over types * * @author gaurav.gupta@payara.fish */ public interface ParameterizedType { - Type getType(); + /** + * Returns the parameter type + * + * @return parameter type + */ + public Type getType(); + /** + * Returns the parameter type name + * + * @return parameter type name + */ String getTypeName(); - List getGenericTypes(); + /** + * Returns the formal type name + * + * @return the formal type name + */ + String getFormalType(); + /** + * @return the true value for formal type parameters and false value for + * parameterized type with actual type arguments. + */ + boolean isFormalType(); + + /** + * + * @return true if type is array + */ boolean isArray(); + + /** + * + * @return the list of parameterized subtype + */ + List getParameterizedTypes(); + } diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ExtensibleTypeImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ExtensibleTypeImpl.java index 09a9881026..ed759bc35e 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ExtensibleTypeImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ExtensibleTypeImpl.java @@ -35,6 +35,7 @@ public ExtensibleTypeImpl(String name, TypeProxy sink, TypeProxy parent) { this.parent = parent; } + @Override public Map getFormalTypeParameters() { return formalTypeParameters; } diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldModelImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldModelImpl.java index 4ff48ac7b2..6d5a1fecac 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldModelImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldModelImpl.java @@ -19,8 +19,8 @@ import java.util.List; import org.glassfish.hk2.classmodel.reflect.ExtensibleType; import org.glassfish.hk2.classmodel.reflect.FieldModel; -import org.glassfish.hk2.classmodel.reflect.ParameterizedType; import org.objectweb.asm.Opcodes; +import org.glassfish.hk2.classmodel.reflect.ParameterizedType; /** * Implementation of a field model @@ -29,15 +29,15 @@ public class FieldModelImpl extends AnnotatedElementImpl implements FieldModel { private final ExtensibleType declaringType; - private final TypeProxy typeProxy; + private TypeProxy typeProxy; - private int access; + private org.objectweb.asm.Type type; - private List formalTypeVariable; + private String formalType; - private final List genericTypes = new ArrayList<>(); + private int access; - private org.objectweb.asm.Type type; + private final List parameterizedTypes = new ArrayList<>(); public FieldModelImpl(String name, TypeProxy typeProxy, ExtensibleType declaringType) { super(name); @@ -72,11 +72,22 @@ public ExtensibleType getType() { public String getTypeName() { if (typeProxy != null) { return typeProxy.getName(); - } else { + } else if (type != null) { return type.getClassName(); + } else { + return null; } } + @Override + public String getFormalType() { + return formalType; + } + + public void setFormalType(String formalType) { + this.formalType = formalType; + } + public TypeProxy getTypeProxy() { return typeProxy; } @@ -85,16 +96,12 @@ public void setAccess(int access) { this.access = access; } - public void setType(org.objectweb.asm.Type type) { - this.type = type; - } - - public List getFormalTypeVariable() { - return formalTypeVariable; + public void setTypeProxy(TypeProxy typeProxy) { + this.typeProxy = typeProxy; } - public void setFormalTypeVariable(List formalTypeVariable) { - this.formalTypeVariable = formalTypeVariable; + public void setType(org.objectweb.asm.Type type) { + this.type = type; } @Override @@ -104,8 +111,13 @@ protected void print(StringBuffer sb) { } @Override - public List getGenericTypes() { - return genericTypes; + public List getParameterizedTypes() { + return parameterizedTypes; + } + + @Override + public boolean isFormalType() { + return formalType != null; } @Override diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldSignatureVisitorImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldSignatureVisitorImpl.java index 4583fb0e51..ea81fb15c4 100644 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldSignatureVisitorImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/FieldSignatureVisitorImpl.java @@ -15,10 +15,11 @@ */ package org.glassfish.hk2.classmodel.reflect.impl; -import java.util.ArrayList; -import java.util.List; +import java.util.ArrayDeque; +import org.glassfish.hk2.classmodel.reflect.FieldModel; import org.objectweb.asm.Opcodes; import org.objectweb.asm.signature.SignatureVisitor; +import org.glassfish.hk2.classmodel.reflect.ParameterizedType; /** * Signature visitor to visit field and respective generic types @@ -27,19 +28,53 @@ */ public class FieldSignatureVisitorImpl extends SignatureVisitor { - private final List typeVariable = new ArrayList<>(); + private final TypeBuilder typeBuilder; + private final ArrayDeque parentType = new ArrayDeque<>(); - public FieldSignatureVisitorImpl() { + public FieldSignatureVisitorImpl(TypeBuilder typeBuilder, FieldModel fieldModel) { super(Opcodes.ASM7); + + this.typeBuilder = typeBuilder; + parentType.add(fieldModel); } @Override public void visitTypeVariable(String typeVariable) { - this.typeVariable.add(typeVariable); + if (!parentType.isEmpty()) { + ParameterizedType current = parentType.peekLast(); + if (current instanceof FieldModelImpl + && ((FieldModelImpl) current).getTypeProxy() == null + && ((FieldModelImpl) current).getFormalType() == null) { + ((FieldModelImpl) current).setFormalType(typeVariable); + } else { + ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(typeVariable); + current.getParameterizedTypes().add(parameterizedType); + } + } } - public List getTypeVariable() { - return typeVariable; + @Override + public void visitClassType(String name) { + String className = org.objectweb.asm.Type.getObjectType(name).getClassName(); + TypeProxy typeProxy = typeBuilder.getHolder(className); + if (typeProxy != null) { + if (!parentType.isEmpty()) { + ParameterizedType current = parentType.peekLast(); + if (current instanceof FieldModelImpl + && ((FieldModelImpl) current).getTypeProxy() == null) { + ((FieldModelImpl) current).setTypeProxy(typeProxy); + } else { + ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(typeProxy); + current.getParameterizedTypes().add(parameterizedType); + parentType.add(parameterizedType); + } + } + } + } + + @Override + public void visitEnd() { + parentType.pollLast(); } } diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/MethodSignatureVisitorImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/MethodSignatureVisitorImpl.java index 22b1fac6a6..a74eebd6e2 100644 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/MethodSignatureVisitorImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/MethodSignatureVisitorImpl.java @@ -15,7 +15,6 @@ */ package org.glassfish.hk2.classmodel.reflect.impl; -import org.glassfish.hk2.classmodel.reflect.InterfaceModel; import org.objectweb.asm.Opcodes; import org.objectweb.asm.signature.SignatureVisitor; @@ -68,6 +67,25 @@ public SignatureVisitor visitReturnType() { return this; } + @Override + public void visitTypeVariable(String typeVariable) { + if (!parentType.isEmpty()) { + ParameterizedType current = parentType.peekLast(); + if (current instanceof ParameterImpl + && ((ParameterImpl) current).getTypeProxy() == null + && ((ParameterImpl) current).getFormalType() == null) { + ((ParameterImpl) current).setFormalType(typeVariable); + } else if (current instanceof ParameterizedTypeImpl + && ((ParameterizedTypeImpl) current).getTypeProxy() == null + && ((ParameterizedTypeImpl) current).getFormalType() == null) { + ((ParameterizedTypeImpl) current).setFormalType(typeVariable); + } else { + ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(typeVariable); + current.getParameterizedTypes().add(parameterizedType); + } + } + } + @Override public void visitClassType(String name) { String className = org.objectweb.asm.Type.getObjectType(name).getClassName(); @@ -82,9 +100,9 @@ public void visitClassType(String name) { && ((ParameterizedTypeImpl) current).getTypeProxy() == null) { ((ParameterizedTypeImpl) current).setTypeProxy(typeProxy); } else { - ParameterizedTypeImpl genericType = new ParameterizedTypeImpl(typeProxy); - current.getGenericTypes().add(genericType); - parentType.add(genericType); + ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl(typeProxy); + current.getParameterizedTypes().add(parameterizedType); + parentType.add(parameterizedType); } } } diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ModelClassVisitor.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ModelClassVisitor.java index 9377a4f8f9..0d442c7189 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ModelClassVisitor.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ModelClassVisitor.java @@ -225,18 +225,18 @@ public FieldVisitor visitField(int access, final String name, final String desc, } cm = (ExtensibleTypeImpl) type; - org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getType(desc); - TypeProxy fieldType = typeBuilder.getHolder(asmType.getClassName()); - final FieldModelImpl field = typeBuilder.getFieldModel(name, fieldType, cm); + final FieldModelImpl field = typeBuilder.getFieldModel(name, null, cm); SignatureReader reader = new SignatureReader(signature == null ? desc : signature); - FieldSignatureVisitorImpl visitor = new FieldSignatureVisitorImpl(); + FieldSignatureVisitorImpl visitor = new FieldSignatureVisitorImpl(typeBuilder, field); reader.accept(visitor); - field.setFormalTypeVariable(visitor.getTypeVariable()); - org.objectweb.asm.Type type = org.objectweb.asm.Type.getType(desc); - field.setType(type); + org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getType(desc); + field.setType(asmType); + if (field.getTypeProxy() == null) { + field.setTypeProxy(typeBuilder.getHolder(asmType.getClassName())); + } field.setAccess(access); fieldVisitor.getContext().field = field; diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterImpl.java index 6cafe3b090..b6bf2ca43c 100644 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterImpl.java @@ -34,9 +34,11 @@ public class ParameterImpl extends AnnotatedElementImpl implements Parameter { private org.objectweb.asm.Type type; + private String formalType; + private final int index; - private final List genericTypes = new ArrayList<>(); + private final List parameterizedTypes = new ArrayList<>(); public ParameterImpl(int index, String name, TypeProxy typeProxy, MethodModel methodModel) { super(name); @@ -65,8 +67,10 @@ public Type getType() { public String getTypeName() { if (typeProxy != null) { return typeProxy.getName(); - } else { + } else if (type != null) { return type.getClassName(); + } else { + return null; } } @@ -83,8 +87,22 @@ public void setType(org.objectweb.asm.Type type) { } @Override - public List getGenericTypes() { - return genericTypes; + public String getFormalType() { + return formalType; + } + + public void setFormalType(String formalType) { + this.formalType = formalType; + } + + @Override + public List getParameterizedTypes() { + return parameterizedTypes; + } + + @Override + public boolean isFormalType() { + return formalType != null; } @Override diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterizedTypeImpl.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterizedTypeImpl.java index 5459d6b260..1470173be7 100644 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterizedTypeImpl.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/ParameterizedTypeImpl.java @@ -17,8 +17,8 @@ import java.util.ArrayList; import java.util.List; -import org.glassfish.hk2.classmodel.reflect.ParameterizedType; import org.glassfish.hk2.classmodel.reflect.Type; +import org.glassfish.hk2.classmodel.reflect.ParameterizedType; /** * @@ -28,10 +28,12 @@ public class ParameterizedTypeImpl implements ParameterizedType { private TypeProxy typeProxy; - private final List genericTypes = new ArrayList<>(); - private org.objectweb.asm.Type type; + private String formalType; + + private final List parameterizedTypes = new ArrayList<>(); + public ParameterizedTypeImpl() { } @@ -39,6 +41,10 @@ public ParameterizedTypeImpl(TypeProxy type) { this.typeProxy = type; } + public ParameterizedTypeImpl(String formalType) { + this.formalType = formalType; + } + @Override public Type getType() { if (typeProxy != null) { @@ -51,8 +57,10 @@ public Type getType() { public String getTypeName() { if (typeProxy != null) { return typeProxy.getName(); - } else { + } else if (type != null) { return type.getClassName(); + } else { + return null; } } @@ -69,8 +77,22 @@ public void setType(org.objectweb.asm.Type type) { } @Override - public List getGenericTypes() { - return genericTypes; + public String getFormalType() { + return formalType; + } + + public void setFormalType(String formalType) { + this.formalType = formalType; + } + + @Override + public List getParameterizedTypes() { + return parameterizedTypes; + } + + @Override + public boolean isFormalType() { + return formalType != null; } @Override diff --git a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/TypeBuilder.java b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/TypeBuilder.java index b2a45628c5..fa6daa039e 100755 --- a/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/TypeBuilder.java +++ b/class-model/src/main/java/org/glassfish/hk2/classmodel/reflect/impl/TypeBuilder.java @@ -16,7 +16,6 @@ package org.glassfish.hk2.classmodel.reflect.impl; -import org.glassfish.hk2.classmodel.reflect.ClassModel; import org.glassfish.hk2.classmodel.reflect.ExtensibleType; import org.glassfish.hk2.classmodel.reflect.Type; diff --git a/class-model/src/test/java/org/glassfish/hk2/classmodel/reflect/test/method/MethodTest.java b/class-model/src/test/java/org/glassfish/hk2/classmodel/reflect/test/method/MethodTest.java index 593f65625c..58d16d0a9d 100755 --- a/class-model/src/test/java/org/glassfish/hk2/classmodel/reflect/test/method/MethodTest.java +++ b/class-model/src/test/java/org/glassfish/hk2/classmodel/reflect/test/method/MethodTest.java @@ -90,25 +90,25 @@ public void simpleTest() throws IOException, InterruptedException { AnnotationModel param1AnnotationModel = param1.getAnnotations().iterator().next(); Assert.assertEquals("brown", param1AnnotationModel.getValues().get("name")); Assert.assertEquals("java.lang.String", param1.getTypeName()); - Assert.assertEquals(0, param1.getGenericTypes().size()); + Assert.assertEquals(0, param1.getParameterizedTypes().size()); Parameter param2 = mm.getParameter(1); Assert.assertEquals(0, param2.getAnnotations().size()); Assert.assertEquals("java.util.List", param2.getTypeName()); - Assert.assertEquals(1, param2.getGenericTypes().size()); - Assert.assertEquals("java.lang.String", param2.getGenericTypes().get(0).getTypeName()); + Assert.assertEquals(1, param2.getParameterizedTypes().size()); + Assert.assertEquals("java.lang.String", param2.getParameterizedTypes().get(0).getTypeName()); Parameter param3 = mm.getParameter(2); Assert.assertEquals(0, param3.getAnnotations().size()); Assert.assertEquals("org.glassfish.hk2.classmodel.reflect.test.method.SampleType", param3.getTypeName()); - List param3Generics = param3.getGenericTypes(); + List param3Generics = param3.getParameterizedTypes(); Assert.assertEquals(3, param3Generics.size()); Assert.assertEquals("java.lang.Double", param3Generics.get(0).getTypeName()); Assert.assertEquals("java.lang.String", param3Generics.get(1).getTypeName()); Assert.assertEquals("org.glassfish.hk2.classmodel.reflect.test.method.SampleType", param3Generics.get(2).getTypeName()); - List param3NestedGenericTypes = param3Generics.get(2).getGenericTypes(); + List param3NestedGenericTypes = param3Generics.get(2).getParameterizedTypes(); Assert.assertEquals(3, param3NestedGenericTypes.size()); Assert.assertEquals("java.lang.Short", param3NestedGenericTypes.get(0).getTypeName()); Assert.assertEquals("java.lang.Float", param3NestedGenericTypes.get(1).getTypeName()); @@ -123,7 +123,7 @@ public void simpleTest() throws IOException, InterruptedException { // Method's return type check ParameterizedType returnType = mm.getReturnType(); Assert.assertEquals("org.glassfish.hk2.classmodel.reflect.test.method.SampleType", returnType.getTypeName()); - List returnTypeGenerics = returnType.getGenericTypes(); + List returnTypeGenerics = returnType.getParameterizedTypes(); Assert.assertEquals(3, returnTypeGenerics.size()); Assert.assertEquals("java.lang.Integer", returnTypeGenerics.get(0).getTypeName()); Assert.assertEquals("java.lang.Character", returnTypeGenerics.get(1).getTypeName());