diff --git a/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java b/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java index f241de2e3afa..ea67cab437fa 100644 --- a/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java +++ b/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java @@ -15,14 +15,18 @@ */ package com.intellij.execution.junit2; +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.execution.Location; import com.intellij.execution.PsiLocation; +import com.intellij.execution.junit.JUnitUtil; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMember; +import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; + public class PsiMemberParameterizedLocation extends PsiLocation { private final PsiClass myContainingClass; private final String myParamSetName; @@ -36,6 +40,29 @@ public class PsiMemberParameterizedLocation extends PsiLocation { myParamSetName = paramSetName; } + public static Location getParameterizedLocation(PsiClass psiClass, String paramSetName) { + return getParameterizedLocation(psiClass, paramSetName, JUnitUtil.PARAMETERIZED_CLASS_NAME); + } + + public static Location getParameterizedLocation(PsiClass psiClass, + String paramSetName, + String parameterizedClassName) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(psiClass, Collections.singleton(JUnitUtil.RUN_WITH)); + if (annotation != null) { + final PsiAnnotationMemberValue attributeValue = annotation.findAttributeValue("value"); + if (attributeValue instanceof PsiClassObjectAccessExpression) { + final PsiTypeElement operand = ((PsiClassObjectAccessExpression)attributeValue).getOperand(); + if (InheritanceUtil.isInheritor(operand.getType(), parameterizedClassName)) { + return new PsiMemberParameterizedLocation(psiClass.getProject(), + psiClass, + null, + paramSetName); + } + } + } + return null; + } + public String getParamSetName() { return myParamSetName; } diff --git a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml index 287df100d347..6b00567b5b0b 100644 --- a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml +++ b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml @@ -26,6 +26,7 @@ + diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.java new file mode 100644 index 000000000000..66793bb92c82 --- /dev/null +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.testAssistant; + +import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.execution.Location; +import com.intellij.execution.PsiLocation; +import com.intellij.execution.junit2.PsiMemberParameterizedLocation; +import com.intellij.execution.junit2.info.MethodLocation; +import com.intellij.ide.impl.dataRules.GetDataRule; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.GlobalSearchScopesCore; +import com.intellij.psi.search.PsiSearchHelper; +import com.intellij.testFramework.Parameterized; +import com.intellij.testFramework.TestDataPath; +import com.intellij.util.CommonProcessors; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class TestLocationDataRule implements GetDataRule { + @Nullable + @Override + public Object getData(DataProvider dataProvider) { + final Project project = CommonDataKeys.PROJECT.getData(dataProvider); + final VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(dataProvider); + if (project != null && file != null) { + final List locations = collectRelativeLocations(project, file); + return locations.size() == 1 ? locations.get(0) : null; + } + return null; + } + + @NotNull + protected static List collectRelativeLocations(Project project, VirtualFile file) { + final List locations = new ArrayList(); + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + if (fileIndex.isInContent(file) && !fileIndex.isInSource(file) && !fileIndex.isInLibraryClasses(file)) { + final VirtualFile parent = file.getParent(); + final VirtualFile contentRoot = fileIndex.getContentRootForFile(file); + if (contentRoot != null) { + final String relativePath = VfsUtilCore.getRelativePath(parent, contentRoot, '/'); + if (relativePath != null) { + final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project); + final List words = StringUtil.getWordsIn(relativePath); + // put longer strings first + Collections.sort(words, new Comparator() { + @Override + public int compare(final String o1, final String o2) { + return o2.length() - o1.length(); + } + }); + + final GlobalSearchScope testScope = GlobalSearchScopesCore.projectTestScope(project); + Set resultFiles = null; + for (String word : words) { + if (word.length() < 5) { + continue; + } + final Set files = new THashSet(); + searchHelper.processAllFilesWithWordInLiterals(word, testScope, new CommonProcessors.CollectProcessor(files)); + if (resultFiles == null) { + resultFiles = files; + } + else { + resultFiles.retainAll(files); + } + if (resultFiles.isEmpty()) break; + } + if (resultFiles != null) { + for (Iterator iterator = resultFiles.iterator(); iterator.hasNext(); ) { + if (!VfsUtilCore.isAncestor(contentRoot, iterator.next().getVirtualFile(), true)) { + iterator.remove(); + } + } + + final String fileName = file.getName(); + final String nameWithoutExtension = file.getNameWithoutExtension(); + + + for (PsiFile resultFile : resultFiles) { + if (resultFile instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)resultFile).getClasses(); + if (classes.length > 0) { + ContainerUtil.addIfNotNull(locations, getLocation(project, fileName, nameWithoutExtension, classes[0])); + } + } + } + } + } + } + } + return locations; + } + + @Nullable + private static Location getLocation(Project project, + String fileName, + String nameWithoutExtension, + PsiClass aClass) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(aClass, TestDataPath.class.getName()); + if (annotation != null) { + final Location parameterizedLocation = + PsiMemberParameterizedLocation.getParameterizedLocation(aClass, "[" + fileName + "]", Parameterized.class.getName()); + if (parameterizedLocation != null) { + return parameterizedLocation; + } + else { + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + PsiMethod method = aClass.findMethodBySignature(elementFactory.createMethod("test" + nameWithoutExtension, PsiType.VOID), true); + if (method != null) { + return MethodLocation.elementInClass(method, aClass); + } else { + method = aClass.findMethodBySignature(elementFactory.createMethod("test" + StringUtil.capitalize(nameWithoutExtension), PsiType.VOID), true); + if (method != null) { + return MethodLocation.elementInClass(method, aClass); + } else { + return new PsiLocation(project, aClass); + } + } + } + } + return null; + } +} diff --git a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java index 30c2dc85d753..412d0d18e74d 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java +++ b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java @@ -16,9 +16,7 @@ package com.intellij.execution.junit2; -import com.intellij.codeInsight.AnnotationUtil; import com.intellij.execution.Location; -import com.intellij.execution.junit.JUnitUtil; import com.intellij.execution.junit2.events.*; import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.execution.junit2.info.TestInfo; @@ -33,7 +31,6 @@ import com.intellij.openapi.project.Project; import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.InheritanceUtil; import com.intellij.rt.execution.junit.states.PoolOfTestStates; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -158,19 +155,7 @@ public class TestProxy extends AbstractTestProxy { if (parentLocation != null) { final PsiElement parentElement = parentLocation.getPsiElement(); if (parentElement instanceof PsiClass) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy((PsiClass)parentElement, Collections.singleton(JUnitUtil.RUN_WITH)); - if (annotation != null) { - final PsiAnnotationMemberValue attributeValue = annotation.findAttributeValue("value"); - if (attributeValue instanceof PsiClassObjectAccessExpression) { - final PsiTypeElement operand = ((PsiClassObjectAccessExpression)attributeValue).getOperand(); - if (InheritanceUtil.isInheritor(operand.getType(), JUnitUtil.PARAMETERIZED_CLASS_NAME)) { - return new PsiMemberParameterizedLocation(project, - parentElement, - null, - getInfo().getName()); - } - } - } + return PsiMemberParameterizedLocation.getParameterizedLocation((PsiClass)parentElement, getInfo().getName()); } } }