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 aef99ea
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 407 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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
import com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants;
import com.redhat.qute.commons.ProjectInfo;
Expand Down Expand Up @@ -120,7 +121,7 @@ private static String getTemplateBaseDir(Module javaProject) {
if (roots.length > 0) {
return roots[0];
}
return javaProject.getModuleFile();
return QuarkusModuleUtil.getModuleDirPath(javaProject);
}

/**
Expand Down
Loading

0 comments on commit aef99ea

Please sign in to comment.