package com.redhat.ceylon.test.eclipse.plugin.launch; import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getCeylonModulesOutputFolder; import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectDeclaredSourceModules; import static com.redhat.ceylon.eclipse.util.CeylonHelper.toJavaStringList; import static com.redhat.ceylon.test.eclipse.plugin.CeylonTestPlugin.LAUNCH_CONFIG_PORT; import static com.redhat.ceylon.test.eclipse.plugin.CeylonTestPlugin.LAUNCH_CONFIG_TYPE; import static com.redhat.ceylon.test.eclipse.plugin.CeylonTestPlugin.LAUNCH_CONFIG_TYPE_JS; import static com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil.getShell; import static com.redhat.ceylon.eclipse.java2ceylon.Java2CeylonProxies.*; import java.util.LinkedHashSet; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IStatusHandler; import org.eclipse.jdt.launching.SocketUtil; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import com.redhat.ceylon.eclipse.core.launch.ModuleLaunchDelegate; import com.redhat.ceylon.ide.common.model.CeylonProjectConfig; import com.redhat.ceylon.model.typechecker.model.Module; import com.redhat.ceylon.test.eclipse.plugin.CeylonTestMessages; import com.redhat.ceylon.test.eclipse.plugin.CeylonTestPlugin; import com.redhat.ceylon.test.eclipse.plugin.ui.TestRunViewPart; import com.redhat.ceylon.test.eclipse.plugin.util.CeylonTestUtil; public class CeylonTestLaunchDelegate extends ModuleLaunchDelegate { private final ThreadLocal<String> portThreadLocal = new ThreadLocal<String>(); @Override public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { String port = getFreePort(); launch.setAttribute(LAUNCH_CONFIG_PORT, port); try { portThreadLocal.set(port); super.launch(config, mode, launch, monitor); } finally { portThreadLocal.remove(); } TestRunViewPart.showPageAsync(); } @Override protected void prepareArguments(List<String> args, List<IPath> workingRepos, IProject p, ILaunchConfiguration configuration, boolean runAsJs) throws CoreException { runAsJs = DebugPlugin.getDefault().getLaunchManager() .getLaunchConfigurationType(LAUNCH_CONFIG_TYPE_JS).equals(configuration.getType()); LinkedHashSet<String> moduleArgs = new LinkedHashSet<String>(); LinkedHashSet<String> testArgs = new LinkedHashSet<String>(); LinkedHashSet<IProject> projects = new LinkedHashSet<IProject>(); List<CeylonTestLaunchConfigEntry> entries = CeylonTestLaunchConfigEntry.buildFromLaunchConfig(configuration); for (CeylonTestLaunchConfigEntry entry : entries) { IProject project = null; Module module = null; switch (entry.getType()) { case PROJECT: project = CeylonTestUtil.getProject(entry.getProjectName()); projects.add(project); for (Module m : getProjectDeclaredSourceModules(project)) { if (CeylonTestUtil.containsCeylonTestImport(m) && CeylonTestUtil.checkNativeBackend(m, runAsJs ? LAUNCH_CONFIG_TYPE_JS : LAUNCH_CONFIG_TYPE)) { moduleArgs.add(m.getNameAsString() + "/" + m.getVersion()); testArgs.add("module " + m.getNameAsString()); } } break; case MODULE: project = CeylonTestUtil.getProject(entry.getProjectName()); projects.add(project); module = CeylonTestUtil.getModule(project, entry.getModPkgDeclName()); moduleArgs.add(module.getNameAsString() + "/" + module.getVersion()); testArgs.add("module " + module.getNameAsString()); break; case PACKAGE: project = CeylonTestUtil.getProject(entry.getProjectName()); projects.add(project); module = CeylonTestUtil.getModule(project, entry.getModuleName()); moduleArgs.add(module.getNameAsString() + "/" + module.getVersion()); testArgs.add("package " + entry.getModPkgDeclName()); break; case CLASS: case CLASS_LOCAL: project = CeylonTestUtil.getProject(entry.getProjectName()); projects.add(project); module = CeylonTestUtil.getModule(project, entry.getModuleName()); moduleArgs.add(module.getNameAsString() + "/" + module.getVersion()); testArgs.add("class " + entry.getModPkgDeclName()); break; case METHOD: case METHOD_LOCAL: project = CeylonTestUtil.getProject(entry.getProjectName()); projects.add(project); module = CeylonTestUtil.getModule(project, entry.getModuleName()); moduleArgs.add(module.getNameAsString() + "/" + module.getVersion()); testArgs.add("function " + entry.getModPkgDeclName()); break; } } if(runAsJs) { args.add("test-js"); } else { args.add("test"); } args.add("--port="+portThreadLocal.get()); for (IPath workingRepo : workingRepos) { args.add("--rep"); args.add(workingRepo.toOSString()); } for (IProject project : projects) { IPath outputFolder = getCeylonModulesOutputFolder(project).getLocation(); if (!workingRepos.contains(outputFolder)) { args.add("--rep"); args.add(outputFolder.toOSString()); } CeylonProjectConfig projectConfig = modelJ2C().ceylonModel() .getProject(project).getConfiguration(); for (String repo : toJavaStringList(projectConfig.getProjectLocalRepos())) { args.add("--rep"); args.add(repo); } } for (String testArg : testArgs) { args.add("--test"); args.add(testArg); } args.addAll(moduleArgs); } @Override public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { if( !validateConfig(config) ) return false; if( !validateCeylonTestDependency(config) ) return false; return super.preLaunchCheck(config, mode, monitor); } private boolean validateCeylonTestDependency(ILaunchConfiguration config) throws CoreException { IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus); if (prompter != null) { if (!((Boolean) prompter.handleStatus(CeylonTestDependencyStatusHandler.CODE, config)).booleanValue()) { return false; } } return true; } private boolean validateConfig(ILaunchConfiguration config) throws CoreException { String errorMessage = null; List<CeylonTestLaunchConfigEntry> entries = CeylonTestLaunchConfigEntry.buildFromLaunchConfig(config); for (CeylonTestLaunchConfigEntry entry : entries) { entry.validate(); if (!entry.isValid()) { errorMessage = entry.getErrorMessage(); break; } } if (errorMessage != null) { final String errorMessageFinal = errorMessage; Display.getDefault().asyncExec(new Runnable() { @Override public void run() { MessageDialog.openInformation(getShell(), CeylonTestMessages.launchDialogInfoTitle, CeylonTestMessages.launchConfigIsNotValid + "\n" + errorMessageFinal); } }); return false; } return true; } private String getFreePort() throws CoreException { int port = SocketUtil.findFreePort(); if (port == -1) { throw new CoreException(new Status(IStatus.ERROR, CeylonTestPlugin.PLUGIN_ID, CeylonTestMessages.errorNoSocket)); } return String.valueOf(port); } }