Skip to content

Commit

Permalink
build: Improve Compatibility verification
Browse files Browse the repository at this point in the history
Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Aug 19, 2024
1 parent 869ead4 commit 0097214
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 406 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,17 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiAnnotationMethod;
import com.intellij.psi.PsiArrayType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLiteral;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeParameter;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -288,7 +270,7 @@ public static VirtualFile getRootDirectory(PsiElement element) {
return getRootDirectory(PsiTreeUtil.getParentOfType(element, PsiFile.class));
}

public static VirtualFile getRootDirectory(PsiFile file) {
public static @Nullable VirtualFile getRootDirectory(PsiFile file) {
ProjectFileIndex index = ProjectFileIndex.getInstance(file.getProject());
VirtualFile directory = index.getSourceRootForFile(file.getVirtualFile());
if (directory == null) {
Expand All @@ -297,25 +279,6 @@ public static VirtualFile getRootDirectory(PsiFile file) {
return directory;
}

public static String getLocation(Project project, VirtualFile directory) {
String location = null;
Module module = ProjectFileIndex.getInstance(project).getModuleForFile(directory);
if (module != null) {
VirtualFile moduleRoot = LocalFileSystem.getInstance().findFileByIoFile(new File(module.getModuleFilePath()).getParentFile());
String path = VfsUtilCore.getRelativePath(directory, moduleRoot);
if (path != null) {
location = '/' + module.getName() + '/' + path;
}
}
if (location == null) {
location = directory.getPath();
}
if (location.endsWith("!/")) {
location = location.substring(0, location.length() - 2);
}
return location;
}

public static boolean overlaps(TextRange typeRange, TextRange methodRange) {
if (typeRange == null || methodRange == null) {
return false;
Expand Down Expand Up @@ -347,6 +310,6 @@ public static String getRawResolvedTypeName(PsiMethod method) {
* @return
*/
public static boolean isVoidReturnType(PsiMethod method) {
return PsiType.VOID.equals(method.getReturnType());
return PsiTypes.voidType().equals(method.getReturnType());
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. 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
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
* Copyright (c) 2023 Red Hat Inc. 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
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.graphql.java;


import java.text.MessageFormat;
import java.util.logging.Logger;
import java.util.regex.Matcher;

import com.intellij.openapi.module.Module;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiArrayInitializerMemberValue;
import com.intellij.psi.PsiArrayType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiJvmModifiersOwner;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.diagnostics.JavaDiagnosticsContext;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.validators.JavaASTValidator;
Expand All @@ -38,18 +24,22 @@
import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.graphql.TypeSystemDirectiveLocation;
import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.jetbrains.annotations.NotNull;

import java.text.MessageFormat;
import java.util.logging.Logger;

import static com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.AnnotationUtils.getAnnotation;
import static com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.AnnotationUtils.isMatchAnnotation;

/**
* Diagnostics for microprofile-graphql.
*
* <p>
* TODO: We currently don't check directives on input/output objects and their properties, because
* it's not trivial to determine whether a class is used as an input, or an output, or both. That
* will possibly require building the whole GraphQL schema on-the-fly, which might be too expensive.
*
* @see https://download.eclipse.org/microprofile/microprofile-graphql-1.0/microprofile-graphql.html
* @see <a href="https://download.eclipse.org/microprofile/microprofile-graphql-1.0/microprofile-graphql.html">MicroProfile GraphQL</a>
*/
public class MicroProfileGraphQLASTValidator extends JavaASTValidator {

Expand All @@ -67,7 +57,7 @@ public class MicroProfileGraphQLASTValidator extends JavaASTValidator {
@Override
public boolean isAdaptedForDiagnostics(JavaDiagnosticsContext context) {
Module javaProject = context.getJavaProject();
if(PsiTypeUtils.findType(javaProject, MicroProfileGraphQLConstants.QUERY_ANNOTATION) == null) {
if (PsiTypeUtils.findType(javaProject, MicroProfileGraphQLConstants.QUERY_ANNOTATION) == null) {
return false;
}
// void GraphQL operations are allowed in Quarkus 3.1 and higher
Expand All @@ -81,9 +71,9 @@ public boolean isAdaptedForDiagnostics(JavaDiagnosticsContext context) {
}

@Override
public void visitMethod(PsiMethod node) {
public void visitMethod(@NotNull PsiMethod node) {
validateDirectivesOnMethod(node);
if(!allowsVoidReturnFromOperations) {
if (!allowsVoidReturnFromOperations) {
validateNoVoidReturnedFromOperations(node);
}
validateMultiReturnTypeFromSubscriptions(node);
Expand All @@ -92,7 +82,7 @@ public void visitMethod(PsiMethod node) {
}

@Override
public void visitClass(PsiClass node) {
public void visitClass(@NotNull PsiClass node) {
validateDirectivesOnClass(node);
super.visitClass(node);
}
Expand All @@ -115,13 +105,13 @@ private void validateDirectivesOnMethod(PsiMethod node) {

private void validateDirectivesOnClass(PsiClass node) {
// a class with @GraphQLApi may only have directives allowed on SCHEMA
if(getAnnotation(node, MicroProfileGraphQLConstants.GRAPHQL_API_ANNOTATION) != null) {
if (getAnnotation(node, MicroProfileGraphQLConstants.GRAPHQL_API_ANNOTATION) != null) {
validateDirectives(node, TypeSystemDirectiveLocation.SCHEMA);
}
// if an interface has a `@Union` annotation, it may only have directives allowed on UNION
// otherwise it may only have directives allowed on INTERFACE
if (node.isInterface()) {
if(getAnnotation(node, MicroProfileGraphQLConstants.UNION_ANNOTATION) != null) {
if (getAnnotation(node, MicroProfileGraphQLConstants.UNION_ANNOTATION) != null) {
validateDirectives(node, TypeSystemDirectiveLocation.UNION);
} else {
validateDirectives(node, TypeSystemDirectiveLocation.INTERFACE);
Expand All @@ -132,7 +122,7 @@ else if (node.isEnum()) {
validateDirectives(node, TypeSystemDirectiveLocation.ENUM);
// enum values may only have directives allowed on ENUM_VALUE
for (PsiField field : node.getFields()) {
if(field instanceof PsiEnumConstant) {
if (field instanceof PsiEnumConstant) {
validateDirectives(field, TypeSystemDirectiveLocation.ENUM_VALUE);
}
}
Expand Down Expand Up @@ -199,12 +189,11 @@ private PsiClass getDirectiveDeclaration(PsiAnnotation annotation) {

private void validateNoVoidReturnedFromOperations(PsiMethod node) {
// ignore constructors, and non-void methods for now, it's faster than iterating through all annotations
if (node.getReturnTypeElement() == null ||
!PsiType.VOID.equals(node.getReturnType())) {
if (node.getReturnTypeElement() == null || !PsiTypeUtils.isVoidReturnType(node)) {
return;
}
for (PsiAnnotation annotation : node.getAnnotations()) {
if (isMatchAnnotation(annotation, MicroProfileGraphQLConstants.QUERY_ANNOTATION) ) {
if (isMatchAnnotation(annotation, MicroProfileGraphQLConstants.QUERY_ANNOTATION)) {
super.addDiagnostic(NO_VOID_MESSAGE, //
MicroProfileGraphQLConstants.DIAGNOSTIC_SOURCE, //
node.getReturnTypeElement(), //
Expand All @@ -224,12 +213,12 @@ private void validateNoVoidReturnedFromOperations(PsiMethod node) {
* A method annotated with `@Subscription` must return a `Multi` or `Flow.Publisher`.
*/
private void validateMultiReturnTypeFromSubscriptions(PsiMethod node) {
if(node.getReturnType() == null) {
if (node.getReturnType() == null) {
return;
}
for (PsiAnnotation annotation : node.getAnnotations()) {
if (isMatchAnnotation(annotation, MicroProfileGraphQLConstants.SUBSCRIPTION_ANNOTATION)) {
if(node.getReturnType().equals(PsiType.VOID)) {
if (PsiTypeUtils.isVoidReturnType(node)) {
super.addDiagnostic(SUBSCRIPTION_MUST_RETURN_MULTI,
MicroProfileGraphQLConstants.DIAGNOSTIC_SOURCE,
node.getReturnTypeElement(),
Expand Down Expand Up @@ -258,7 +247,7 @@ private void validateMultiReturnTypeFromSubscriptions(PsiMethod node) {
* a `Multi` or `Flow.Publisher` type.
*/
private void validateNoMultiReturnTypeFromQueriesAndMutations(PsiMethod node) {
if(node.getReturnType() == null) {
if (node.getReturnType() == null) {
return;
}
for (PsiAnnotation annotation : node.getAnnotations()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@
import com.intellij.facet.FacetManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.RootPolicy;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl;
import com.redhat.devtools.intellij.quarkus.facet.QuarkusFacet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -59,7 +62,7 @@ public class QuarkusModuleUtil {
* @return true if module is a Quarkus project and false otherwise.
*/
public static boolean isQuarkusModule(Module module) {
return hasLibrary(module, QuarkusConstants.QUARKUS_CORE_PREFIX);
return hasLibrary(module, QuarkusConstants.QUARKUS_CORE_PREFIX);
}

/**
Expand Down Expand Up @@ -148,13 +151,7 @@ private static boolean isQuarkusModule(VirtualFile file, Project project) {
return module != null && (FacetManager.getInstance(module).getFacetByType(QuarkusFacet.FACET_TYPE_ID) != null || QuarkusModuleUtil.isQuarkusModule(module));
}

public static VirtualFile getModuleDirPath(Module module) {
ModuleRootManager manager = ModuleRootManager.getInstance(module);
VirtualFile[] roots = manager.getContentRoots();
if (roots.length > 0) {
return roots[0];
} else {
return VfsUtil.findFileByIoFile(new File(module.getModuleFilePath()).getParentFile(), true);
}
public static @Nullable VirtualFile getModuleDirPath(@NotNull Module module) {
return LocalFileSystem.getInstance().findFileByPath(ModuleUtilCore.getModuleDirPath(module));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private void collectClassesAndInterfaces(PsiPackage packageRoot, List<JavaTypeIn
}
} else {
// Search classes by the name (without the package name)
PrefixMatcher matcher = new CamelHumpMatcher(typeName, true, false);
PrefixMatcher matcher = new CamelHumpMatcher(typeName, true);
matcher = new BetterPrefixMatcher(matcher, Integer.MIN_VALUE);

final List<String> existing = new ArrayList<>();
Expand Down
Loading

0 comments on commit 0097214

Please sign in to comment.