1 // Copyright 2000-2020 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.
2 package com.jetbrains.python.testing;
4 import com.intellij.execution.Location;
5 import com.intellij.execution.PsiLocation;
6 import com.intellij.openapi.progress.ProgressManager;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.util.io.FileUtilRt;
9 import com.intellij.openapi.vfs.LocalFileSystem;
10 import com.intellij.openapi.vfs.VirtualFile;
11 import com.intellij.psi.PsiFile;
12 import com.intellij.psi.PsiManager;
13 import com.intellij.util.ThreeState;
14 import com.jetbrains.python.psi.PyClass;
15 import com.jetbrains.python.psi.PyFunction;
16 import com.jetbrains.python.psi.stubs.PyClassNameIndex;
17 import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
18 import com.jetbrains.python.psi.types.TypeEvalContext;
19 import org.jetbrains.annotations.ApiStatus;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
23 import java.util.ArrayList;
24 import java.util.List;
26 public final class PythonUnitTestUtil {
27 private PythonUnitTestUtil() {}
29 public static List<Location> findLocations(@NotNull final Project project,
30 @NotNull String fileName,
31 @Nullable String className,
32 @Nullable String methodName) {
33 if (fileName.contains("%")) {
34 fileName = fileName.substring(0, fileName.lastIndexOf("%"));
36 final List<Location> locations = new ArrayList<>();
37 if (methodName == null && className == null) {
38 final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(fileName);
39 if (virtualFile == null) return locations;
40 final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
41 if (psiFile != null) {
42 locations.add(new PsiLocation<>(project, psiFile));
46 if (className != null) {
47 for (PyClass cls : PyClassNameIndex.find(className, project, false)) {
48 ProgressManager.checkCanceled();
50 final PsiFile containingFile = cls.getContainingFile();
51 final VirtualFile virtualFile = containingFile.getVirtualFile();
52 final String clsFileName = virtualFile == null ? containingFile.getName() : virtualFile.getPath();
53 final String clsFileNameWithoutExt = FileUtilRt.getNameWithoutExtension(clsFileName);
54 if (!clsFileNameWithoutExt.endsWith(fileName) && !fileName.equals(clsFileName)) {
57 if (methodName == null) {
58 locations.add(new PsiLocation<>(project, cls));
61 final PyFunction method = cls.findMethodByName(methodName, true, null);
66 locations.add(new PyPsiLocationWithFixedClass(project, method, cls));
70 else if (methodName != null) {
71 for (PyFunction function : PyFunctionNameIndex.find(methodName, project)) {
72 ProgressManager.checkCanceled();
73 if (function.getContainingClass() == null) {
74 final PsiFile containingFile = function.getContainingFile();
75 final VirtualFile virtualFile = containingFile.getVirtualFile();
76 final String clsFileName = virtualFile == null ? containingFile.getName() : virtualFile.getPath();
77 final String clsFileNameWithoutExt = FileUtilRt.getNameWithoutExtension(clsFileName);
78 if (!clsFileNameWithoutExt.endsWith(fileName)) {
81 locations.add(new PsiLocation<>(project, function));
89 * @deprecated use {@link PythonUnitTestDetectorsKt#isUnitTestCaseClass(PyClass, TypeEvalContext)}
92 @ApiStatus.ScheduledForRemoval(inVersion = "2021.1")
93 public static boolean isUnitTestCaseClass(@NotNull PyClass pyClass) {
94 return PythonUnitTestDetectorsKt.isUnitTestCaseClass(pyClass, TypeEvalContext.codeInsightFallback(pyClass.getProject()));
98 * @deprecated use {@link PythonUnitTestDetectorsBasedOnSettings#isTestClass(PyClass, ThreeState, TypeEvalContext)}
101 @ApiStatus.ScheduledForRemoval(inVersion = "2021.1")
102 public static boolean isTestClass(@NotNull final PyClass cls,
103 @NotNull final ThreeState testCaseClassRequired,
104 @Nullable TypeEvalContext context) {
105 return PythonUnitTestDetectorsBasedOnSettings.isTestClass(cls, testCaseClassRequired, context);