/* * #%~ * org.overture.ide.debug * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.ide.debug.ui.launchconfigurations; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.ILaunchShortcut2; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.eclipse.ui.progress.IProgressService; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.AExplicitOperationDefinition; import org.overture.ast.node.INode; import org.overture.ide.core.IVdmModel; import org.overture.ide.core.resources.IVdmProject; import org.overture.ide.debug.core.IDebugConstants; import org.overture.ide.debug.core.VdmDebugPlugin; import org.overture.ide.ui.utility.ast.AstNameUtil; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; import org.overture.typechecker.assistant.TypeCheckerAssistantFactory; public abstract class VdmLaunchShortcut implements ILaunchShortcut2 { public final ITypeCheckerAssistantFactory assistantFactory = new TypeCheckerAssistantFactory(); /** * Returns the type of configuration this shortcut is applicable to. * * @return the type of configuration this shortcut is applicable to */ protected abstract ILaunchConfigurationType getConfigurationType(); /** * Creates and returns a new configuration based on the specified type. * * @param type * type to create a launch configuration for * @return launch configuration configured to launch the specified type */ protected abstract ILaunchConfiguration createConfiguration(INode type, String projectName); /** * Finds and returns the types in the given collection of elements that can be launched. * * @param elements * scope to search for types that can be launched * @param context * progress reporting context * @return collection of types that can be launched, possibly empty * @exception InterruptedException * if the search is canceled * @exception CoreException * if the search fails */ // protected abstract IAstNode[] findTypes(Object[] elements, // IRunnableContext context) throws InterruptedException, // CoreException; protected abstract INode[] filterTypes(Object[] elements, IRunnableContext context); /** * Returns a title for a type selection dialog used to prompt the user when there is more than one type that can be * launched. * * @return type selection dialog title */ protected abstract String getTypeSelectionTitle(); /** * Returns an error message to use when the editor does not contain a type that can be launched. * * @return error message when editor cannot be launched */ protected abstract String getEditorEmptyMessage(); /** * Returns an error message to use when the selection does not contain a type that can be launched. * * @return error message when selection cannot be launched */ protected abstract String getSelectionEmptyMessage(); IProject project = null; /** * Resolves a type that can be launched from the given scope and launches in the specified mode. * * @param scope * the java elements to consider for a type that can be launched * @param mode * launch mode * @param selectTitle * prompting title for choosing a type to launch * @param emptyMessage * error message when no types are resolved for launching */ private void searchAndLaunch(Object[] scope, String mode, String selectTitle, String emptyMessage) { INode[] types = null; try { project = findProject(scope, PlatformUI.getWorkbench().getProgressService()); ILaunchConfiguration config = findLaunchConfiguration(project.getName(), getConfigurationType()); if (config != null) { // config already exists for the project. launch(config, mode); return; } types = findTypes(scope, PlatformUI.getWorkbench().getProgressService()); } catch (InterruptedException e) { return; } catch (CoreException e) { MessageDialog.openError(getShell(), LauncherMessages.VdmLaunchShortcut_0, e.getMessage()); return; } INode type = null; if (types == null || types.length == 0) { MessageDialog.openError(getShell(), LauncherMessages.VdmLaunchShortcut_1, emptyMessage); } else if (types.length > 1) { type = chooseType(types, selectTitle); } else { type = types[0]; } if (type != null && project != null) { launch(type, mode, project.getName()); } } /** * Prompts the user to select a type from the given types. * * @param types * the types to choose from * @param title * the selection dialog title * @return the selected type or <code>null</code> if none. */ protected INode chooseType(INode[] types, String title) { try { DebugTypeSelectionDialog mmsd = new DebugTypeSelectionDialog(VdmDebugPlugin.getActiveWorkbenchShell(), types, title, project); if (mmsd.open() == Window.OK) { return (INode) mmsd.getResult()[0]; } } catch (Exception e) { e.printStackTrace(); } return null; } private void launch(INode type, String mode, String projectName) { ILaunchConfiguration config = findLaunchConfiguration(projectName, getConfigurationType()); if (config == null) { config = createConfiguration(type, projectName); } launch(config, mode); } private void launch(ILaunchConfiguration config, String mode) { if (config != null) { DebugUITools.launch(config, mode); } } /** * Finds and returns an <b>existing</b> configuration to re-launch for the given type, or <code>null</code> if there * is no existing configuration. * * @return a configuration to use for launching the given type or <code>null</code> if none */ protected ILaunchConfiguration findLaunchConfiguration(String projectName, ILaunchConfigurationType configType) { List<ILaunchConfiguration> candidateConfigs = Collections.emptyList(); try { ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(configType); candidateConfigs = new ArrayList<ILaunchConfiguration>(configs.length); for (int i = 0; i < configs.length; i++) { ILaunchConfiguration config = configs[i]; // String defaultModule = config.getAttribute(IDebugConstants.VDM_LAUNCH_CONFIG_DEFAULT, ""); String pName = config.getAttribute(IDebugConstants.VDM_LAUNCH_CONFIG_PROJECT, ""); // String operation = config.getAttribute(IDebugConstants.VDM_LAUNCH_CONFIG_OPERATION, ""); if (// defaultModule.equals(getModuleName(type).toString()) // && pName.equalsIgnoreCase(projectName) // && operation.equals(getOperationName(type) + "()") ) { //$NON-NLS-1$ candidateConfigs.add(config); } } } catch (CoreException e) { // JDIDebugUIPlugin.log(e); } int candidateCount = candidateConfigs.size(); if (candidateCount == 1) { return (ILaunchConfiguration) candidateConfigs.get(0); } else if (candidateCount > 1) { return chooseConfiguration(candidateConfigs); // return candidateConfigs.get(0); } return null; } protected String getModuleName(INode node) { if (node instanceof AExplicitFunctionDefinition) { return ((AExplicitFunctionDefinition) node).getLocation().getModule(); } if (node instanceof AExplicitOperationDefinition) { return ((AExplicitOperationDefinition) node).getLocation().getModule(); } return ""; } protected String getModuleNameLaunch(INode node) { String name = ""; if (node instanceof AExplicitFunctionDefinition) { name = ((AExplicitFunctionDefinition) node).getLocation().getModule(); if (!assistantFactory.createPAccessSpecifierAssistant().isStatic(((AExplicitFunctionDefinition) node).getAccess())) { name += "()"; } } if (node instanceof AExplicitOperationDefinition) { name = ((AExplicitOperationDefinition) node).getLocation().getModule(); if (!assistantFactory.createPAccessSpecifierAssistant().isStatic(((AExplicitOperationDefinition) node).getAccess())) { name += "()"; } } return name; } protected String getOperationName(INode node) { return AstNameUtil.getName(node); } protected boolean isStaticAccessRequired(INode node) { if (node instanceof AExplicitFunctionDefinition) { return assistantFactory.createPAccessSpecifierAssistant().isStatic(((AExplicitFunctionDefinition) node).getAccess()); } if (node instanceof AExplicitOperationDefinition) { return assistantFactory.createPAccessSpecifierAssistant().isStatic(((AExplicitOperationDefinition) node).getAccess()); } return true; } /** * Returns a configuration from the given collection of configurations that should be launched, or <code>null</code> * to cancel. Default implementation opens a selection dialog that allows the user to choose one of the specified * launch configurations. Returns the chosen configuration, or <code>null</code> if the user cancels. * * @param configList * list of configurations to choose from * @return configuration to launch or <code>null</code> to cancel */ protected ILaunchConfiguration chooseConfiguration( List<ILaunchConfiguration> configList) { IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation(); ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider); dialog.setElements(configList.toArray()); dialog.setTitle(getTypeSelectionTitle()); dialog.setMessage(LauncherMessages.VdmLaunchShortcut_2); dialog.setMultipleSelection(false); int result = dialog.open(); labelProvider.dispose(); if (result == Window.OK) { return (ILaunchConfiguration) dialog.getFirstResult(); } return null; } /** * Convenience method to return the active workbench window shell. * * @return active workbench window shell */ protected Shell getShell() { return VdmDebugPlugin.getActiveWorkbenchShell(); } /* * (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String) */ public void launch(IEditorPart editor, String mode) { // IEditorInput input = editor.getEditorInput(); // IJavaElement je = (IJavaElement) input.getAdapter(IJavaElement.class); // TODO get ISourceUnit from editor // IVdmSourceUnit je = null; // if (je != null) // { // searchAndLaunch(new Object[] { je }, mode, getTypeSelectionTitle(), getEditorEmptyMessage()); // } } public void launch(ISelection selection, String mode) { if (selection instanceof IStructuredSelection) { searchAndLaunch(((IStructuredSelection) selection).toArray(), mode, getTypeSelectionTitle(), getSelectionEmptyMessage()); } } /* * (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse.ui.IEditorPart) */ public IResource getLaunchableResource(IEditorPart editorpart) { return getLaunchableResource(editorpart.getEditorInput()); } /* * (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchableResource(org.eclipse.jface.viewers.ISelection) */ public IResource getLaunchableResource(ISelection selection) { if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() == 1) { Object element = ss.getFirstElement(); if (element instanceof IAdaptable) { return getLaunchableResource((IAdaptable) element); } } } return null; } /** * Returns the resource containing the Java element associated with the given adaptable, or <code>null</code>. * * @param adaptable * adaptable object * @return containing resource or <code>null</code> */ private IResource getLaunchableResource(IAdaptable adaptable) { // IJavaElement je = (IJavaElement) adaptable.getAdapter(IJavaElement.class); // if (je != null) { // return je.getResource(); // } // TODO return null; } /* * (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchConfigurations(org.eclipse.ui.IEditorPart) */ public ILaunchConfiguration[] getLaunchConfigurations(IEditorPart editorpart) { // let the framework resolve configurations based on resource mapping return null; } /* * (non-Javadoc) * @see org.eclipse.debug.ui.ILaunchShortcut2#getLaunchConfigurations(org.eclipse.jface.viewers.ISelection) */ public ILaunchConfiguration[] getLaunchConfigurations(ISelection selection) { // let the framework resolve configurations based on resource mapping return null; } protected IProject findProject(Object[] scope, IProgressService progressService) throws InterruptedException, CoreException { for (Object object : scope) { if (object instanceof IProject) { IProject project = (IProject) object; return project; } } return null; } protected ILaunchManager getLaunchManager() { return DebugPlugin.getDefault().getLaunchManager(); } protected INode[] findTypes(Object[] elements, IRunnableContext context) throws InterruptedException, CoreException { for (Object object : elements) { if (object instanceof IAdaptable) { IVdmProject vdmProject = (IVdmProject) ((IAdaptable) object).getAdapter(IVdmProject.class); if (vdmProject != null) { final IVdmModel model = vdmProject.getModel(); try { context.run(false, false, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { model.refresh(false, monitor); } }); } catch (InvocationTargetException e) { if (VdmDebugPlugin.DEBUG) { e.printStackTrace(); } } return filterTypes(model.getRootElementList().toArray(), context); } } } return null; } }