mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[java-analysis] IDEA-375444 Speedup retrieving package-level nullity annotations
(cherry picked from commit 7be077c9a1a6b7fade1833689567b5947e2c77de) IJ-CR-168171 GitOrigin-RevId: 01c5b38d7e028585b94d1596c0de8c7c323a2fa3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b8b75d3d91
commit
e02fbb2cfc
@@ -30,7 +30,10 @@ import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValueProvider.Result;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jdom.Element;
|
||||
@@ -290,30 +293,53 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
|
||||
return result;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (root.equals(directory.getVirtualFile())) break;
|
||||
directory = directory.getParentDirectory();
|
||||
superPackage = true;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ContextNullabilityInfo getNullityDefault(@NotNull PsiModifierListOwner container,
|
||||
PsiAnnotation.TargetType @NotNull [] placeTargetTypes,
|
||||
boolean superPackage) {
|
||||
PsiAnnotation.TargetType @NotNull [] placeTargetTypes) {
|
||||
LOG.assertTrue(!(container instanceof PsiPackage)); // Packages are handled separately in findNullityDefaultOnPackage
|
||||
ContextNullabilityInfo res = ContextNullabilityInfo.EMPTY;
|
||||
PsiModifierList modifierList = container.getModifierList();
|
||||
if (modifierList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
ContextNullabilityInfo info = checkNullityDefault(annotation, placeTargetTypes, superPackage);
|
||||
if (container instanceof PsiPackage) {
|
||||
VirtualFile annotationFile = PsiUtilCore.getVirtualFile(annotation);
|
||||
info = info.filtering(context -> {
|
||||
VirtualFile ownerFile = PsiUtilCore.getVirtualFile(context);
|
||||
if (annotationFile != null && ownerFile != null && !annotationFile.equals(ownerFile)) {
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(container.getProject()).getFileIndex();
|
||||
VirtualFile annotationRoot = index.getClassRootForFile(annotationFile);
|
||||
VirtualFile ownerRoot = index.getClassRootForFile(ownerFile);
|
||||
if (ownerRoot != null && !ownerRoot.equals(annotationRoot)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
ContextNullabilityInfo info = checkNullityDefault(annotation, placeTargetTypes, false);
|
||||
res = res.orElse(info);
|
||||
}
|
||||
}
|
||||
@@ -407,7 +433,7 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
|
||||
@NotNull PsiElement element) {
|
||||
PsiJavaModule module = JavaPsiModuleUtil.findDescriptorByElement(element);
|
||||
if (module != null) {
|
||||
return getNullityDefault(module, targetTypes, false);
|
||||
return getNullityDefault(module, targetTypes);
|
||||
}
|
||||
return ContextNullabilityInfo.EMPTY;
|
||||
}
|
||||
|
||||
@@ -273,8 +273,7 @@ public abstract class NullableNotNullManager {
|
||||
}
|
||||
|
||||
protected abstract @NotNull ContextNullabilityInfo getNullityDefault(@NotNull PsiModifierListOwner container,
|
||||
PsiAnnotation.TargetType @NotNull [] placeTargetTypes,
|
||||
boolean superPackage);
|
||||
PsiAnnotation.TargetType @NotNull [] placeTargetTypes);
|
||||
|
||||
@ApiStatus.Internal
|
||||
@NotNull
|
||||
@@ -315,7 +314,7 @@ public abstract class NullableNotNullManager {
|
||||
if (element instanceof PsiModifierListOwner) {
|
||||
PsiModifierListOwner listOwner = (PsiModifierListOwner)element;
|
||||
NullabilityAnnotationInfo result = CachedValuesManager.getCachedValue(listOwner, () -> {
|
||||
return CachedValueProvider.Result.create(getNullityDefault(listOwner, TYPE_USE_TARGET, false),
|
||||
return CachedValueProvider.Result.create(getNullityDefault(listOwner, TYPE_USE_TARGET),
|
||||
PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}).forContext(context);
|
||||
if (result != null) {
|
||||
@@ -326,9 +325,7 @@ public abstract class NullableNotNullManager {
|
||||
if (element instanceof PsiClassOwner) {
|
||||
PsiClassOwner classOwner = (PsiClassOwner)element;
|
||||
return CachedValuesManager.getCachedValue(classOwner, () -> {
|
||||
String packageName = classOwner.getPackageName();
|
||||
PsiPackage psiPackage = JavaPsiFacade.getInstance(classOwner.getProject()).findPackage(packageName);
|
||||
ContextNullabilityInfo fromPackage = findNullityDefaultOnPackage(TYPE_USE_TARGET, psiPackage);
|
||||
ContextNullabilityInfo fromPackage = findNullityDefaultOnPackage(TYPE_USE_TARGET, classOwner.getContainingFile());
|
||||
return CachedValueProvider.Result.create(fromPackage.orElse(findNullityDefaultOnModule(TYPE_USE_TARGET, classOwner)),
|
||||
PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}).forContext(context);
|
||||
@@ -356,16 +353,14 @@ public abstract class NullableNotNullManager {
|
||||
PsiElement element = place.getContext();
|
||||
while (element != null) {
|
||||
if (element instanceof PsiModifierListOwner) {
|
||||
NullabilityAnnotationInfo result = getNullityDefault((PsiModifierListOwner)element, placeTargetTypes, false).forContext(place);
|
||||
NullabilityAnnotationInfo result = getNullityDefault((PsiModifierListOwner)element, placeTargetTypes).forContext(place);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof PsiClassOwner) {
|
||||
String packageName = ((PsiClassOwner)element).getPackageName();
|
||||
PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
|
||||
NullabilityAnnotationInfo fromPackage = findNullityDefaultOnPackage(placeTargetTypes, psiPackage).forContext(place);
|
||||
NullabilityAnnotationInfo fromPackage = findNullityDefaultOnPackage(placeTargetTypes, element.getContainingFile()).forContext(place);
|
||||
if (fromPackage != null) {
|
||||
return fromPackage;
|
||||
}
|
||||
@@ -382,16 +377,9 @@ public abstract class NullableNotNullManager {
|
||||
return ContextNullabilityInfo.EMPTY;
|
||||
}
|
||||
|
||||
private @NotNull ContextNullabilityInfo findNullityDefaultOnPackage(PsiAnnotation.TargetType @NotNull [] placeTargetTypes,
|
||||
@Nullable PsiPackage psiPackage) {
|
||||
boolean superPackage = false;
|
||||
ContextNullabilityInfo info = ContextNullabilityInfo.EMPTY;
|
||||
while (psiPackage != null) {
|
||||
info = info.orElse(getNullityDefault(psiPackage, placeTargetTypes, superPackage));
|
||||
superPackage = true;
|
||||
psiPackage = psiPackage.getParentPackage();
|
||||
}
|
||||
return info;
|
||||
protected @NotNull ContextNullabilityInfo findNullityDefaultOnPackage(PsiAnnotation.TargetType @NotNull [] placeTargetTypes,
|
||||
PsiFile file) {
|
||||
return ContextNullabilityInfo.EMPTY;
|
||||
}
|
||||
|
||||
public abstract @NotNull List<String> getNullables();
|
||||
|
||||
@@ -34,6 +34,12 @@ class ClsPackageStatementImpl extends ClsElementImpl implements PsiPackageStatem
|
||||
|
||||
@Override
|
||||
public PsiModifierList getAnnotationList() {
|
||||
if (myFile != null && myFile.getName().equals("package-info.class")) {
|
||||
PsiClass[] classes = myFile.getClasses();
|
||||
if (classes.length == 1) {
|
||||
return classes[0].getModifierList();
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Method not implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package p;
|
||||
package refactoring.introduceVariable;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package p;
|
||||
package refactoring.introduceVariable;
|
||||
class Test {
|
||||
@org.checkerframework.checker.nullness.qual.Nullable
|
||||
String s;
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@@ -26,7 +27,11 @@ public abstract class DataFlowInspectionTestCase extends LightJavaCodeInsightFix
|
||||
ConstantValueInspection cvInspection = new ConstantValueInspection();
|
||||
inspectionMutator.accept(inspection, cvInspection);
|
||||
myFixture.enableInspections(inspection, cvInspection);
|
||||
myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
|
||||
myFixture.testHighlighting(true, false, true, getTestFileName());
|
||||
}
|
||||
|
||||
protected @NotNull String getTestFileName() {
|
||||
return getTestName(false) + ".java";
|
||||
}
|
||||
|
||||
static void addCheckerAnnotations(JavaCodeInsightTestFixture fixture) {
|
||||
|
||||
@@ -40,9 +40,9 @@ public class LightIntroduceVariableTest extends LightJavaCodeInsightFixtureTestC
|
||||
myFixture.addClass("package org.checkerframework.framework.qual; public class DefaultQualifier {}");
|
||||
myFixture.addClass("package org.checkerframework.checker.nullness.qual; @java.lang.annotation.Target({ElementType.TYPE_USE}) public class NonNull {}");
|
||||
myFixture.addClass("package org.checkerframework.checker.nullness.qual; @java.lang.annotation.Target({ElementType.TYPE_USE}) public @interface Nullable {}");
|
||||
myFixture.addFileToProject("p/package-info.java", """
|
||||
myFixture.addFileToProject("refactoring/introduceVariable/package-info.java", """
|
||||
@org.checkerframework.framework.qual.DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.ALL)
|
||||
package p;
|
||||
package refactoring.introduceVariable;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
""");
|
||||
MockIntroduceVariableHandler handler = new MockIntroduceVariableHandler("m", false, false, false,
|
||||
|
||||
@@ -48,4 +48,9 @@ public class LombokDataFlowInspectionTest extends DataFlowInspectionTestCase {
|
||||
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull String getTestFileName() {
|
||||
return "test/" + super.getTestFileName();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user