package org.atoum.intellij.plugin.atoum; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.php.PhpIndex; import com.jetbrains.php.lang.psi.PhpFile; import com.jetbrains.php.lang.psi.elements.ClassReference; import com.jetbrains.php.lang.psi.elements.PhpClass; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class Utils { public static Boolean isClassAtoumTest(PhpClass checkedClass) { // First, we check if the class is in the units tests namespace if (!checkedClass.getNamespaceName().toLowerCase().contains(getTestsNamespaceSuffix().toLowerCase())) { return false; } if (checkedClass.isAbstract() || checkedClass.isInterface()) { return false; } // We also check if the class extends atoum PhpClass loopCheckedClass = checkedClass; while (loopCheckedClass.getSuperClass() != null) { PhpClass parent = loopCheckedClass.getSuperClass(); if (parent.getFQN().equals("\\atoum")) { return true; } loopCheckedClass = parent; } // We try with another method to check, if the project does not have atoum/stubs do { List<ClassReference> extendsList = checkedClass.getExtendsList().getReferenceElements(); if (extendsList.iterator().hasNext()) { ClassReference ref = extendsList.iterator().next(); if (ref.getFQN() != null && ref.getFQN().equals("\\atoum")) { return true; } } checkedClass = checkedClass.getSuperClass(); } while (checkedClass != null); return false; } @Nullable public static PhpClass locateTestClass(Project project, PhpClass testedClass) { Collection<PhpClass> possibleClasses = locateTestClasses(project, testedClass); if (possibleClasses.size() > 0) { return (PhpClass)possibleClasses.toArray()[0]; } return null; } @Nullable public static Collection<PhpClass> locateTestClasses(Project project, PhpClass testedClass) { if (testedClass.getNamespaceName().length() == 1) { Collection<PhpClass> foundClasses = locatePhpClasses(project, getTestsNamespaceSuffix() + testedClass.getName()); if (foundClasses.size() > 0) { return foundClasses; } } String[] namespaceParts = testedClass.getNamespaceName().split("\\\\"); for(int i=namespaceParts.length; i>=1; i--){ List<String> foo = Lists.newArrayList(namespaceParts); foo.add(i, getTestsNamespaceSuffix().substring(0, getTestsNamespaceSuffix().length() - 1)); String possibleClassname = StringUtils.join(foo, "\\") + "\\" + testedClass.getName(); Collection<PhpClass> foundClasses = locatePhpClasses(project, possibleClassname); if (foundClasses.size() > 0) { return foundClasses; } } return new ArrayList<PhpClass>(); } @Nullable public static PhpClass locateTestedClass(Project project, PhpClass testClass) { Collection<PhpClass> possibleClasses = locateTestedClasses(project, testClass); if (possibleClasses.size() > 0) { return (PhpClass)possibleClasses.toArray()[0]; } return null; } @Nullable public static Collection<PhpClass> locateTestedClasses(Project project, PhpClass testClass) { String testClassNamespaceName = testClass.getNamespaceName(); String testedClassname = testClassNamespaceName.toLowerCase().replace(getTestsNamespaceSuffix().toLowerCase(), "") + testClass.getName(); return locatePhpClasses(project, testedClassname); } @Nullable protected static PhpClass locatePhpClass(Project project, String name) { Collection<PhpClass> phpClasses = locatePhpClasses(project, name); if (phpClasses.size() != 1) { return null; } return (PhpClass)phpClasses.toArray()[0]; } @Nullable protected static Collection<PhpClass> locatePhpClasses(Project project, String name) { return PhpIndex.getInstance(project).getAnyByFQN(name); } private static String getTestsNamespaceSuffix() { return "tests\\units\\"; } //https://github.com/Haehnchen/idea-php-symfony2-plugin/blob/cb422db9779025d65fdf0ba5d26a38d401eca939/src/fr/adrienbrault/idea/symfony2plugin/util/PhpElementsUtil.java#L784 @Nullable public static PhpClass getFirstClassFromFile(PhpFile phpFile) { Collection<PhpClass> phpClasses = PsiTreeUtil.collectElementsOfType(phpFile, PhpClass.class); return phpClasses.size() == 0 ? null : phpClasses.iterator().next(); } @Nullable public static PhpClass getFirstTestClassFromFile(PhpFile phpFile) { Collection<PhpClass> phpClasses = PsiTreeUtil.collectElementsOfType(phpFile, PhpClass.class); for (PhpClass phpClass:phpClasses) { if (isClassAtoumTest(phpClass)) { return phpClass; } } return null; } }