blocking calls detection inspection : minor changes

This commit is contained in:
Nikita Katkov
2018-08-23 16:38:27 +03:00
committed by Nicolay Mitropolsky
parent afc9d936e9
commit 76e2d4b06b
11 changed files with 140 additions and 97 deletions

View File

@@ -1,9 +1,9 @@
<idea-plugin>
<extensionPoints>
<extensionPoint qualifiedName="com.intellij.blockingMethodChecker"
<extensionPoint qualifiedName="com.intellij.codeInsight.blockingMethodChecker"
interface="com.intellij.codeInspection.blockingCallsDetection.BlockingMethodChecker"/>
<extensionPoint qualifiedName="com.intellij.nonblockingMethodChecker"
interface="com.intellij.codeInspection.blockingCallsDetection.NonblockingContextChecker"/>
<extensionPoint qualifiedName="com.intellij.codeInsight.nonBlockingContextChecker"
interface="com.intellij.codeInspection.blockingCallsDetection.NonBlockingContextChecker"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<localInspection language="UAST" enabledByDefault="true" level="WARNING" shortName="UnstableApiUsage"
@@ -15,6 +15,8 @@
enabledByDefault="true" level="WARNING"
key="method.name.contains.blocking.word.display.name" bundle="com.intellij.jvm.analysis.JvmAnalysisBundle"
implementationClass="com.intellij.codeInspection.blockingCallsDetection.BlockingMethodInNonBlockingContextInspection"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.codeInsight">
<blockingMethodChecker implementation="com.intellij.codeInspection.blockingCallsDetection.ThrowsTypeBlockingMethodChecker"/>
</extensions>
</idea-plugin>

View File

@@ -6,13 +6,13 @@ jvm.inspections.unstable.api.usage.ignore.inside.imports=Ignore inside imports
jvm.inspections.unstable.api.usage.description=''{0}'' is marked unstable
method.name.contains.blocking.word.problem.descriptor=Inappropriate blocking method call
method.name.contains.blocking.word.display.name=Inappropriate thread-blocking method call found
inspection.blocking.method.annotation.blocking=Blocking Annotations
inspection.blocking.method.annotation.nonblocking=Non-blocking Annotations
inspection.blocking.method.annotation.configure.add.blocking.title=Add Blocking Annotation
inspection.blocking.method.annotation.configure.add.nonblocking.title=Add Non-Blocking Annotation
inspection.blocking.method.annotation.configure.empty.text=No annotations added.
inspection.blocking.method.annotation.configure.add.text=Add annotation
method.name.contains.blocking.word.display.name=Inappropriate thread-blocking method call
jvm.inspections.blocking.method.annotation.blocking=Blocking Annotations
jvm.inspections.blocking.method.annotation.non-blocking=Non-Blocking Annotations
jvm.inspections.blocking.method.annotation.configure.add.blocking.title=Add Blocking Annotation
jvm.inspections.blocking.method.annotation.configure.add.non-blocking.title=Add Non-Blocking Annotation
jvm.inspections.blocking.method.annotation.configure.empty.text=No annotations added.
jvm.inspections.blocking.method.annotation.configure.add.text=Add annotation
jvm.inspections.string.touppercase.tolowercase.without.locale.display.name=Call to 'String.toUpperCase()' or 'toLowerCase()' without a Locale

View File

