/******************************************************************************* * Copyright (c) 2017 Rogue Wave Software Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rogue Wave Software Inc. - initial implementation *******************************************************************************/ package org.eclipse.php.phpunit.ui.launch; import static org.eclipse.php.phpunit.ui.launch.PHPUnitLaunchAttributes.*; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.dltk.ast.Modifiers; import org.eclipse.dltk.core.*; import org.eclipse.dltk.core.index2.search.ISearchEngine.MatchRule; import org.eclipse.dltk.core.search.IDLTKSearchScope; import org.eclipse.dltk.core.search.SearchEngine; import org.eclipse.dltk.internal.ui.filters.ClosedProjectFilter; import org.eclipse.dltk.internal.ui.filters.DotFileFilter; import org.eclipse.dltk.internal.ui.filters.LibraryFilter; import org.eclipse.dltk.ui.DLTKPluginImages; import org.eclipse.dltk.ui.ModelElementLabelProvider; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.viewers.*; import org.eclipse.jface.window.Window; import org.eclipse.php.core.PHPToolkitUtil; import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersKeys; import org.eclipse.php.internal.core.model.PHPModelAccess; import org.eclipse.php.internal.core.project.PHPNature; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.ui.PHPUiConstants; import org.eclipse.php.internal.ui.filters.RSEProjectFilter; import org.eclipse.php.internal.ui.util.PHPPluginImages; import org.eclipse.php.phpunit.PHPUnitMessages; import org.eclipse.php.phpunit.PHPUnitPlugin; import org.eclipse.php.phpunit.ui.preference.PHPUnitPreferenceKeys; import org.eclipse.php.phpunit.ui.preference.PHPUnitPreferencePage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.dialogs.SelectionDialog; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.views.navigator.ResourceComparator; public class PHPUnitLaunchConfigurationTab extends AbstractLaunchConfigurationTab { protected static PHPUnitLaunchConfigurationTab theTab; public static PHPUnitLaunchConfigurationTab getCurrent() { if (theTab == null) theTab = new PHPUnitLaunchConfigurationTab(); return theTab; } private Button fCodeCoverageButton; private Button fReportingButton; private Text fPhpunitConfigPath; private Button fSingleTestRadioButton; private Button fProjButton; private Label fProjLabel; private Text fProjText; private String previousSelectedProjectText; private Button fSearchButton; private Label fTestFileLabel; private Label fTestLabel; private Text fTestText; private Button fTestContainerRadioButton; private IResource fContainerElement; private Button fContainerSearchButton; private Text fContainerText; private Button fUsePharButton; private Button fUseComposerButton; private IProject fSelectedProject; private String fElementPath = ""; //$NON-NLS-1$ private PHPUnitTestElementFinder testElementFinder = new PHPUnitTestElementFinder(); private final ILabelProvider fPHPElementLabelProvider = new PHPUnitTreeLabelProvider(); private final Image fTestIcon = PHPUnitPlugin.createImage("main.png"); //$NON-NLS-1$ protected static class PHPUnitTreeLabelProvider extends LabelProvider { private Image fScriptFolder; private Image fClassImage; private Image fPHPProject; private Image fPHPFile; public PHPUnitTreeLabelProvider() { fClassImage = DLTKPluginImages.get(DLTKPluginImages.IMG_OBJS_CLASS); fScriptFolder = PHPPluginImages.get(PHPPluginImages.IMG_OBJS_PHP_FOLDER); fPHPProject = PHPPluginImages.get(PHPPluginImages.IMG_OBJS_PHP_PROJECT); fPHPFile = PHPPluginImages.get(PHPPluginImages.IMG_OBJS_PHP_FILE); } @Override public String getText(Object element) { if (element != null) { String elementName = ""; //$NON-NLS-1$ if (element instanceof IModelElement) { IModelElement modelElement = (IModelElement) element; elementName = modelElement.getElementName(); } return elementName; } return ""; //$NON-NLS-1$ } @Override public Image getImage(Object element) { Image result = null; if (element != null && element instanceof IModelElement) { if (element instanceof IScriptProject) { return fPHPProject; } if (element instanceof IScriptFolder || element instanceof IProjectFragment) { result = fScriptFolder; } if (element instanceof ISourceModule) { result = fPHPFile; } if (element instanceof IType) { result = fClassImage; } } return result; } }; public PHPUnitLaunchConfigurationTab() { theTab = this; } @Override public void initializeFrom(final ILaunchConfiguration config) { try { boolean isContainer = config.getAttribute(ATTRIBUTE_RUN_CONTAINER, false); String container = config.getAttribute(ATTRIBUTE_CONTAINER, StringUtils.EMPTY); String containerTypeName = config.getAttribute(ATTRIBUTE_CONTAINER_TYPE, StringUtils.EMPTY); String projectName = config.getAttribute(ATTRIBUTE_PROJECT, StringUtils.EMPTY); String testClassName = config.getAttribute(ATTRIBUTE_CLASS, StringUtils.EMPTY); String testFileName = config.getAttribute(ATTRIBUTE_FILE, StringUtils.EMPTY); boolean codeCoverage = config.getAttribute(ATTRIBUTE_CODE_COVERAGE, false); boolean xmlReporting = config.getAttribute(ATTRIBUTE_LOG_XML, false); String xmlUnitConfig = config.getAttribute(ATTRIBUTE_PHPUNIT_CFG, StringUtils.EMPTY); String executionType = config.getAttribute(ATTRIBUTE_EXECUTION_TYPE, PHAR_EXECUTION_TYPE); fSingleTestRadioButton.setSelection(!isContainer); fTestContainerRadioButton.setSelection(isContainer); setEnableSingleTestGroup(!isContainer); setEnableContainerTestGroup(isContainer); if (isContainer && !projectName.isEmpty()) { IResource containerElement = null; IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); if (!container.isEmpty()) { if (SOURCE_CONTAINER.equals(containerTypeName)) { final IFile file = project.getFile(container); containerElement = file; } if (FOLDER_CONTAINER.equals(containerTypeName)) { final IFolder folder = project.getFolder(container); containerElement = folder; } } if (PROJECT_CONTAINER.equals(containerTypeName)) { containerElement = project; } if (containerElement != null) { fContainerElement = containerElement; fContainerText.setText(fContainerElement.getFullPath().toPortableString()); } if (fContainerElement == null) { testModeChanged(); } fTestText.setText(StringUtils.EMPTY); fTestFileLabel.setText(StringUtils.EMPTY); } else { fProjText.setText(projectName); fTestText.setText(testClassName); fTestFileLabel.setText(testFileName); fContainerText.setText(StringUtils.EMPTY); } fPhpunitConfigPath.setText(xmlUnitConfig); fCodeCoverageButton.setSelection(codeCoverage); fReportingButton.setSelection(xmlReporting); fUsePharButton.setSelection(executionType.equals(PHAR_EXECUTION_TYPE)); fUseComposerButton.setSelection(!fUsePharButton.getSelection()); } catch (final CoreException ce) { } } @Override public void createControl(final Composite parent) { final Composite comp = new Composite(parent, SWT.NONE); setControl(comp); comp.setLayout(new GridLayout()); comp.setLayoutData(new GridData(GridData.FILL_BOTH)); createElementGroup(comp); createAdditionalGroup(comp); createExecutionGroup(comp); } private String choosePHPUnitConfig() { String initialPath = fPhpunitConfigPath.getText(); IContainer root = fSelectedProject; String pathStr = OpenFileDialog.openFile(getShell(), root, PHPUnitMessages.PHPUnitLaunchConfigurationTab_2, PHPUnitMessages.PHPUnitLaunchConfigurationTab_3, initialPath); if (pathStr == null) { return StringUtils.EMPTY; } IPath path = new Path(pathStr); return path.removeFirstSegments(1).toOSString(); } private void notifyParameterChanged() { validatePage(); updateLaunchConfigurationDialog(); } /** * @param comp */ private void createAdditionalGroup(final Composite comp) { final Group additionalGroup = new Group(comp, SWT.NULL); additionalGroup.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Additional); additionalGroup.setLayout(new GridLayout(3, false)); additionalGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); createCodeCoverageSection(additionalGroup); createReportingSection(additionalGroup); } /** * @param comp */ private void createCodeCoverageSection(final Composite comp) { fCodeCoverageButton = new Button(comp, SWT.CHECK); fCodeCoverageButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Coverage); fCodeCoverageButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1)); fCodeCoverageButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { notifyParameterChanged(); } }); Link fLink = new Link(comp, SWT.WRAP); fLink.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_6); fLink.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), PHPUnitPreferencePage.ID, new String[] { PHPUnitPreferencePage.ID }, null); dialog.open(); } }); } /** * @param comp */ private void createReportingSection(final Composite comp) { fReportingButton = new Button(comp, SWT.CHECK); fReportingButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Generate_Report); fReportingButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); fReportingButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { notifyParameterChanged(); } }); Label label = new Label(comp, SWT.NONE); label.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_2); fPhpunitConfigPath = new Text(comp, SWT.BORDER); fPhpunitConfigPath.addModifyListener(e -> notifyParameterChanged()); final GridData gd = new GridData(GridData.FILL_HORIZONTAL); fPhpunitConfigPath.setLayoutData(gd); Button browse = new Button(comp, SWT.NONE); browse.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_5); browse.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleBrowsePHPUnitConfigPressed(); } }); } private void createExecutionGroup(final Composite comp) { final Group group = new Group(comp, SWT.NULL); group.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Execution_parameters); group.setLayout(new GridLayout(2, false)); group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fUsePharButton = new Button(group, SWT.RADIO); fUsePharButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Use_global_phar); fUsePharButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true)); fUsePharButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { notifyParameterChanged(); } }); Link fLink = new Link(group, SWT.WRAP); fLink.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Preferences_link); fLink.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), PHPUnitPreferencePage.ID, new String[] { PHPUnitPreferencePage.ID }, null); dialog.open(); } }); fUseComposerButton = new Button(group, SWT.RADIO); fUseComposerButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Use_composer); fUseComposerButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true, 2, 1)); fUseComposerButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { notifyParameterChanged(); } }); } /** * @param comp */ private void createElementGroup(final Composite comp) { final Group elementGroup = new Group(comp, SWT.NULL); elementGroup.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Elements); elementGroup.setLayout(new GridLayout(3, false)); elementGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); createSingleTestSection(elementGroup); createTestContainerSection(elementGroup); } private void createProjButton(final Composite comp) { fProjButton = new Button(comp, SWT.PUSH); fProjButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Browse); fProjButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent evt) { handleProjectButtonPressed(); } }); setButtonGridData(fProjButton); } private void createProjLabel(final Composite comp) { GridData gd; fProjLabel = new Label(comp, SWT.NONE); fProjLabel.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Project); gd = new GridData(); gd.horizontalIndent = 25; fProjLabel.setLayoutData(gd); } private void createProjText(final Composite comp) { fProjText = new Text(comp, SWT.SINGLE | SWT.BORDER); fProjText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fProjText.addModifyListener(evt -> { if (previousSelectedProjectText != null && previousSelectedProjectText.length() > 0 && !previousSelectedProjectText.equals(fProjText.getText())) { testElementFinder.cleareCaches(); } previousSelectedProjectText = fProjText.getText(); validatePage(); notifyParameterChanged(); fSearchButton.setEnabled(fSingleTestRadioButton.getSelection() && fProjText.getText().length() > 0); }); } private void createSingleTestSection(final Composite comp) { createTestRadioButton(comp); createProjLabel(comp); createProjText(comp); createProjButton(comp); createTestLabel(comp); createTestText(comp); createTestSearchButton(comp); new Label(comp, SWT.NONE); createTestFileLabel(comp); } private void createTestContainerSection(final Composite comp) { fTestContainerRadioButton = new Button(comp, SWT.RADIO); fTestContainerRadioButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Run_Container); GridData gd = new GridData(); gd.horizontalSpan = 3; fTestContainerRadioButton.setLayoutData(gd); fTestContainerRadioButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { if (fTestContainerRadioButton.getSelection()) testModeChanged(); } }); fContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalIndent = 25; gd.horizontalSpan = 2; fContainerText.setLayoutData(gd); fContainerText.addModifyListener(evt -> notifyParameterChanged()); fContainerSearchButton = new Button(comp, SWT.PUSH); fContainerSearchButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Search); fContainerSearchButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent evt) { handleContainerSearchButtonSelected(); } }); setButtonGridData(fContainerSearchButton); } private void createTestFileLabel(final Composite comp) { fTestFileLabel = new Label(comp, SWT.NONE); fTestFileLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1)); } private void createTestLabel(final Composite comp) { fTestLabel = new Label(comp, SWT.NONE); GridData gd = new GridData(); gd.horizontalIndent = 25; fTestLabel.setLayoutData(gd); fTestLabel.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Class); } private void createTestRadioButton(final Composite comp) { fSingleTestRadioButton = new Button(comp, SWT.RADIO); fSingleTestRadioButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Test); final GridData gd = new GridData(); gd.horizontalSpan = 3; fSingleTestRadioButton.setLayoutData(gd); fSingleTestRadioButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { if (fSingleTestRadioButton.getSelection()) { testModeChanged(); } } }); } private void createTestSearchButton(final Composite comp) { fSearchButton = new Button(comp, SWT.PUSH); fSearchButton.setEnabled(fProjText.getText().length() > 0); fSearchButton.setText(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Search); fSearchButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent evt) { if (previousSelectedProjectText != null && previousSelectedProjectText.length() > 0 && !previousSelectedProjectText.equals(fProjText.getText())) { testElementFinder.cleareCaches(); } IScriptProject phpProject = getPHPProject(); if (!validatePHPProject(phpProject.getProject())) { return; } previousSelectedProjectText = fProjText.getText(); handleSearchButtonPressed(); } }); setButtonGridData(fSearchButton); } private void createTestText(final Composite comp) { fTestText = new Text(comp, SWT.SINGLE | SWT.BORDER); fTestText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fTestText.addModifyListener(evt -> updateLaunchConfigurationDialog()); fTestText.setEditable(false); } /** * Return the IProject corresponding to the project name in the project name * text field, or null if the text does not match a project name. */ private IScriptProject getPHPProject() { final String projectName = fProjText.getText().trim(); if (projectName.isEmpty()) { return null; } final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(fProjText.getText()); try { if (PHPToolkitUtil.isPHPProject(project)) { return DLTKCore.create(project); } } catch (CoreException e) { // return null } return null; } private String getProjectRelativePath(final IResource element) { if (element instanceof IProject) { return StringUtils.EMPTY; } return element.getFullPath().makeRelativeTo(element.getProject().getFullPath()).toOSString(); } private void handleContainerSearchButtonSelected() { final IResource phpElement = chooseContainer(fContainerElement); if (phpElement != null) setContainerElement(phpElement); } private IResource chooseContainer(final Object initElement) { final ITreeContentProvider provider = new WorkbenchContentProvider(); final ILabelProvider labelProvider = new WorkbenchLabelProvider(); final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), labelProvider, provider); dialog.setTitle(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Container_Selection); dialog.setMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Choose_Container); // filter elements RSEProjectFilter filter1 = new RSEProjectFilter(); dialog.addFilter(filter1); DotFileFilter filter2 = new DotFileFilter(); dialog.addFilter(filter2); ClosedProjectFilter filter3 = new ClosedProjectFilter(); dialog.addFilter(filter3); dialog.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof IFile) { IResource resource = (IResource) element; return "php".equalsIgnoreCase(resource.getFileExtension()); //$NON-NLS-1$ } return true; } }); LibraryFilter filter6 = new LibraryFilter(); dialog.addFilter(filter6); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); dialog.setAllowMultiple(false); dialog.setInitialSelection(initElement); if (dialog.open() == Dialog.OK) { return (IResource) dialog.getFirstResult(); } return null; } /** * Show a dialog that lets the user select a project. This in turn provides * context for the main class, allowing the user to key a main class name, * or constraining the search for main classes to the specified project. */ private void handleProjectButtonPressed() { final IProject project = choosePHPProject(); if (project == null) { return; } final String projectName = project.getName(); fProjText.setText(projectName); validatePHPProject(project); } private void handleBrowsePHPUnitConfigPressed() { String newPath = choosePHPUnitConfig(); fPhpunitConfigPath.setText(newPath); } /** * Show a dialog that lists all main classess */ private void handleSearchButtonPressed() { final IScriptProject phpProject = getPHPProject(); if (phpProject == null) { return; } boolean[] radioSetting = new boolean[2]; try { // fix for 66922 Wrong radio behaviour when switching // remember the selected radio button radioSetting[0] = fSingleTestRadioButton.getSelection(); radioSetting[1] = fTestContainerRadioButton.getSelection(); if (testElementFinder.getPHP_UNIT_SUITE_CACHED() == null && testElementFinder.getPHP_UNIT_CASE_CACHED() == null) { getLaunchConfigurationDialog().run(true, false, testElementFinder.search(phpProject)); } } catch (InterruptedException e) { setErrorMessage(e.getMessage()); return; } catch (InvocationTargetException e) { PHPUnitPlugin.log(e.getTargetException()); return; } finally { fSingleTestRadioButton.setSelection(radioSetting[0]); fTestContainerRadioButton.setSelection(radioSetting[1]); } Shell shell = getShell(); SelectionDialog dialog = new TestSelectionDialog(shell, testElementFinder.getPHP_UNIT_CASES_AND_SUITES()); dialog.setTitle(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Test_Selection); dialog.setMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Choose_Test); if (dialog.open() == Window.CANCEL) { return; } Object[] results = dialog.getResult(); if ((results == null) || (results.length < 1)) { return; } IType type = (IType) results[0]; if (type != null) { fElementPath = type.getPath().toOSString(); fTestText.setText(type.getElementName()); fProjText.setText(type.getScriptProject().getElementName()); IResource typResource = type.getResource(); if (typResource != null) { IPath relativePath = typResource.getFullPath().makeRelativeTo(typResource.getProject().getFullPath()); fTestFileLabel.setText(relativePath.toPortableString()); } else { fTestFileLabel.setText(StringUtils.EMPTY); } validatePHPProject(typResource.getProject()); } } /* * Realize a Project selection dialog and return the first selected project, * or null if there was none. */ private IProject choosePHPProject() { final ILabelProvider labelProvider = new ModelElementLabelProvider(ModelElementLabelProvider.SHOW_DEFAULT); final ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider); dialog.setTitle(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Project_Selection); dialog.setMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Choose_Project); IScriptProject[] scriptProjects = getScriptProjects(); dialog.setElements(scriptProjects); dialog.setInitialSelections(scriptProjects); if (dialog.open() == Window.OK) { IScriptProject scriptProject = (IScriptProject) dialog.getFirstResult(); return scriptProject.getProject(); } return null; } private IScriptProject[] getScriptProjects() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); if (projects == null) { return new IScriptProject[0]; } List<IScriptProject> scriptProjectsList = new ArrayList<>(); for (IProject project : projects) { try { if (project.isOpen() && project.hasNature(PHPNature.ID) && !project.hasNature(PHPUiConstants.RSE_TEMP_PROJECT_NATURE_ID) && !project.getName().equals(PHPUiConstants.RSE_TEMP_PROJECT_NAME)) { IScriptProject scriptProject = DLTKCore.create(project); scriptProjectsList.add(scriptProject); } } catch (CoreException e) { PHPUnitPlugin.log(e); } } return scriptProjectsList.toArray(new IScriptProject[scriptProjectsList.size()]); } private String findFileToExecute(ILaunchConfiguration config, IProject project) throws CoreException { String runType = config.getAttribute(ATTRIBUTE_EXECUTION_TYPE, PHAR_EXECUTION_TYPE); if (COMPOSER_EXECUTION_TYPE.equals(runType)) { return PHPUnitLaunchUtils.findComposerExecutionFile(project); } else if (PHAR_EXECUTION_TYPE.equals(runType)) { return PHPUnitPreferenceKeys.getPHPUnitPharPath(); } return null; } @Override public boolean isValid(final ILaunchConfiguration config) { return getErrorMessage() == null; } @Override public void performApply(final ILaunchConfigurationWorkingCopy config) { fSelectedProject = null; if (fTestContainerRadioButton.getSelection()) { config.setAttribute(ATTRIBUTE_RUN_CONTAINER, true); if (fContainerElement != null) { fElementPath = fContainerElement.getFullPath().toOSString(); fSelectedProject = fContainerElement.getProject(); config.setAttribute(ATTRIBUTE_PROJECT, fSelectedProject.getProject().getName()); config.setAttribute(ATTRIBUTE_CONTAINER, getProjectRelativePath(fContainerElement)); String typeName = getContainerType(fContainerElement); config.setAttribute(ATTRIBUTE_CONTAINER_TYPE, typeName); } } else { config.setAttribute(ATTRIBUTE_RUN_CONTAINER, false); final String pText = fProjText.getText(); config.setAttribute(ATTRIBUTE_PROJECT, pText); if (pText != null) { final IScriptProject[] scriptProjects = getScriptProjects(); for (IScriptProject script : scriptProjects) { if (pText.equals(script.getProject().getName())) { fSelectedProject = script.getProject(); break; } } } config.setAttribute(ATTRIBUTE_CLASS, fTestText.getText()); config.setAttribute(ATTRIBUTE_FILE, fTestFileLabel.getText()); config.setAttribute(ATTRIBUTE_CONTAINER_TYPE, SOURCE_CONTAINER); } if (StringUtils.isNotEmpty(fElementPath)) { config.setAttribute(PHPUnitPlugin.ELEMENT_PATH_ATTR, fElementPath); fElementPath = StringUtils.EMPTY; } config.setAttribute(ATTRIBUTE_CODE_COVERAGE, fCodeCoverageButton.getSelection()); config.setAttribute(ATTRIBUTE_LOG_XML, fReportingButton.getSelection()); config.setAttribute(ATTRIBUTE_PHPUNIT_CFG, fPhpunitConfigPath.getText()); if (fUsePharButton.getSelection()) { config.setAttribute(ATTRIBUTE_EXECUTION_TYPE, PHAR_EXECUTION_TYPE); } else if (fUseComposerButton.getSelection()) { config.setAttribute(ATTRIBUTE_EXECUTION_TYPE, COMPOSER_EXECUTION_TYPE); } // Set up PHP script launching specific attributes String projectName; try { // Don't stop on a first breakpoint if in debug mode config.setAttribute(IDebugParametersKeys.FIRST_LINE_BREAKPOINT, false); projectName = config.getAttribute(ATTRIBUTE_PROJECT, ""); //$NON-NLS-1$ if (StringUtils.isNotEmpty(projectName)) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); config.setAttribute(IPHPDebugConstants.PHP_Project, project.getName()); String fileToExecute = findFileToExecute(config, project); config.setAttribute(IPHPDebugConstants.ATTR_FILE, fileToExecute); config.setAttribute(IPHPDebugConstants.ATTR_FILE_FULL_PATH, fileToExecute); } } catch (CoreException e) { PHPUnitPlugin.log(e); } } private String getContainerType(IResource container) { if (container instanceof IProject) { return PROJECT_CONTAINER; } if (container instanceof IFolder) { return FOLDER_CONTAINER; } if (container instanceof IFile) { return SOURCE_CONTAINER; } return null; } private void setButtonGridData(final Button button) { final GridData gridData = new GridData(); button.setLayoutData(gridData); } private void setContainerElement(final IResource container) { fContainerElement = container; fContainerText.setText(container.getFullPath().toString()); validatePage(); notifyParameterChanged(); } @Override public void setDefaults(final ILaunchConfigurationWorkingCopy config) { PHPUnitLaunchUtils.initializeDefaults(config); } private void setEnableContainerTestGroup(final boolean enabled) { fContainerSearchButton.setEnabled(enabled); fContainerText.setEnabled(enabled); } private void setEnableSingleTestGroup(final boolean enabled) { fProjLabel.setEnabled(enabled); fProjText.setEnabled(enabled); fProjButton.setEnabled(enabled); fTestLabel.setEnabled(enabled); fSearchButton.setEnabled(enabled && fProjText.getText().length() > 0); } private void testModeChanged() { if (previousSelectedProjectText != null && previousSelectedProjectText.length() > 0 && !previousSelectedProjectText.equals(fProjText.getText())) { testElementFinder.cleareCaches(); } previousSelectedProjectText = fProjText.getText(); boolean isSingleTestMode = fSingleTestRadioButton.getSelection(); setEnableSingleTestGroup(isSingleTestMode); setEnableContainerTestGroup(!isSingleTestMode); if (!isSingleTestMode && StringUtils.isEmpty(fContainerText.getText())) { final IScriptProject phpProject = getPHPProject(); if (phpProject != null) { setContainerElement(phpProject.getProject()); } } validatePage(); updateLaunchConfigurationDialog(); } private void validatePage() { setErrorMessage(null); setMessage(null); if (fSingleTestRadioButton.getSelection()) { IScriptProject scriptProject = getPHPProject(); if (scriptProject == null) { testElementFinder.cleareCaches(); setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_No_Project); return; } String projectName = scriptProject.getElementName(); final IStatus status = ResourcesPlugin.getWorkspace().validatePath(IPath.SEPARATOR + projectName, IResource.PROJECT); if (!status.isOK()) { testElementFinder.cleareCaches(); setErrorMessage(PHPUnitMessages.format(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Bad_Project_Name, projectName)); return; } final IProject project = scriptProject.getProject(); if (!project.exists()) { testElementFinder.cleareCaches(); setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Project_unavailable); return; } try { if (PHPToolkitUtil.isPHPProject(project)) { setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Project_Not_PHP); testElementFinder.cleareCaches(); return; } } catch (CoreException e) { } if (validatePHPProject(project.getProject())) { final String className = fTestText.getText().trim(); if (className.length() == 0) { setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_No_Test); return; } else { IDLTKSearchScope searchScope = SearchEngine.createSearchScope(scriptProject); IType[] classes = PHPModelAccess.getDefault().findTypes(className, MatchRule.EXACT, 0, Modifiers.AccInterface | Modifiers.AccNameSpace | Modifiers.AccAbstract, searchScope, null); if (classes.length < 1) { setErrorMessage(PHPUnitMessages.format(PHPUnitMessages.PHPUnitValidator_Not_In_Project, new String[] { className, projectName })); } } } } else { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource resource = root.findMember(fContainerText.getText()); if (resource == null) { setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_No_Element_To_Test); return; } } if (fUseComposerButton.getSelection() && fSelectedProject != null && PHPUnitLaunchUtils.findComposerExecutionFile(fSelectedProject) == null) { setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Unable_find_dependencies); return; } } private boolean validatePHPProject(final IProject phpProject) { try { if (testElementFinder.getPHP_UNIT_SUITE_CACHED() == null && testElementFinder.getPHP_UNIT_CASE_CACHED() == null) { getLaunchConfigurationDialog().run(true, false, testElementFinder.search(DLTKCore.create(phpProject))); } } catch (final InterruptedException | InvocationTargetException e) { PHPUnitPlugin.log(e); } if (testElementFinder.getPHP_UNIT_CASES_AND_SUITES() == null || testElementFinder.getPHP_UNIT_CASES_AND_SUITES().length == 0) { setErrorMessage(PHPUnitMessages.PHPUnitLaunchConfigurationTab_Project_No_Tests); fSearchButton.setEnabled(false); updateLaunchConfigurationDialog(); return false; } fSearchButton.setEnabled(true); return true; } @Override public Image getImage() { return fTestIcon; } @Override public String getName() { return PHPUnitMessages.PHPUnitLaunchConfigurationTab_7; } @Override public void dispose() { super.dispose(); fTestIcon.dispose(); fPHPElementLabelProvider.dispose(); } }