Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2025 IBM Corporation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/

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

import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;

/**
* Utility class for common IntelliJ PSI-based diagnostic logic.
*/
public class DiagnosticsUtils {

/**
* inheritsFrom
* Check if specified superType is present or not in the type hierarchy
*
* @param clazz
* @param fqSuperType
* @return
*/
public 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));
}
}
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 Down Expand Up @@ -63,6 +63,8 @@ public class BeanValidationConstants {
public static final String STRING = "java.lang.String";
public static final String BIG_INTEGER = "java.math.BigInteger";
public static final String BIG_DECIMAL = "java.math.BigDecimal";
public static final String COLLECTION_FQ = "java.util.Collection";
public static final String MAP_FQ = "java.util.Map";

public static final String DIAGNOSTIC_SOURCE = "jakarta-bean-validation";
public static final String DIAGNOSTIC_CODE_INVALID_TYPE = "FixTypeOfElement";
Expand Down
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 @@ -14,11 +14,13 @@
package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.beanvalidation;

import com.intellij.psi.*;
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;
import org.eclipse.lsp4j.DiagnosticSeverity;

import static io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.DiagnosticsUtils.inheritsFrom;
import static io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils.getSimpleName;
import static io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.beanvalidation.BeanValidationConstants.*;

Expand Down Expand Up @@ -159,40 +161,40 @@ 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, CHAR_SEQUENCE)
|| inheritsFrom(resolvedClass, COLLECTION_FQ)
|| inheritsFrom(resolvedClass, MAP_FQ));
}

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 fields of type CharSequence, Collection, Array, or Map.
SizeOrNonEmptyAnnotationsMethod = This annotation can only be used on methods that have CharSequence, Collection, Array or Map as a return type.
# 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
Loading