Skip to content

Commit

Permalink
HHH-14724 Fix generation of problematic metamodel classes which use T…
Browse files Browse the repository at this point in the history
…YPE_USE annotations
  • Loading branch information
beikov committed Jul 29, 2021
1 parent 0fdf431 commit 1a6924c
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 2 deletions.
2 changes: 1 addition & 1 deletion tooling/metamodel-generator/hibernate-jpamodelgen.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies {

testCompile libraries.junit
testCompile libraries.jpa
testCompile libraries.validation
testCompile libraries.validation
testCompile project( ':hibernate-core' )
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpamodelgen.util;

import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.SimpleTypeVisitor8;

/**
* @author Christian Beikov
*/
public final class TypeRenderingVisitor extends SimpleTypeVisitor8<Object, Object> {

private final StringBuilder sb = new StringBuilder();

private TypeRenderingVisitor() {
}

public static String toString(TypeMirror typeMirror) {
if ( typeMirror instanceof TypeVariable ) {
// Top level type variables don't need to render the upper bound as `T extends Type`
final Element typeVariableElement = ( (TypeVariable) typeMirror ).asElement();
if ( typeVariableElement instanceof TypeParameterElement ) {
final TypeParameterElement typeParameter = (TypeParameterElement) typeVariableElement;
if ( typeParameter.getEnclosingElement().getKind() == ElementKind.METHOD ) {
// But for method level type variable we return the upper bound
// because the type variable has no meaning except for that method
typeMirror = ( (TypeVariable) typeMirror ).getUpperBound();
}
else {
return typeParameter.toString();
}
}
else {
typeMirror = typeVariableElement.asType();
}
}
else if ( typeMirror instanceof IntersectionType ) {
// For top level type only the first type is relevant
typeMirror = ( (IntersectionType) typeMirror ).getBounds().get( 0 );
}
final TypeRenderingVisitor typeRenderingVisitor = new TypeRenderingVisitor();
typeMirror.accept( typeRenderingVisitor, null );
return typeRenderingVisitor.sb.toString();
}

@Override
public Object visitPrimitive(PrimitiveType t, Object o) {
final String primitiveTypeName = getPrimitiveTypeName( t.getKind() );
if ( primitiveTypeName != null ) {
sb.append( primitiveTypeName );
}
return null;
}

private static String getPrimitiveTypeName(TypeKind kind) {
switch ( kind ) {
case INT:
return "int";
case BOOLEAN:
return "boolean";
case BYTE:
return "byte";
case CHAR:
return "char";
case DOUBLE:
return "double";
case FLOAT:
return "float";
case LONG:
return "long";
case SHORT:
return "short";
case VOID:
return "void";
}
return null;
}

@Override
public Object visitNull(NullType t, Object o) {
return null;
}

@Override
public Object visitArray(ArrayType t, Object o) {
t.getComponentType().accept( this, null );
sb.append( "[]" );
return t;
}

@Override
public Object visitDeclared(DeclaredType t, Object o) {
sb.append( t.asElement().toString() );
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
if ( !typeArguments.isEmpty() ) {
sb.append( '<' );
typeArguments.get( 0 ).accept( this, null );
for ( int i = 1; i < typeArguments.size(); i++ ) {
sb.append( ", " );
typeArguments.get( i ).accept( this, null );
}
sb.append( '>' );
}
return null;
}

@Override
public Object visitTypeVariable(TypeVariable t, Object o) {
final Element typeVariableElement = t.asElement();
if ( typeVariableElement instanceof TypeParameterElement ) {
final TypeParameterElement typeParameter = (TypeParameterElement) typeVariableElement;
sb.append( typeParameter );
if ( !"java.lang.Object".equals( t.getUpperBound().toString() ) ) {
sb.append( " extends " );
t.getUpperBound().accept( this, null );
}
}
else {
typeVariableElement.asType().accept( this, null );
}
return null;
}

@Override
public Object visitWildcard(WildcardType t, Object o) {
sb.append( '?' );
if ( t.getExtendsBound() != null ) {
sb.append( " extends " );
t.getExtendsBound().accept( this, null );
}
if ( t.getSuperBound() != null ) {
sb.append( " super " );
t.getSuperBound().accept( this, null );
}
return null;
}

@Override
public Object visitUnion(UnionType t, Object o) {
return null;
}

@Override
public Object visitIntersection(IntersectionType t, Object o) {
final List<? extends TypeMirror> bounds = t.getBounds();
bounds.get( 0 ).accept( this, null );
for ( int i = 0; i < bounds.size(); i++ ) {
sb.append( " & " );
bounds.get( i ).accept( this, null );
}
return null;
}

@Override
public Object visitExecutable(ExecutableType t, Object o) {
return null;
}

@Override
public Object visitNoType(NoType t, Object o) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static String toTypeString(TypeMirror type) {
if ( type.getKind().isPrimitive() ) {
return PRIMITIVE_WRAPPERS.get( type.getKind() );
}
return type.toString();
return TypeRenderingVisitor.toString( type );
}

public static String toArrayTypeString(ArrayType type, Context context) {
Expand Down

0 comments on commit 1a6924c

Please sign in to comment.