more information about errors relating to inherited members in processor

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-03-26 15:52:56 +01:00 committed by Christian Beikov
parent 8148c32cd7
commit 80792f5b8d
2 changed files with 99 additions and 48 deletions

View File

@ -18,13 +18,14 @@
*/ */
public class EgTest extends CompilationTest { public class EgTest extends CompilationTest {
@Test @Test
@WithClasses({ Publisher.class, Author.class, Address.class, Book.class, Library.class }) @WithClasses({ Publisher.class, Author.class, Address.class, Book.class, Library.class, Bookshop.class })
public void test() { public void test() {
System.out.println( getMetaModelSourceAsString( Author.class ) ); System.out.println( getMetaModelSourceAsString( Author.class ) );
System.out.println( getMetaModelSourceAsString( Book.class ) ); System.out.println( getMetaModelSourceAsString( Book.class ) );
System.out.println( getMetaModelSourceAsString( Author.class, true ) ); System.out.println( getMetaModelSourceAsString( Author.class, true ) );
System.out.println( getMetaModelSourceAsString( Book.class, true ) ); System.out.println( getMetaModelSourceAsString( Book.class, true ) );
System.out.println( getMetaModelSourceAsString( Library.class ) ); System.out.println( getMetaModelSourceAsString( Library.class ) );
System.out.println( getMetaModelSourceAsString( Bookshop.class ) );
assertMetamodelClassGeneratedFor( Author.class, true ); assertMetamodelClassGeneratedFor( Author.class, true );
assertMetamodelClassGeneratedFor( Book.class, true ); assertMetamodelClassGeneratedFor( Book.class, true );
assertMetamodelClassGeneratedFor( Publisher.class, true ); assertMetamodelClassGeneratedFor( Publisher.class, true );
@ -32,5 +33,6 @@ public void test() {
assertMetamodelClassGeneratedFor( Book.class ); assertMetamodelClassGeneratedFor( Book.class );
assertMetamodelClassGeneratedFor( Publisher.class ); assertMetamodelClassGeneratedFor( Publisher.class );
assertMetamodelClassGeneratedFor( Library.class ); assertMetamodelClassGeneratedFor( Library.class );
assertMetamodelClassGeneratedFor( Bookshop.class );
} }
} }

View File

@ -854,7 +854,7 @@ private void validateAssociation(Element memberOfClass, AnnotationMirror annotat
switch ( typeMirror.getKind() ) { switch ( typeMirror.getKind() ) {
case TYPEVAR: case TYPEVAR:
if ( hasAnnotation(element, ENTITY) ) { if ( hasAnnotation(element, ENTITY) ) {
context.message(memberOfClass, "type '" + typeMirror + "' is a type variable", message(memberOfClass, "type '" + typeMirror + "' is a type variable",
Diagnostic.Kind.WARNING); Diagnostic.Kind.WARNING);
} }
break; break;
@ -866,13 +866,13 @@ private void validateAssociation(Element memberOfClass, AnnotationMirror annotat
validateBidirectionalMapping(memberOfClass, annotation, mappedBy, assocTypeElement); validateBidirectionalMapping(memberOfClass, annotation, mappedBy, assocTypeElement);
} }
else { else {
context.message(memberOfClass, "type '" + assocTypeElement.getSimpleName() message(memberOfClass, "type '" + assocTypeElement.getSimpleName()
+ "' is not annotated '@Entity'", + "' is not annotated '@Entity'",
Diagnostic.Kind.WARNING); Diagnostic.Kind.WARNING);
} }
break; break;
default: default:
context.message(memberOfClass, "type '" + typeMirror + "' is not an entity type", message(memberOfClass, "type '" + typeMirror + "' is not an entity type",
Diagnostic.Kind.WARNING); Diagnostic.Kind.WARNING);
} }
} }
@ -898,7 +898,7 @@ private void validateBidirectionalMapping(
} }
} }
// not found // not found
context.message(memberOfClass, annotation, message(memberOfClass, annotation,
annotationVal, annotationVal,
"no matching member in '" + assocTypeElement.getSimpleName() + "'", "no matching member in '" + assocTypeElement.getSimpleName() + "'",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
@ -916,7 +916,7 @@ private void validateBackRef(
case ONE_TO_ONE: case ONE_TO_ONE:
backType = attributeType(member); backType = attributeType(member);
if ( !hasAnnotation(member, ONE_TO_ONE) ) { if ( !hasAnnotation(member, ONE_TO_ONE) ) {
context.message(memberOfClass, annotation, annotationVal, message(memberOfClass, annotation, annotationVal,
"member '" + member.getSimpleName() "member '" + member.getSimpleName()
+ "' of '" + assocTypeElement.getSimpleName() + "' of '" + assocTypeElement.getSimpleName()
+ "' is not annotated '@OneToOne'", + "' is not annotated '@OneToOne'",
@ -926,7 +926,7 @@ private void validateBackRef(
case ONE_TO_MANY: case ONE_TO_MANY:
backType = attributeType(member); backType = attributeType(member);
if ( !hasAnnotation(member, MANY_TO_ONE) ) { if ( !hasAnnotation(member, MANY_TO_ONE) ) {
context.message(memberOfClass, annotation, annotationVal, message(memberOfClass, annotation, annotationVal,
"member '" + member.getSimpleName() "member '" + member.getSimpleName()
+ "' of '" + assocTypeElement.getSimpleName() + "' of '" + assocTypeElement.getSimpleName()
+ "' is not annotated '@ManyToOne'", + "' is not annotated '@ManyToOne'",
@ -936,7 +936,7 @@ private void validateBackRef(
case MANY_TO_MANY: case MANY_TO_MANY:
backType = elementType( attributeType(member) ); backType = elementType( attributeType(member) );
if ( !hasAnnotation(member, MANY_TO_MANY) ) { if ( !hasAnnotation(member, MANY_TO_MANY) ) {
context.message(memberOfClass, annotation, annotationVal, message(memberOfClass, annotation, annotationVal,
"member '" + member.getSimpleName() "member '" + member.getSimpleName()
+ "' of '" + assocTypeElement.getSimpleName() + "' of '" + assocTypeElement.getSimpleName()
+ "' is not annotated '@ManyToMany'", + "' is not annotated '@ManyToMany'",
@ -948,7 +948,7 @@ private void validateBackRef(
} }
if ( backType!=null if ( backType!=null
&& !context.getTypeUtils().isSameType(backType, element.asType()) ) { && !context.getTypeUtils().isSameType(backType, element.asType()) ) {
context.message(memberOfClass, annotation, annotationVal, message(memberOfClass, annotation, annotationVal,
"member '" + member.getSimpleName() "member '" + member.getSimpleName()
+ "' of '" + assocTypeElement.getSimpleName() + "' of '" + assocTypeElement.getSimpleName()
+ "' is not of type '" + element.getSimpleName() + "'", + "' is not of type '" + element.getSimpleName() + "'",
@ -1031,7 +1031,7 @@ else if ( kind == TypeKind.DECLARED ) {
} }
break; break;
default: default:
context.message( method, message( method,
"incorrect return type '" + declaredType + "'", "incorrect return type '" + declaredType + "'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
break; break;
@ -1047,7 +1047,7 @@ private boolean validatedQueryReturnType(ExecutableElement method, TypeElement t
if ( method.getParameters().stream() if ( method.getParameters().stream()
.noneMatch(param -> param.asType().toString() .noneMatch(param -> param.asType().toString()
.startsWith(JD_PAGE_REQUEST))) { .startsWith(JD_PAGE_REQUEST))) {
context.message(method, message(method,
"method with return type '" + typeName "method with return type '" + typeName
+ "' has no parameter of type 'PageRequest'", + "' has no parameter of type 'PageRequest'",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
@ -1060,7 +1060,7 @@ private boolean validatedQueryReturnType(ExecutableElement method, TypeElement t
if ( method.getParameters().stream() if ( method.getParameters().stream()
.noneMatch(param -> param.asType().toString() .noneMatch(param -> param.asType().toString()
.startsWith(HIB_KEYED_PAGE))) { .startsWith(HIB_KEYED_PAGE))) {
context.message(method, message(method,
"method with return type '" + typeName "method with return type '" + typeName
+ "' has no parameter of type 'KeyedPage'", + "' has no parameter of type 'KeyedPage'",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
@ -1074,7 +1074,7 @@ private boolean validatedQueryReturnType(ExecutableElement method, TypeElement t
return true; return true;
} }
else { else {
context.message(method, message(method,
"incorrect return type '" + typeName + "'", "incorrect return type '" + typeName + "'",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
return false; return false;
@ -1139,7 +1139,7 @@ private void addDeleteMethod(ExecutableElement method, @Nullable TypeMirror retu
if ( kind != TypeKind.VOID if ( kind != TypeKind.VOID
&& kind != TypeKind.INT && kind != TypeKind.INT
&& kind != TypeKind.LONG ) { && kind != TypeKind.LONG ) {
context.message(method, message(method,
"must be 'void' or return 'int' or 'long'", "must be 'void' or return 'int' or 'long'",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
} }
@ -1154,18 +1154,18 @@ private void addLifecycleMethod(ExecutableElement method) {
if ( !HIB_STATELESS_SESSION.equals(sessionType) if ( !HIB_STATELESS_SESSION.equals(sessionType)
&& !MUTINY_STATELESS_SESSION.equals(sessionType) && !MUTINY_STATELESS_SESSION.equals(sessionType)
&& !UNI_MUTINY_STATELESS_SESSION.equals(sessionType) ) { && !UNI_MUTINY_STATELESS_SESSION.equals(sessionType) ) {
context.message( method, message( method,
"repository must be backed by a 'StatelessSession'", "repository must be backed by a 'StatelessSession'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( method.getParameters().size() != 1 ) { else if ( method.getParameters().size() != 1 ) {
context.message( method, message( method,
"must have exactly one parameter", "must have exactly one parameter",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( returnType == null ) { else if ( returnType == null ) {
context.message( method, message( method,
"must be declared 'void'", "must be declared 'void'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1177,20 +1177,20 @@ else if ( returnType == null ) {
final TypeMirror parameterType = parameterType( parameter ); final TypeMirror parameterType = parameterType( parameter );
final DeclaredType declaredType = entityType( parameterType ); final DeclaredType declaredType = entityType( parameterType );
if ( declaredType == null ) { if ( declaredType == null ) {
context.message( parameter, message( parameter,
"incorrect parameter type '" + parameterType + "' is not an entity type", "incorrect parameter type '" + parameterType + "' is not an entity type",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( !containsAnnotation( declaredType.asElement(), ENTITY ) else if ( !containsAnnotation( declaredType.asElement(), ENTITY )
// TODO: improve this (carefully consider the case of an erased type variable) // TODO: improve this (carefully consider the case of an erased type variable)
&& declaredParameterType == parameterType ) { && declaredParameterType == parameterType ) {
context.message( parameter, message( parameter,
"incorrect parameter type '" + parameterType + "' is not annotated '@Entity'", "incorrect parameter type '" + parameterType + "' is not annotated '@Entity'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( returnArgument else if ( returnArgument
&& !context.getTypeUtils().isSameType( returnType, declaredParameterType ) ) { && !context.getTypeUtils().isSameType( returnType, declaredParameterType ) ) {
context.message( parameter, message( parameter,
"return type '" + returnType "return type '" + returnType
+ "' disagrees with parameter type '" + parameterType + "'", + "' disagrees with parameter type '" + parameterType + "'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -1301,7 +1301,7 @@ private void addFinderMethod(
@Nullable TypeMirror returnType, @Nullable TypeMirror returnType,
@Nullable TypeElement containerType) { @Nullable TypeElement containerType) {
if ( returnType == null ) { if ( returnType == null ) {
context.message( method, message( method,
"missing return type", "missing return type",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1309,7 +1309,7 @@ else if ( returnType.getKind() == TypeKind.ARRAY ) {
final ArrayType arrayType = (ArrayType) returnType; final ArrayType arrayType = (ArrayType) returnType;
final TypeMirror componentType = arrayType.getComponentType(); final TypeMirror componentType = arrayType.getComponentType();
if ( componentType.getKind() != TypeKind.DECLARED ) { if ( componentType.getKind() != TypeKind.DECLARED ) {
context.message( method, message( method,
"incorrect return type '" + returnType + "' is not an array with entity elements", "incorrect return type '" + returnType + "' is not an array with entity elements",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1317,7 +1317,7 @@ else if ( returnType.getKind() == TypeKind.ARRAY ) {
final DeclaredType declaredType = (DeclaredType) componentType; final DeclaredType declaredType = (DeclaredType) componentType;
final TypeElement entity = (TypeElement) declaredType.asElement(); final TypeElement entity = (TypeElement) declaredType.asElement();
if ( !containsAnnotation( entity, ENTITY ) ) { if ( !containsAnnotation( entity, ENTITY ) ) {
context.message( method, message( method,
"incorrect return type '" + returnType + "' is not annotated '@Entity'", "incorrect return type '" + returnType + "' is not annotated '@Entity'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1331,7 +1331,7 @@ else if ( returnType.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) ununi( returnType ); final DeclaredType declaredType = (DeclaredType) ununi( returnType );
final TypeElement entity = (TypeElement) declaredType.asElement(); final TypeElement entity = (TypeElement) declaredType.asElement();
if ( !containsAnnotation( entity, ENTITY ) ) { if ( !containsAnnotation( entity, ENTITY ) ) {
context.message( method, message( method,
"incorrect return type '" + declaredType + "' is not annotated '@Entity'", "incorrect return type '" + declaredType + "' is not annotated '@Entity'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1344,10 +1344,10 @@ else if ( returnType.getKind() == TypeKind.DECLARED ) {
for ( VariableElement parameter : method.getParameters() ) { for ( VariableElement parameter : method.getParameters() ) {
final String type = parameter.asType().toString(); final String type = parameter.asType().toString();
if ( isPageParam(type) ) { if ( isPageParam(type) ) {
context.message( parameter, "pagination would have no effect", Diagnostic.Kind.ERROR); message( parameter, "pagination would have no effect", Diagnostic.Kind.ERROR);
} }
else if ( isOrderParam(type) ) { else if ( isOrderParam(type) ) {
context.message( parameter, "ordering would have no effect", Diagnostic.Kind.ERROR); message( parameter, "ordering would have no effect", Diagnostic.Kind.ERROR);
} }
} }
final long parameterCount = final long parameterCount =
@ -1356,7 +1356,7 @@ else if ( isOrderParam(type) ) {
.count(); .count();
switch ( (int) parameterCount ) { switch ( (int) parameterCount ) {
case 0: case 0:
context.message( method, "missing parameter", Diagnostic.Kind.ERROR ); message( method, "missing parameter", Diagnostic.Kind.ERROR );
break; break;
case 1: case 1:
createSingleParameterFinder( method, declaredType, entity ); createSingleParameterFinder( method, declaredType, entity );
@ -1368,7 +1368,7 @@ else if ( isOrderParam(type) ) {
} }
} }
else { else {
context.message( method, message( method,
"incorrect return type '" + returnType + "' is not an entity type", "incorrect return type '" + returnType + "' is not an entity type",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -1432,7 +1432,7 @@ else if ( !types.isSameType( typeArgument, entity.asType() ) ) {
private void createCriteriaDelete(ExecutableElement method, TypeMirror returnType) { private void createCriteriaDelete(ExecutableElement method, TypeMirror returnType) {
final TypeElement entity = primaryEntity; final TypeElement entity = primaryEntity;
if ( entity == null) { if ( entity == null) {
context.message( method, "repository does not have a well-defined primary entity type", message( method, "repository does not have a well-defined primary entity type",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
} }
else { else {
@ -1473,7 +1473,7 @@ private void createCriteriaDelete(ExecutableElement method, TypeMirror returnTyp
} }
private void wrongTypeArgError(String entity, VariableElement parameter, boolean pageRequest) { private void wrongTypeArgError(String entity, VariableElement parameter, boolean pageRequest) {
context.message(parameter, message(parameter,
(pageRequest (pageRequest
? "mismatched type of page request (should be 'PageRequest<? super " ? "mismatched type of page request (should be 'PageRequest<? super "
:"mismatched type of order (should be 'Order<? super ") :"mismatched type of order (should be 'Order<? super ")
@ -1482,7 +1482,7 @@ private void wrongTypeArgError(String entity, VariableElement parameter, boolean
} }
private void missingTypeArgError(String entity, VariableElement parameter, boolean pageRequest) { private void missingTypeArgError(String entity, VariableElement parameter, boolean pageRequest) {
context.message(parameter, message(parameter,
(pageRequest (pageRequest
? "missing type of page request (should be 'PageRequest<? super " ? "missing type of page request (should be 'PageRequest<? super "
: "missing type of order (should be 'Order<? super ") : "missing type of order (should be 'Order<? super ")
@ -1524,7 +1524,7 @@ private OrderBy orderByExpression(AnnotationMirror orderBy, TypeElement entityTy
.replace('$', '.') .replace('$', '.')
.replace('_', '.'); //Jakarta Data allows _ here .replace('_', '.'); //Jakarta Data allows _ here
if ( memberMatchingPath( entityType, path ) == null ) { if ( memberMatchingPath( entityType, path ) == null ) {
context.message( method, orderBy, message( method, orderBy,
"no matching field named '" + fieldName "no matching field named '" + fieldName
+ "' in entity class '" + entityType.getQualifiedName() + "'", + "' in entity class '" + entityType.getQualifiedName() + "'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -1804,7 +1804,7 @@ enum FieldType {
final Element member = memberMatchingPath( entityType, parameterName( param ) ); final Element member = memberMatchingPath( entityType, parameterName( param ) );
if ( member != null ) { if ( member != null ) {
if ( containsAnnotation( member, MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION ) ) { if ( containsAnnotation( member, MANY_TO_MANY, ONE_TO_MANY, ELEMENT_COLLECTION ) ) {
context.message( param, message( param,
"matching field is a collection", "matching field is a collection",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
return null; return null;
@ -1816,7 +1816,8 @@ enum FieldType {
else if ( containsAnnotation( param, PATTERN ) ) { else if ( containsAnnotation( param, PATTERN ) ) {
final AnnotationMirror mirror = getAnnotationMirror(param, PATTERN); final AnnotationMirror mirror = getAnnotationMirror(param, PATTERN);
if ( mirror!=null && !param.asType().toString().equals( String.class.getName() ) ) { if ( mirror!=null && !param.asType().toString().equals( String.class.getName() ) ) {
context.message( param, mirror, "parameter annotated '@Pattern' is not of type 'String'", message( param, mirror,
"parameter annotated '@Pattern' is not of type 'String'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
return FieldType.BASIC; return FieldType.BASIC;
@ -1842,7 +1843,7 @@ else if ( containsAnnotation( member, NATURAL_ID ) ) {
} }
} }
context.message( param, message( param,
"no matching field named '" + parameterName( param ) "no matching field named '" + parameterName( param )
+ "' in entity class '" + entityType + "'", + "' in entity class '" + entityType + "'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -1908,7 +1909,7 @@ private boolean checkParameterType(TypeElement entityType, VariableElement param
} }
private void parameterTypeError(TypeElement entityType, VariableElement param, TypeMirror attributeType) { private void parameterTypeError(TypeElement entityType, VariableElement param, TypeMirror attributeType) {
context.message(param, message(param,
"matching field has type '" + attributeType "matching field has type '" + attributeType
+ "' in entity class '" + entityType + "'", + "' in entity class '" + entityType + "'",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2107,7 +2108,7 @@ private void addQueryMethod(
if ( returnType != null && returnType.getKind() == TypeKind.DECLARED ) { if ( returnType != null && returnType.getKind() == TypeKind.DECLARED ) {
final DeclaredType resultType = (DeclaredType) returnType; final DeclaredType resultType = (DeclaredType) returnType;
if ( !resultType.getTypeArguments().isEmpty() ) { if ( !resultType.getTypeArguments().isEmpty() ) {
context.message(method, mirror, value, message(method, mirror, value,
"query result type may not be a generic type" "query result type may not be a generic type"
+ " (change '" + returnType + + " (change '" + returnType +
"' to '" + context.getTypeUtils().erasure(returnType) + "')", "' to '" + context.getTypeUtils().erasure(returnType) + "')",
@ -2163,7 +2164,7 @@ private void validateUpdateHql(
AnnotationValue value) { AnnotationValue value) {
boolean reactive = usingReactiveSession( sessionType ); boolean reactive = usingReactiveSession( sessionType );
if ( !isValidUpdateReturnType( returnType, method, reactive ) ) { if ( !isValidUpdateReturnType( returnType, method, reactive ) ) {
context.message( method, mirror, value, message( method, mirror, value,
"return type of mutation query method must be " + (!reactive ? "'int', 'boolean' or 'void'" : "'Uni<Integer>', 'Uni<Boolean>' or 'Uni<Void>'"), "return type of mutation query method must be " + (!reactive ? "'int', 'boolean' or 'void'" : "'Uni<Integer>', 'Uni<Boolean>' or 'Uni<Void>'"),
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
@ -2205,7 +2206,7 @@ private void validateSelectHql(
break; break;
case DECLARED: case DECLARED:
if ( !checkConstructorReturn( (DeclaredType) returnType, selection ) ) { if ( !checkConstructorReturn( (DeclaredType) returnType, selection ) ) {
context.message(method, mirror, value, message(method, mirror, value,
"return type '" + returnType "return type '" + returnType
+ "' of method has no constructor matching query selection list", + "' of method has no constructor matching query selection list",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
@ -2238,7 +2239,7 @@ else if ( selection instanceof JpaRoot ) {
} }
} }
if ( !returnTypeCorrect ) { if ( !returnTypeCorrect ) {
context.message(method, mirror, value, message(method, mirror, value,
"return type of query did not match return type '" + returnType + "' of method", "return type of query did not match return type '" + returnType + "' of method",
Diagnostic.Kind.ERROR); Diagnostic.Kind.ERROR);
} }
@ -2258,7 +2259,7 @@ private void validateSql(
public void ordinalParameter(int sourcePosition) { public void ordinalParameter(int sourcePosition) {
ordinalCount++; ordinalCount++;
if ( ordinalCount > paramNames.size() ) { if ( ordinalCount > paramNames.size() ) {
context.message(method, mirror, value, message(method, mirror, value,
"missing method parameter for query parameter " + ordinalCount "missing method parameter for query parameter " + ordinalCount
+ " (add a parameter to '" + method.getSimpleName() + "')", + " (add a parameter to '" + method.getSimpleName() + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2268,7 +2269,7 @@ public void ordinalParameter(int sourcePosition) {
@Override @Override
public void namedParameter(String name, int sourcePosition) { public void namedParameter(String name, int sourcePosition) {
if ( !paramNames.contains(name) ) { if ( !paramNames.contains(name) ) {
context.message(method, mirror, value, message(method, mirror, value,
"missing method parameter for query parameter :" + name "missing method parameter for query parameter :" + name
+ " (add a parameter '" + name + "' to '" + method.getSimpleName() + "')", + " (add a parameter '" + name + "' to '" + method.getSimpleName() + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2278,7 +2279,7 @@ public void namedParameter(String name, int sourcePosition) {
@Override @Override
public void jpaPositionalParameter(int label, int sourcePosition) { public void jpaPositionalParameter(int label, int sourcePosition) {
if ( label > paramNames.size() ) { if ( label > paramNames.size() ) {
context.message(method, mirror, value, message(method, mirror, value,
"missing method parameter for query parameter ?" + label "missing method parameter for query parameter ?" + label
+ " (add a parameter to '" + method.getSimpleName() + "')", + " (add a parameter to '" + method.getSimpleName() + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2399,13 +2400,13 @@ private void checkParameter(
final String name = param.getName(); final String name = param.getName();
int index = paramNames.indexOf( name ); int index = paramNames.indexOf( name );
if ( index < 0 ) { if ( index < 0 ) {
context.message( method, mirror, value, message( method, mirror, value,
"missing method parameter for query parameter :" + name "missing method parameter for query parameter :" + name
+ " (add a parameter '" + queryParamType + ' ' + name + "' to '" + method.getSimpleName() + "')", + " (add a parameter '" + queryParamType + ' ' + name + "' to '" + method.getSimpleName() + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( !isLegalAssignment( paramTypes.get(index), queryParamType ) ) { else if ( !isLegalAssignment( paramTypes.get(index), queryParamType ) ) {
context.message( method, mirror, value, message( method, mirror, value,
"parameter matching query parameter :" + name + " has the wrong type" "parameter matching query parameter :" + name + " has the wrong type"
+ " (change the method parameter type to '" + queryParamType + "')", + " (change the method parameter type to '" + queryParamType + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2414,13 +2415,13 @@ else if ( !isLegalAssignment( paramTypes.get(index), queryParamType ) ) {
else if ( param.getPosition() != null ) { else if ( param.getPosition() != null ) {
int position = param.getPosition(); int position = param.getPosition();
if ( position > paramNames.size() ) { if ( position > paramNames.size() ) {
context.message( method, mirror, value, message( method, mirror, value,
"missing method parameter for query parameter ?" + position "missing method parameter for query parameter ?" + position
+ " (add a parameter of type '" + queryParamType + "' to '" + method.getSimpleName() + "')", + " (add a parameter of type '" + queryParamType + "' to '" + method.getSimpleName() + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
} }
else if ( !isLegalAssignment( paramTypes.get(position-1), queryParamType ) ) { else if ( !isLegalAssignment( paramTypes.get(position-1), queryParamType ) ) {
context.message( method, mirror, value, message( method, mirror, value,
"parameter matching query parameter ?" + position + " has the wrong type" "parameter matching query parameter ?" + position + " has the wrong type"
+ " (change the method parameter type to '" + queryParamType + "')", + " (change the method parameter type to '" + queryParamType + "')",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2588,7 +2589,7 @@ private void checkParameters(
final String param = paramNames.get(i-1); final String param = paramNames.get(i-1);
final String type = paramTypes.get(i-1); final String type = paramTypes.get(i-1);
if ( parameterIsMissing( hql, i, param, type ) ) { if ( parameterIsMissing( hql, i, param, type ) ) {
context.message( method, mirror, value, message( method, mirror, value,
"missing query parameter for '" + param "missing query parameter for '" + param
+ "' (no parameter named :" + param + " or ?" + i + ")", + "' (no parameter named :" + param + " or ?" + i + ")",
Diagnostic.Kind.ERROR ); Diagnostic.Kind.ERROR );
@ -2639,4 +2640,52 @@ static boolean usingReactiveSessionAccess(String sessionType) {
return UNI_MUTINY_SESSION.equals(sessionType) return UNI_MUTINY_SESSION.equals(sessionType)
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType); || UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
} }
private boolean isLocal(Element methodOrParam) {
switch (methodOrParam.getKind()) {
case PARAMETER:
return element.getEnclosedElements()
.contains( methodOrParam.getEnclosingElement() );
case METHOD:
case FIELD:
return element.getEnclosedElements()
.contains( methodOrParam );
default:
return true;
}
}
public void message(Element method, String message, Diagnostic.Kind severity) {
if ( isLocal(method) ) {
context.message(method, message, severity);
}
else {
context.message(element, messageWithLocation(method, message), severity);
}
}
public void message(Element method, AnnotationMirror mirror, String message, Diagnostic.Kind severity) {
if ( isLocal(method) ) {
context.message(method, mirror, message, severity);
}
else {
context.message(element, messageWithLocation(method, message), severity);
}
}
public void message(Element method, AnnotationMirror mirror, AnnotationValue value, String message, Diagnostic.Kind severity) {
if ( isLocal(method) ) {
context.message(method, mirror, value, message, severity);
}
else {
context.message(element, messageWithLocation(method, message), severity);
}
}
private static String messageWithLocation(Element element, String message) {
return element.getKind() == ElementKind.PARAMETER
? message + " for parameter '" + element.getSimpleName()
+ "' of inherited member '" + element.getEnclosingElement().getSimpleName() + "'"
: message + " for inherited member '" + element.getSimpleName() + "'";
}
} }