Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020, 2024 IBM Corporation, Reza Akhavan and others.
* Copyright (c) 2020, 2025 IBM Corporation, Reza Akhavan and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -13,7 +13,10 @@

package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.beanvalidation;

import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.AbstractDiagnosticsCollector;
import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages;
import org.eclipse.lsp4j.Diagnostic;
Expand Down Expand Up @@ -159,40 +162,57 @@ private void validAnnotation(PsiElement element, PsiAnnotation annotation, Strin
diagnostics.add(createDiagnostic(element, (PsiJavaFile) element.getContainingFile(),
source, DIAGNOSTIC_CODE_INVALID_TYPE, annotationName, DiagnosticSeverity.Error));
}
} else if (matchedAnnotation.equals(NOT_EMPTY) || matchedAnnotation.equals(SIZE)) {
if (!(isSizeOrNonEmptyAllowed(type))) {
String source = isMethod ?
Messages.getMessage("SizeOrNonEmptyAnnotationsMethod") : Messages.getMessage(
"SizeOrNonEmptyAnnotationsField");
diagnostics.add(createDiagnostic(element, (PsiJavaFile) element.getContainingFile(),
source, DIAGNOSTIC_CODE_INVALID_TYPE, annotationName, DiagnosticSeverity.Error));
}
}

// These ones contains check on all collection types which requires resolving
// the String of the type somehow
// This will also require us to check if the field type was a custom collection
// subtype which means we
// have to resolve it and get the super interfaces and check to see if
// Collection, Map or Array was implemented
// for that custom type (which could as well be a user made subtype)

// else if (annotation.getElementName().equals(NOT_EMPTY) || annotation.getElementName().equals(SIZE)) {
//
// System.out.println("--Field name: " + Signature.getTypeSignatureKind(fieldType));
// System.out.println("--Field name: " + Signature.getParameterTypes(fieldType));
// if ( !fieldType.equals(getSignatureFormatOfType(CHAR_SEQUENCE)) &&
// !fieldType.contains("List") &&
// !fieldType.contains("Set") &&
// !fieldType.contains("Collection") &&
// !fieldType.contains("Array") &&
// !fieldType.contains("Vector") &&
// !fieldType.contains("Stack") &&
// !fieldType.contains("Queue") &&
// !fieldType.contains("Deque") &&
// !fieldType.contains("Map")) {
//
// diagnostics.add(new Diagnostic(fieldAnnotationrange,
// "This annotation can only be used on CharSequence, Collection, Array, "
// + "Map type fields."));
// }
// }
}
}
}

/**
* isSizeOrNonEmptyAllowed
* This method checks whether the supported types for the Size and NotEmpty annotations are CharSequence, Collection, Map, or array.
*
* @param childType
* @return
*/
public static boolean isSizeOrNonEmptyAllowed(PsiType childType) {

if (childType instanceof PsiArrayType) {
return true;
}
if (childType instanceof PsiPrimitiveType) {
return false;
}
PsiClass resolvedClass = PsiUtil.resolveClassInClassTypeOnly(childType);
return resolvedClass != null && (inheritsFrom(resolvedClass, "java.lang.CharSequence")
|| inheritsFrom(resolvedClass, "java.util.Collection")
|| inheritsFrom(resolvedClass, "java.util.Map"));
}

/**
* inheritsFrom
* Check if specified superType is present or not in the type hierarchy
*
* @param clazz
* @param fqSuperType
* @return
*/
private static boolean inheritsFrom(PsiClass clazz, String fqSuperType) {
Project project = clazz.getProject();
PsiClass superClass = JavaPsiFacade.getInstance(project)
.findClass(fqSuperType, GlobalSearchScope.allScope(project));
return superClass != null &&
(clazz.isEquivalentTo(superClass) || clazz.isInheritor(superClass, true));
}


private void checkStringOnly(PsiElement element, List<Diagnostic> diagnostics, String annotationName, boolean isMethod, PsiType type) {
if (!type.getCanonicalText().equals(STRING)
&& !type.getCanonicalText().equals(CHAR_SEQUENCE)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# /*******************************************************************************
# * Copyright (c) 2022, 2024 IBM Corporation and others.
# * Copyright (c) 2022, 2025 IBM Corporation and others.
# *
# * This program and the accompanying materials are made available under the
# * terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -65,6 +65,8 @@ AnnotationStringMethods = The {0} annotation can only be used on String and Char
AnnotationStringFields = The {0} annotation can only be used on String and CharSequence type fields.
AnnotationDateMethods = The {0} annotation can only be used on: Date, Calendar, Instant, LocalDate, LocalDateTime, LocalTime, MonthDay, OffsetDateTime, OffsetTime, Year, YearMonth, ZonedDateTime, HijrahDate, JapaneseDate, JapaneseDate, MinguoDate and ThaiBuddhistDate type methods.
AnnotationDateFields = The {0} annotation can only be used on: Date, Calendar, Instant, LocalDate, LocalDateTime, LocalTime, MonthDay, OffsetDateTime, OffsetTime, Year, YearMonth, ZonedDateTime, HijrahDate, JapaneseDate, JapaneseDate, MinguoDate and ThaiBuddhistDate type fields.
SizeOrNonEmptyAnnotationsField = This annotation can only be used on CharSequence, Collection, Array, Map type fields.
SizeOrNonEmptyAnnotationsMethod = This annotation can only be used on CharSequence, Collection, Array, Map return type methods.
# The next two messages do not include CharSequence
AnnotationMinMaxMethods = The {0} annotation can only be used on \n- BigDecimal \n- BigInteger\n- byte, short, int, long (and their respective wrappers) \n type methods.
AnnotationMinMaxFields = The {0} annotation can only be used on \n- BigDecimal \n- BigInteger\n- byte, short, int, long (and their respective wrappers) \n type fields.
Expand Down
Loading