// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). // Licensed under the Apache License, Version 2.0 (see LICENSE). package com.twitter.intellij.pants.execution; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPackage; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testIntegration.TestIntegrationUtils; import com.twitter.intellij.pants.util.PantsConstants; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; public class PantsJUnitTestRunConfigurationProducer extends PantsTestRunConfigurationProducer { @Override protected boolean setupConfigurationFromContext( @NotNull ExternalSystemRunConfiguration configuration, @NotNull ConfigurationContext context, @NotNull Ref<PsiElement> sourceElement ) { Optional<PantsConfigurationContext> contextOptional = PantsConfigurationContext.validatesAndCreate(context); if (!contextOptional.isPresent()) { return false; } PantsConfigurationContext configurationContext = contextOptional.get(); final Module module = configurationContext.getModule(); final VirtualFile buildRoot = configurationContext.getBuildRoot(); final List<String> targets = configurationContext.getTargets(); final PsiElement psiLocation = configurationContext.getLocation(); final ExternalSystemTaskExecutionSettings taskSettings = configuration.getSettings(); taskSettings.setTaskNames(Collections.singletonList("test")); /** * Add the module's folder:: to target_roots **/ taskSettings.setExternalProjectPath(FileUtil.join(buildRoot.getPath(), targets.iterator().next())); taskSettings.setTaskNames(Collections.singletonList("test")); final PsiPackage testPackage; // Find out whether the click is on a test package if (psiLocation instanceof PsiPackage) { testPackage = (PsiPackage) psiLocation; } else if (psiLocation instanceof PsiDirectory) { testPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory) psiLocation)); } else { testPackage = null; } // Return false if it is a neither a test class nor a test package if (!TestIntegrationUtils.isTest(psiLocation) && !hasJUnitTestClasses(testPackage, module)) { return false; } final List<String> scriptParameters = new ArrayList<>(); scriptParameters.addAll(targets); final PsiClass psiClass = TestIntegrationUtils.findOuterClass(psiLocation); final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(psiLocation, PsiMethod.class, false); if (psiMethod != null) { sourceElement.set(psiMethod); configuration.setName(psiMethod.getName()); scriptParameters.add(PantsConstants.PANTS_CLI_OPTION_JUNIT_TEST + "=" + psiClass.getQualifiedName() + "#" + psiMethod.getName()); } else if (psiClass != null) { sourceElement.set(psiClass); configuration.setName(psiClass.getName()); scriptParameters.add("--test-junit-test=" + psiClass.getQualifiedName()); } else if (testPackage != null) { sourceElement.set(testPackage); configuration.setName(testPackage.getName()); // Iterate through test classes in testPackage that is only in the scope of the module Arrays.stream(testPackage.getClasses(module.getModuleScope())) .filter(TestIntegrationUtils::isTest) .forEach(psiClazz -> scriptParameters.add("--test-junit-test=" + psiClazz.getQualifiedName())); } else { return false; } taskSettings.setScriptParameters(StringUtil.join(scriptParameters, " ")); return true; } private boolean hasJUnitTestClasses(PsiPackage psiPackage, Module module) { if (psiPackage == null) return false; for (PsiClass psiClass : psiPackage.getClasses(module.getModuleScope())) { if (TestIntegrationUtils.isTest(psiClass)) { return true; } } return false; } }