BlockingMethodInNonBlockingContextInspection: removing the inspection level cache (IDEA-206047)

This commit is contained in:
Nikita Katkov
2019-02-05 16:45:52 +03:00
committed by Nicolay Mitropolsky
parent b17646a802
commit eb073e18d2
3 changed files with 30 additions and 56 deletions

View File

@@ -1,15 +1,14 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.codeInsight.ExternalAnnotationsManager;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class AnnotationBasedBlockingMethodChecker implements BlockingMethodChecker {
@@ -29,18 +28,6 @@ public class AnnotationBasedBlockingMethodChecker implements BlockingMethodCheck
@Override
public boolean isMethodBlocking(@NotNull PsiMethod method) {
return hasAnnotation(method, myBlockingAnnotations);
}
static boolean hasAnnotation(PsiModifierListOwner owner, List<String> annotationsFQNames) {
boolean hasAnnotation = annotationsFQNames.stream()
.anyMatch(annotation -> owner.hasAnnotation(annotation));
if (hasAnnotation) return true;
PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner);
if (externalAnnotations == null) return false;
Set<String> externalAnnotationsFQNames =
Arrays.stream(externalAnnotations).map(PsiAnnotation::getQualifiedName).collect(Collectors.toSet());
return ContainerUtil.intersects(annotationsFQNames, externalAnnotationsFQNames);
return AnnotationUtil.findAnnotation(method, myBlockingAnnotations, false) != null;
}
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.UCallExpression;
@@ -10,8 +11,6 @@ import org.jetbrains.uast.UastUtils;
import java.util.List;
import static com.intellij.codeInspection.blockingCallsDetection.AnnotationBasedBlockingMethodChecker.hasAnnotation;
public class AnnotationBasedNonBlockingContextChecker implements NonBlockingContextChecker {
private final List<String> myNonBlockingAnnotations;
@@ -37,6 +36,6 @@ public class AnnotationBasedNonBlockingContextChecker implements NonBlockingCont
if (callingMethod == null) return false;
PsiMethod psiCallingMethod = callingMethod.getJavaPsi();
return hasAnnotation(psiCallingMethod, myNonBlockingAnnotations);
return AnnotationUtil.findAnnotation(psiCallingMethod, myNonBlockingAnnotations, false) != null;
}
}

View File

@@ -17,9 +17,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import one.util.streamex.StreamEx;
@@ -79,7 +76,6 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
myNonBlockingContextCheckers.stream().anyMatch(extension -> extension.isApplicable(file));
}
private class OptionsPanel extends JPanel {
private OptionsPanel() {
super(new BorderLayout());
@@ -143,50 +139,42 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
UCallExpression callExpression = AnalysisUastUtil.getUCallExpression(element);
if (callExpression == null) return;
if (!isContextNonBlockingFor(element)) return;
if (!isContextNonBlockingFor(element, myNonBlockingContextCheckers)) return;
ProgressIndicatorProvider.checkCanceled();
PsiMethod referencedMethod = callExpression.resolve();
if (referencedMethod == null) return;
if (!CachedValuesManager.getCachedValue(referencedMethod, getIsBlockingProvider(referencedMethod, myBlockingMethodCheckers))) {
return;
}
if (!isMethodOrSupersBlocking(referencedMethod, myBlockingMethodCheckers)) return;
PsiElement elementToHighLight = AnalysisUastUtil.getMethodIdentifierSourcePsi(callExpression);
if (elementToHighLight == null) return;
myHolder.registerProblem(elementToHighLight,
JvmAnalysisBundle.message("jvm.inspections.blocking.method.problem.descriptor"));
}
}
private static CachedValueProvider<Boolean> getIsBlockingProvider(PsiMethod referencedMethod,
List<? extends BlockingMethodChecker> blockingMethodCheckers) {
return () -> {
boolean isBlocking =
StreamEx.of(referencedMethod).append(referencedMethod.findDeepestSuperMethods())
.anyMatch(method -> isMethodBlocking(method, blockingMethodCheckers));
return CachedValueProvider.Result.create(isBlocking, PsiModificationTracker.MODIFICATION_COUNT);
};
}
private static boolean isMethodOrSupersBlocking(PsiMethod referencedMethod,
List<? extends BlockingMethodChecker> blockingMethodCheckers) {
return StreamEx.of(referencedMethod).append(referencedMethod.findDeepestSuperMethods())
.anyMatch(method -> isMethodBlocking(method, blockingMethodCheckers));
}
private boolean isContextNonBlockingFor(PsiElement element) {
return myNonBlockingContextCheckers.stream().anyMatch(extension -> {
ProgressIndicatorProvider.checkCanceled();
return extension.isContextNonBlockingFor(element);
});
}
private static boolean isMethodBlocking(PsiMethod method,
List<? extends BlockingMethodChecker> blockingMethodCheckers) {
return blockingMethodCheckers.stream().anyMatch(extension -> {
ProgressIndicatorProvider.checkCanceled();
return extension.isMethodBlocking(method);
});
}
private static boolean isMethodBlocking(PsiMethod method,
List<? extends BlockingMethodChecker> blockingMethodCheckers) {
return blockingMethodCheckers.stream().anyMatch(extension -> {
ProgressIndicatorProvider.checkCanceled();
return extension.isMethodBlocking(method);
});
}
private static boolean isContextNonBlockingFor(PsiElement element,
List<? extends NonBlockingContextChecker> nonBlockingContextCheckers) {
return nonBlockingContextCheckers.stream().anyMatch(extension -> {
ProgressIndicatorProvider.checkCanceled();
return extension.isContextNonBlockingFor(element);
});
}
}