mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup [java]: JavaPsiAnnotationUtil.processPackageAnnotations; use in MethodUtils.findAnnotationInTree
GitOrigin-RevId: 3b3dc8c976638b26fe6bdc5c3bf2e968dca861c1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f025ab655a
commit
8aa429fe4c
+103
@@ -0,0 +1,103 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeserver.core;
|
||||
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Utility methods related to {@link PsiAnnotation}.
|
||||
*/
|
||||
public final class JavaPsiAnnotationUtil {
|
||||
/**
|
||||
* @param annotation annotation class
|
||||
* @return annotation retention policy; null if cannot be determined
|
||||
*/
|
||||
public static @Nullable RetentionPolicy getRetentionPolicy(@NotNull PsiClass annotation) {
|
||||
PsiModifierList modifierList = annotation.getModifierList();
|
||||
if (modifierList != null) {
|
||||
PsiAnnotation retentionAnno = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION);
|
||||
if (retentionAnno == null) return RetentionPolicy.CLASS;
|
||||
|
||||
PsiAnnotationMemberValue policyRef = PsiImplUtil.findAttributeValue(retentionAnno, null);
|
||||
if (policyRef instanceof PsiReference ref) {
|
||||
PsiElement field = ref.resolve();
|
||||
if (field instanceof PsiEnumConstant constant) {
|
||||
String name = constant.getName();
|
||||
try {
|
||||
return Enum.valueOf(RetentionPolicy.class, name);
|
||||
}
|
||||
catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process package annotations related to the specified {@link PsiFile}.
|
||||
* Only annotations declared in package-info files within the same source root will be processed.
|
||||
* Both source and class files are supported.
|
||||
*
|
||||
* @param file context {@link PsiFile} to find and process annotations related to
|
||||
* @param processor a processor function
|
||||
* @param processSuperPackages whether to process annotations from super-packages.
|
||||
* A super-package is a package whose qualified name is a prefix of a current package name
|
||||
* (e.g., package "com.example" is a super-package of "com.example.foo")
|
||||
*/
|
||||
public static void processPackageAnnotations(@NotNull PsiFile file,
|
||||
@NotNull PackageAnnotationProcessor processor,
|
||||
boolean processSuperPackages) {
|
||||
boolean superPackage = false;
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(file.getProject()).getFileIndex();
|
||||
VirtualFile vFile = file.getVirtualFile();
|
||||
if (vFile == null) return;
|
||||
VirtualFile root = index.getSourceRootForFile(vFile);
|
||||
boolean compiled = false;
|
||||
if (root == null) {
|
||||
root = index.getClassRootForFile(vFile);
|
||||
if (root == null) return;
|
||||
compiled = true;
|
||||
}
|
||||
// Single-file source root -- no package-info processing for now
|
||||
if (root.equals(vFile)) return;
|
||||
PsiDirectory directory = file.getContainingDirectory();
|
||||
while (directory != null) {
|
||||
PsiFile packageFile = directory.findFile(compiled ? PsiPackage.PACKAGE_INFO_CLS_FILE : PsiPackage.PACKAGE_INFO_FILE);
|
||||
if (packageFile instanceof PsiJavaFile javaFile) {
|
||||
PsiPackageStatement stmt = javaFile.getPackageStatement();
|
||||
if (stmt != null) {
|
||||
PsiModifierList modifierList = stmt.getAnnotationList();
|
||||
if (modifierList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
processor.process(annotation, superPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!processSuperPackages || root.equals(directory.getVirtualFile())) break;
|
||||
directory = directory.getParentDirectory();
|
||||
superPackage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A functional interface to be used with {@link #processPackageAnnotations(PsiFile, PackageAnnotationProcessor, boolean)}
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface PackageAnnotationProcessor {
|
||||
/**
|
||||
* @param annotation applicable package annotation
|
||||
* @param superPackage whether the annotation is from a super-package
|
||||
*/
|
||||
void process(@NotNull PsiAnnotation annotation, boolean superPackage);
|
||||
}
|
||||
}
|
||||
+1
@@ -3,6 +3,7 @@ package com.intellij.java.codeserver.highlighting;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationTargetUtil;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.java.codeserver.core.JavaPsiAnnotationUtil;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds.AnnotationValueErrorContext;
|
||||
import com.intellij.java.syntax.parser.JavaKeywords;
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.java.codeserver.core.JavaPsiAnnotationUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.util.JavaPsiAnnotationUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
+5
-1
@@ -10,6 +10,7 @@ import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
import com.intellij.java.codeserver.core.JavaPsiAnnotationUtil;
|
||||
import com.intellij.java.syntax.parser.JavaKeywords;
|
||||
import com.intellij.modcommand.ActionContext;
|
||||
import com.intellij.modcommand.ModCommandExecutor;
|
||||
@@ -19,7 +20,10 @@ import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.JavaElementKind;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
package com.siyeh.ig.psiutils;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.java.codeserver.core.JavaPsiAnnotationUtil;
|
||||
import com.intellij.java.syntax.parser.JavaKeywords;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.lang.jvm.JvmModifier;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
@@ -563,28 +562,19 @@ public final class MethodUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof PsiClassOwner classOwner) {
|
||||
final String packageName = classOwner.getPackageName();
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
|
||||
if (aPackage == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(aPackage, fqAnnotationNames);
|
||||
if(annotation != null) {
|
||||
// Check that annotation actually belongs to the same library/source root
|
||||
// which could be important in case of split-packages
|
||||
final VirtualFile annotationFile = PsiUtilCore.getVirtualFile(annotation);
|
||||
final VirtualFile currentFile = classOwner.getVirtualFile();
|
||||
if(annotationFile != null && currentFile != null) {
|
||||
final ProjectFileIndex projectFileIndex = ProjectFileIndex.getInstance(element.getProject());
|
||||
final VirtualFile annotationClassRoot = projectFileIndex.getClassRootForFile(annotationFile);
|
||||
final VirtualFile currentClassRoot = projectFileIndex.getClassRootForFile(currentFile);
|
||||
if (!Objects.equals(annotationClassRoot, currentClassRoot)) {
|
||||
return null;
|
||||
if (element instanceof PsiFile classOwner) {
|
||||
var processor = new JavaPsiAnnotationUtil.PackageAnnotationProcessor() {
|
||||
PsiAnnotation myAnnotation = null;
|
||||
|
||||
@Override
|
||||
public void process(@NotNull PsiAnnotation annotation, boolean superPackage) {
|
||||
if (fqAnnotationNames.contains(annotation.getQualifiedName())) {
|
||||
myAnnotation = annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotation;
|
||||
};
|
||||
JavaPsiAnnotationUtil.processPackageAnnotations(classOwner, processor, false);
|
||||
return processor.myAnnotation;
|
||||
}
|
||||
|
||||
element = element.getContext();
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.codeInspection.options.OptionController;
|
||||
import com.intellij.codeInspection.options.OptionControllerProvider;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.java.codeserver.core.JavaPsiAnnotationUtil;
|
||||
import com.intellij.java.codeserver.core.JavaPsiModuleUtil;
|
||||
import com.intellij.java.library.JavaLibraryModificationTracker;
|
||||
import com.intellij.java.library.JavaLibraryUtil;
|
||||
@@ -23,7 +24,6 @@ import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -360,39 +360,16 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
|
||||
@Override
|
||||
protected @NotNull ContextNullabilityInfo findNullityDefaultOnPackage(PsiAnnotation.TargetType @NotNull [] placeTargetTypes,
|
||||
PsiFile file) {
|
||||
boolean superPackage = false;
|
||||
ContextNullabilityInfo info = ContextNullabilityInfo.EMPTY;
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
VirtualFile vFile = file.getVirtualFile();
|
||||
if (vFile == null) return info;
|
||||
VirtualFile root = index.getSourceRootForFile(vFile);
|
||||
boolean compiled = false;
|
||||
if (root == null) {
|
||||
root = index.getClassRootForFile(vFile);
|
||||
if (root == null) return info;
|
||||
compiled = true;
|
||||
}
|
||||
// Single-file source root -- no package-info processing for now
|
||||
if (root.equals(vFile)) return info;
|
||||
PsiDirectory directory = file.getContainingDirectory();
|
||||
while (directory != null) {
|
||||
PsiFile packageFile = directory.findFile(compiled ? PsiPackage.PACKAGE_INFO_CLS_FILE : PsiPackage.PACKAGE_INFO_FILE);
|
||||
if (packageFile instanceof PsiJavaFile javaFile) {
|
||||
PsiPackageStatement stmt = javaFile.getPackageStatement();
|
||||
if (stmt != null) {
|
||||
PsiModifierList modifierList = stmt.getAnnotationList();
|
||||
if (modifierList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
info = info.orElse(checkNullityDefault(annotation, placeTargetTypes, superPackage));
|
||||
}
|
||||
}
|
||||
}
|
||||
var processor = new JavaPsiAnnotationUtil.PackageAnnotationProcessor() {
|
||||
@NotNull ContextNullabilityInfo info = ContextNullabilityInfo.EMPTY;
|
||||
|
||||
@Override
|
||||
public void process(@NotNull PsiAnnotation annotation, boolean superPackage) {
|
||||
info = info.orElse(checkNullityDefault(annotation, placeTargetTypes, superPackage));
|
||||
}
|
||||
if (root.equals(directory.getVirtualFile())) break;
|
||||
directory = directory.getParentDirectory();
|
||||
superPackage = true;
|
||||
}
|
||||
return info;
|
||||
};
|
||||
JavaPsiAnnotationUtil.processPackageAnnotations(file, processor, true);
|
||||
return processor.info;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,16 +3,23 @@ package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* @deprecated use com.intellij.java.codeserver.core.JavaPsiAnnotationUtil
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Deprecated
|
||||
public final class JavaPsiAnnotationUtil {
|
||||
/**
|
||||
* @param annotation annotation class
|
||||
* @return annotation retention policy; null if cannot be determined
|
||||
* @deprecated use com.intellij.java.codeserver.core.JavaPsiAnnotationUtil
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Deprecated
|
||||
public static @Nullable RetentionPolicy getRetentionPolicy(@NotNull PsiClass annotation) {
|
||||
PsiModifierList modifierList = annotation.getModifierList();
|
||||
if (modifierList != null) {
|
||||
|
||||
Reference in New Issue
Block a user