@@ -2,9 +2,7 @@
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -12,17 +10,20 @@ import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public class DefaultBlockingMethodChecker implements BlockingMethodChecker {
public class AnnotationBasedBlockingMethodChecker implements BlockingMethodChecker {
private final List<String> myBlockingAnnotations;
public DefaultBlockingMethodChecker(List<String> blockingAnnotations) {
public AnnotationBasedBlockingMethodChecker(List<String> blockingAnnotations) {
myBlockingAnnotations = blockingAnnotations;
}
@Override
public boolean isActive(Project project) {
return !myBlockingAnnotations.isEmpty();
public boolean isActive(@NotNull PsiFile file) {
if (myBlockingAnnotations.isEmpty()) return false;
PsiClass annotationClass = JavaPsiFacade.getInstance(file.getProject())
.findClass(BlockingMethodInNonBlockingContextInspection.DEFAULT_BLOCKING_ANNOTATION, file.getResolveScope());
return annotationClass != null;
}
@Override

View File

@@ -2,9 +2,7 @@
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.ProjectScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.UCallExpression;
import org.jetbrains.uast.UMethod;
@@ -16,19 +14,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public class DefaultNonblockingContextChecker implements NonblockingContextChecker {
public class AnnotationBasedNonBlockingContextChecker implements NonBlockingContextChecker {
private final List<String> myNonblockingAnnotations;
private final List<String> myNonBlockingAnnotations;
public DefaultNonblockingContextChecker(List<String> nonblockingAnnotations) {
myNonblockingAnnotations = nonblockingAnnotations;
public AnnotationBasedNonBlockingContextChecker(List<String> nonBlockingAnnotations) {
myNonBlockingAnnotations = nonBlockingAnnotations;
}
@Override
public boolean isActive(Project project) {
if (myNonblockingAnnotations.isEmpty()) return false;
PsiClass annotationClass = JavaPsiFacade.getInstance(project)
.findClass(BlockingMethodInNonBlockingContextInspection.DEFAULT_NONBLOCKING_ANNOTATION, ProjectScope.getProjectScope(project));
public boolean isActive(@NotNull PsiFile file) {
if (myNonBlockingAnnotations.isEmpty()) return false;
PsiClass annotationClass = JavaPsiFacade.getInstance(file.getProject())
.findClass(BlockingMethodInNonBlockingContextInspection.DEFAULT_NONBLOCKING_ANNOTATION, file.getResolveScope());
return annotationClass != null;
}
@@ -48,7 +46,7 @@ public class DefaultNonblockingContextChecker implements NonblockingContextCheck
HashSet<String> setOfAnnotations = Arrays.stream(AnnotationUtil.getAllAnnotations(method, true, null))
.map(PsiAnnotation::getQualifiedName).collect(Collectors.toCollection(HashSet::new));
return myNonblockingAnnotations.stream()
return myNonBlockingAnnotations.stream()
.anyMatch(annotation -> setOfAnnotations.contains(annotation));
}
}

View File

@@ -6,7 +6,6 @@ import com.intellij.icons.AllIcons;
import com.intellij.ide.util.ClassFilter;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
@@ -14,7 +13,6 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBUI;
@@ -25,7 +23,6 @@ import javax.swing.*;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -41,15 +38,15 @@ class BlockingAnnotationsPanel {
private final String myCustomAddLinkText;
BlockingAnnotationsPanel(Project project,
String name,
String defaultAnnotation,
List<String> annotations,
String[] defaultAnnotations,
String customEmptyText,
String customAddLinkText) {
String name,
String defaultAnnotation,
List<String> annotations,
List<String> defaultAnnotations,
String customEmptyText,
String customAddLinkText) {
myProject = project;
myDefaultAnnotation = defaultAnnotation;
myDefaultAnnotations = new HashSet<>(Arrays.asList(defaultAnnotations));
myDefaultAnnotations = new HashSet<>(defaultAnnotations);
myCustomEmptyText = customEmptyText;
myCustomAddLinkText = customAddLinkText;
myTableModel = new ListWrappingTableModel(annotations, name) {
@@ -93,16 +90,14 @@ class BlockingAnnotationsPanel {
.appendSecondaryText(myCustomAddLinkText, SimpleTextAttributes.LINK_ATTRIBUTES, e -> chooseAnnotation(name));
ShortcutSet shortcutSet = CommonActionsPanel.getCommonShortcut(CommonActionsPanel.Buttons.ADD);
Shortcut shortcut = ArrayUtil.getFirstElement(shortcutSet.getShortcuts());
if (shortcut != null) {
emptyText.appendSecondaryText(" (" + KeymapUtil.getShortcutText(shortcut) + ")", StatusText.DEFAULT_ATTRIBUTES, null);
}
String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(shortcutSet);
emptyText.appendSecondaryText(" (" + shortcutText + ")", StatusText.DEFAULT_ATTRIBUTES, null);
}
return emptyText;
}
};
final ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myTable).disableUpDownActions()
final ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myTable)
.setAddAction(b -> chooseAnnotation(name))
.setRemoveAction(new AnActionButtonRunnable() {
@Override
@@ -119,7 +114,9 @@ class BlockingAnnotationsPanel {
final JPanel panel = toolbarDecorator.createPanel();
myComponent = new JPanel(new BorderLayout());
myComponent.setBorder(IdeBorderFactory.createEmptyBorder(JBUI.insetsTop(10)));
myComponent.add(new JLabel(name), BorderLayout.NORTH);
final JLabel label = new JLabel(name + ":");
label.setBorder(IdeBorderFactory.createEmptyBorder(JBUI.insetsBottom(10)));
myComponent.add(label, BorderLayout.NORTH);
myComponent.add(panel, BorderLayout.CENTER);
myComponent.setPreferredSize(new JBDimension(myComponent.getPreferredSize().width, 200));

View File

@@ -2,14 +2,14 @@
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
public interface BlockingMethodChecker {
ExtensionPointName<BlockingMethodChecker> EP_NAME = ExtensionPointName.create("com.intellij.blockingMethodChecker");
ExtensionPointName<BlockingMethodChecker> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.blockingMethodChecker");
boolean isActive(Project project);
boolean isActive(@NotNull PsiFile file);
boolean isMethodBlocking(@NotNull PsiMethod method);
}

View File

@@ -4,7 +4,6 @@ package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.analysis.JvmAnalysisBundle;
import com.intellij.codeInspection.AbstractBaseUastLocalInspectionTool;
import com.intellij.codeInspection.AnalysisUastUtil;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -15,6 +14,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
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;
@@ -29,6 +29,7 @@ import org.jetbrains.uast.UCallExpression;
import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.List;
public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUastLocalInspectionTool {
@@ -37,7 +38,7 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
public static final String DEFAULT_NONBLOCKING_ANNOTATION = "org.jetbrains.annotations.NonBlocking";
public List<String> myBlockingAnnotations = new SmartList<>();
public List<String> myNonblockingAnnotations = new SmartList<>();
public List<String> myNonBlockingAnnotations = new SmartList<>();
@Nullable
@Override
@@ -58,27 +59,26 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
List<BlockingMethodChecker> blockingMethodCheckers =
ContainerUtil.append(BlockingMethodChecker.EP_NAME.getExtensionList(),
new DefaultBlockingMethodChecker(myBlockingAnnotations));
new AnnotationBasedBlockingMethodChecker(myBlockingAnnotations));
List<NonblockingContextChecker> nonblockingContextCheckers =
ContainerUtil.append(NonblockingContextChecker.EP_NAME.getExtensionList(),
new DefaultNonblockingContextChecker(myNonblockingAnnotations));
List<NonBlockingContextChecker> nonBlockingContextCheckers =
ContainerUtil.append(NonBlockingContextChecker.EP_NAME.getExtensionList(),
new AnnotationBasedNonBlockingContextChecker(myNonBlockingAnnotations));
if (!isInspectionActive(holder.getProject(), blockingMethodCheckers, nonblockingContextCheckers)) {
if (!isInspectionActive(holder.getFile(), blockingMethodCheckers, nonBlockingContextCheckers)) {
return PsiElementVisitor.EMPTY_VISITOR;
}
return new BlockingMethodInNonBlockingContextVisitor(holder, blockingMethodCheckers, nonblockingContextCheckers);
return new BlockingMethodInNonBlockingContextVisitor(holder, blockingMethodCheckers, nonBlockingContextCheckers);
}
private static boolean isInspectionActive(Project project,
private static boolean isInspectionActive(PsiFile file,
List<BlockingMethodChecker> myBlockingMethodCheckers,
List<NonblockingContextChecker> myNonblockingContextCheckers) {
return myBlockingMethodCheckers.stream().anyMatch(extension -> extension.isActive(project)) &&
myNonblockingContextCheckers.stream().anyMatch(extension -> extension.isActive(project));
List<NonBlockingContextChecker> myNonBlockingContextCheckers) {
return myBlockingMethodCheckers.stream().anyMatch(extension -> extension.isActive(file)) &&
myNonBlockingContextCheckers.stream().anyMatch(extension -> extension.isActive(file));
}
private class OptionsPanel extends JPanel {
private OptionsPanel() {
super(new BorderLayout());
@@ -89,27 +89,27 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
new BlockingAnnotationsPanel(
project,
JvmAnalysisBundle
.message("inspection.blocking.method.annotation.blocking"),
.message("jvm.inspections.blocking.method.annotation.blocking"),
DEFAULT_BLOCKING_ANNOTATION,
myBlockingAnnotations,
new String[]{DEFAULT_BLOCKING_ANNOTATION},
JvmAnalysisBundle.message("inspection.blocking.method.annotation.configure.empty.text"),
JvmAnalysisBundle.message("inspection.blocking.method.annotation.configure.add.blocking.title"));
Collections.singletonList(DEFAULT_BLOCKING_ANNOTATION),
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.empty.text"),
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.blocking.title"));
BlockingAnnotationsPanel nonblockingAnnotationsPanel =
BlockingAnnotationsPanel nonBlockingAnnotationsPanel =
new BlockingAnnotationsPanel(
project,
JvmAnalysisBundle.message(
"inspection.blocking.method.annotation.nonblocking"),
"jvm.inspections.blocking.method.annotation.non-blocking"),
DEFAULT_NONBLOCKING_ANNOTATION,
myNonblockingAnnotations,
new String[]{DEFAULT_NONBLOCKING_ANNOTATION},
JvmAnalysisBundle.message("inspection.blocking.method.annotation.configure.add.nonblocking.title"),
JvmAnalysisBundle.message("inspection.blocking.method.annotation.configure.add.nonblocking.title"));
myNonBlockingAnnotations,
Collections.singletonList(DEFAULT_NONBLOCKING_ANNOTATION),
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.empty.text"),
JvmAnalysisBundle.message("jvm.inspections.blocking.method.annotation.configure.add.non-blocking.title"));
mainPanel.setFirstComponent(blockingAnnotationsPanel.getComponent());
mainPanel.setSecondComponent(nonblockingAnnotationsPanel.getComponent());
mainPanel.setSecondComponent(nonBlockingAnnotationsPanel.getComponent());
add(mainPanel, BorderLayout.CENTER);
}
@@ -129,14 +129,14 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
private static class BlockingMethodInNonBlockingContextVisitor extends PsiElementVisitor {
private final ProblemsHolder myHolder;
private final List<BlockingMethodChecker> myBlockingMethodCheckers;
private final List<NonblockingContextChecker> myNonblockingContextCheckers;
private final List<NonBlockingContextChecker> myNonBlockingContextCheckers;
public BlockingMethodInNonBlockingContextVisitor(@NotNull ProblemsHolder holder,
List<BlockingMethodChecker> blockingMethodCheckers,
List<NonblockingContextChecker> nonblockingContextCheckers) {
List<NonBlockingContextChecker> nonBlockingContextCheckers) {
myHolder = holder;
this.myBlockingMethodCheckers = blockingMethodCheckers;
this.myNonblockingContextCheckers = nonblockingContextCheckers;
this.myNonBlockingContextCheckers = nonBlockingContextCheckers;
}
@Override
@@ -150,27 +150,32 @@ public class BlockingMethodInNonBlockingContextInspection extends AbstractBaseUa
PsiMethod referencedMethod = callExpression.resolve();
if (referencedMethod == null) return;
boolean isReferencedMethodBlocking = CachedValuesManager.getCachedValue(referencedMethod, () -> {
boolean isBlocking =
StreamEx.of(referencedMethod).append(referencedMethod.findDeepestSuperMethods()).anyMatch(method -> isMethodBlocking(method));
return CachedValueProvider.Result.create(isBlocking, PsiModificationTracker.MODIFICATION_COUNT);
});
if (!isReferencedMethodBlocking) return;
if (!CachedValuesManager.getCachedValue(referencedMethod, getIsBlockingProvider(referencedMethod, myBlockingMethodCheckers))) {
return;
}
PsiElement elementToHighLight = AnalysisUastUtil.getMethodIdentifierSourcePsi(callExpression);
if (elementToHighLight == null) return;
myHolder.registerProblem(elementToHighLight,
JvmAnalysisBundle.message("method.name.contains.blocking.word.problem.descriptor"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
JvmAnalysisBundle.message("method.name.contains.blocking.word.problem.descriptor"));
}
private static CachedValueProvider<Boolean> getIsBlockingProvider(PsiMethod referencedMethod,
List<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 boolean isContextNonBlockingFor(PsiElement element) {
return myNonblockingContextCheckers.stream().anyMatch(extension -> extension.isContextNonBlockingFor(element));
return myNonBlockingContextCheckers.stream().anyMatch(extension -> extension.isContextNonBlockingFor(element));
}
private boolean isMethodBlocking(PsiMethod method) {
return myBlockingMethodCheckers.stream().anyMatch(extension -> extension.isMethodBlocking(method));
private static boolean isMethodBlocking(PsiMethod method, List<BlockingMethodChecker> blockingMethodCheckers) {
return blockingMethodCheckers.stream().anyMatch(extension -> extension.isMethodBlocking(method));
}
}
}

View File

@@ -2,14 +2,14 @@
package com.intellij.codeInspection.blockingCallsDetection;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
public interface NonblockingContextChecker {
ExtensionPointName<NonblockingContextChecker> EP_NAME = ExtensionPointName.create("com.intellij.nonblockingMethodChecker");
public interface NonBlockingContextChecker {
ExtensionPointName<NonBlockingContextChecker> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.nonBlockingContextChecker");
boolean isActive(Project project);
boolean isActive(@NotNull PsiFile file);
boolean isContextNonBlockingFor(@NotNull PsiElement element);
}

View File

@@ -1,21 +1,22 @@
// 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.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ThrowsTypeBlockingMethodChecker implements BlockingMethodChecker {
private static final HashSet<String> BLOCKING_EXCEPTION_TYPES = new HashSet<>(Arrays.asList(
private static final Set<String> BLOCKING_EXCEPTION_TYPES = ContainerUtil.immutableSet(
"java.lang.InterruptedException",
"java.io.IOException"));
"java.io.IOException");
@Override
public boolean isActive(Project project) {
return !BLOCKING_EXCEPTION_TYPES.isEmpty();
public boolean isActive(@NotNull PsiFile file) {
return true;
}
@Override

View File

@@ -58,7 +58,7 @@ public class BlockingMethodInNonBlockingContextInspectionTest extends UsefulTest
BlockingMethodInNonBlockingContextInspection myInspection = new BlockingMethodInNonBlockingContextInspection();
myInspection.myBlockingAnnotations =
Collections.singletonList(BlockingMethodInNonBlockingContextInspection.DEFAULT_BLOCKING_ANNOTATION);
myInspection.myNonblockingAnnotations =
myInspection.myNonBlockingAnnotations =
Collections.singletonList(BlockingMethodInNonBlockingContextInspection.DEFAULT_NONBLOCKING_ANNOTATION);
myFixture.enableInspections(myInspection);
}

View File

@@ -0,0 +1,39 @@
// 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;
import com.intellij.codeInspection.blockingCallsDetection.BlockingMethodInNonBlockingContextInspection;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import java.util.Collections;
public class BlockingCallDetectionKotlinTest extends JavaCodeInsightFixtureTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
BlockingMethodInNonBlockingContextInspection myInspection = new BlockingMethodInNonBlockingContextInspection();
myInspection.myBlockingAnnotations =
Collections.singletonList(BlockingMethodInNonBlockingContextInspection.DEFAULT_BLOCKING_ANNOTATION);
myInspection.myNonBlockingAnnotations =
Collections.singletonList(BlockingMethodInNonBlockingContextInspection.DEFAULT_NONBLOCKING_ANNOTATION);
myFixture.enableInspections(myInspection);
}
public void testKotlinCodeInspecting() {
myFixture.addClass("package org.jetbrains.annotations;\n" +
"public @interface Blocking {}");
myFixture.addClass("package org.jetbrains.annotations;\n" +
"public @interface NonBlocking {}");
myFixture.addFileToProject("/TestKotlinCodeInspection.kt",
"import org.jetbrains.annotations.Blocking\n" +
"import org.jetbrains.annotations.NonBlocking\n" +
"@NonBlocking\n" +
"fun nonBlockingFunction() {\n" +
" <warning descr=\"Inappropriate blocking method call\">blockingFunction</warning>();\n" +
"}\n" +
"@Blocking\n" +
"fun blockingFunction() {}");
myFixture.testHighlighting(true, false, true, "TestKotlinCodeInspection.kt");
}
}