/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package org.absmodels.abs.plugin.actions.runconfig; import static org.absmodels.abs.plugin.util.Constants.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.absmodels.abs.plugin.builder.AbsNature; import org.absmodels.abs.plugin.exceptions.AbsJobException; import org.absmodels.abs.plugin.exceptions.TypeCheckerException; import org.absmodels.abs.plugin.util.Constants; import org.absmodels.abs.plugin.util.UtilityFunctions; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import abs.common.WrongProgramArgumentException; import abs.frontend.analyser.SemanticConditionList; import abs.frontend.ast.Model; import abs.frontend.ast.Product; import abs.frontend.ast.ProductDecl; import abs.frontend.delta.DeltaModellingException; public abstract class AbstractTab extends AbstractLaunchConfigurationTab { protected Label projectLabel; protected Combo projectDropDown; protected Combo productDropDown; private String lastProjectName = ""; private String lastProd = ""; private boolean lastResult; /** * A Listener updating the LaunchConfigurationDialog of the given tab * when an event occurs. */ public static class TabListener implements Listener { final private AbstractTab tab; public TabListener(AbstractTab tab){ this.tab=tab; } @Override public void handleEvent(Event event) { tab.updateLaunchConfigurationDialog(); } } //---create methods------------------------ protected void createProjectDropDownMenu(TabListener myListener, Composite comp) { Group group = createGroup(comp, "ABS Project", 1, 1, GridData.FILL_HORIZONTAL); projectDropDown = new Combo(group, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); GridData gridData = new GridData(); gridData.widthHint = 200; projectDropDown.setLayoutData(gridData); projectDropDown.addListener(SWT.Selection, myListener); /* Refresh products everytime the project is changed */ projectDropDown.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { fillProductDropDownMenue(null); updateErrors(); } }); } /** * Don't recommend to start projects which have errors. * TODO: manipulating the error message here does not cooperate well with isValid(). */ protected boolean updateErrors() { boolean res = true; String projectName = getSelectedProjectName(); String prod = getSelectedProductName(); if (this.lastProjectName != null && this.lastProd != null && this.lastProjectName.equals(projectName) && this.lastProd.equals(prod)) { // use result from last time, so that we do not have to do a full typecheck // every time something changes in the run configuration dialog return lastResult; } if (projectName != null) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { AbsNature nat = UtilityFunctions.getAbsNature(project); assert nat != null; synchronized (nat.modelLock) { Model model = nat.getCompleteModel(); /* E.g. errors in the project */ if (model == null) return false; /* Check product if any */ // work on a copy: model = model.parseTreeCopy(); if (prod != null) { model.flattenForProduct(prod); /* Type check again */ model.flushCache(); // #335, see IncrementalModelBuilder#flushAll() } SemanticConditionList errs = model.getErrors(); // TODO: check for warnings also if (errs != null && errs.containsErrors()) { createMarkers(nat, errs); throw new AbsJobException(new TypeCheckerException(errs)); } errs = model.typeCheck(); // TODO: check for warnings also if (errs != null && errs.containsErrors()) { createMarkers(nat, errs); throw new AbsJobException(new TypeCheckerException(errs)); } } setErrorMessage(null); } catch (AbsJobException e) { setErrorMessage(e.getMessage()); res = false; } catch (WrongProgramArgumentException e) { setErrorMessage(e.getMessage()); res = false; } catch (DeltaModellingException e) { setErrorMessage(e.getMessage()); res = false; } getLaunchConfigurationDialog().updateMessage(); } // cache the result lastProd = prod; lastProjectName = projectName; lastResult = res; return res; } private void createMarkers(AbsNature nat, SemanticConditionList errs) { try { nat.createMarkers(errs); } catch (CoreException e) { // ignore } } @Override public boolean isValid(ILaunchConfiguration launchConfig) { boolean res = super.isValid(launchConfig); res &= updateErrors(); return res; } /** * Must be called after createProjectDropDownMenu, since we need to figure out the selected project. * @author stolz */ protected void createProductDropDownMenu(TabListener myListener, Composite comp) { Group group = createGroup(comp, "ABS Product", 1, 1, GridData.FILL_HORIZONTAL); productDropDown = new Combo(group, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); GridData gridData = new GridData(); gridData.widthHint = 200; productDropDown.setLayoutData(gridData); productDropDown.addListener(SWT.Selection, myListener); } protected static Group createGroup(Composite parent, String text, int columns, int hspan, int fill) { Group g = new Group(parent, SWT.NONE); g.setLayout(new GridLayout(columns, false)); g.setText(text); g.setFont(parent.getFont()); GridData gd = new GridData(fill); gd.horizontalSpan = hspan; g.setLayoutData(gd); return g; } //---set methods---------------------------------- protected void initProject(ILaunchConfiguration configuration) throws CoreException { String name = configuration.getAttribute(RUNCONFIG_PROJECT_NAME_ATTRIBUTE, getDefaultProjectName()); fillProjectDropDownMenue(name); name = configuration.getAttribute(RUNCONFIG_PRODUCT_NAME_ATTRIBUTE, (String)null); fillProductDropDownMenue(name); updateErrors(); } protected void fillProjectDropDownMenue(String name) { List<String> projectNames = getProjectNames(); int selectedProjectName = 0; projectDropDown.removeAll(); for (int i = 0; i < projectNames.size() ; i++) { String projectName = projectNames.get(i); if(projectName.equals(name)){ selectedProjectName = i; } projectDropDown.add(projectName); } projectDropDown.select(selectedProjectName); } /** * Lists all products in the current project's module, incl. a "<base>" product if * no particular product is selected. * @param preSelected The product that should be preselected, or null for <base>. */ protected void fillProductDropDownMenue(String preSelected) { productDropDown.removeAll(); productDropDown.add("<base>"); IProject proj = getSelectedProject(); if (proj == null) { return; } AbsNature n = UtilityFunctions.getAbsNature(proj); Model m = n.getCompleteModel(); if (m == null) return; Collection<ProductDecl> prods = m.getProductDecls(); if (prods == null) return; int i = 1; /* base comes first */ int selected = 0; for (ProductDecl p : prods) { final String name = p.getName(); productDropDown.add(name); if (name.equals(preSelected)) { selected = i; } i++; } productDropDown.select(selected); } protected IProject getSelectedProject() { final int idx = projectDropDown.getSelectionIndex(); if (idx == -1) return null; String projN = getProjectNames().get(idx); IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(projN); return proj; } //---get and help functions---------------------------------- protected String getDefaultProjectName() { List<String> names = getProjectNames(); if (names!=null && !names.isEmpty()){ return names.get(0); } else { return null; } } protected ArrayList<String> getProjectNames() { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); ArrayList<String> projectNames = new ArrayList<String>(); for (int i = 0; i < projects.length; i++) { try { if(projects[i].isAccessible() && projects[i].hasNature(Constants.NATURE_ID)){ projectNames.add(projects[i].getName()); } } catch (CoreException e) { //just skip the project, if an error occurs (see hasNature for error description) } } return projectNames; } protected String getSelectedProjectName() { return projectDropDown.getItem(projectDropDown.getSelectionIndex()); } /** * @return the product name, or null if the base product is selected. */ protected String getSelectedProductName() { final int index = productDropDown.getSelectionIndex(); if (index <= 0) /* base is at index 0 */ return null; return productDropDown.getItem(index); } }