//
// This file is part of the Prose Development Tools for Eclipse package.
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is Prose Development Tools for Eclipse.
//
// The Initial Developer of the Original Code is Angela Nicoara. Portions
// created by Angela Nicoara are Copyright (C) 2006 Angela Nicoara.
// All Rights Reserved.
//
// Contributor(s):
// $Id: NewAspectWizardPage.java,v 1.1 2008/11/18 12:26:05 anicoara Exp $
// ==============================================================================
//
package ch.ethz.prose.eclipse.internal.wizards;
import java.util.ArrayList;
import org.eclipse.core.resources.IResource;
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.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.dom.TokenScanner;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ComboDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.wizards.NewContainerWizardPage;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
/**
* Wizard page to create a new Prose aspect.
*
* @author Angela Nicoara
* @author Johann Gyger
* @version $Id: NewAspectWizardPage.java,v 1.1 2008/11/18 12:26:05 anicoara Exp $
*/
public class NewAspectWizardPage extends NewContainerWizardPage {
/** MethodCut type */
public static final int METHOD_CUT_TYPE = 0;
/** MethodRedefineCut type */
public static final int METHOD_REDEFINE_CUT_TYPE = 1;
/** GetCut type */
public static final int GET_CUT_TYPE = 2;
/** SetCut type */
public static final int SET_CUT_TYPE = 3;
/** ThrowCut type */
public static final int THROW_CUT_TYPE = 4;
/** CatchCut type */
public static final int CATCH_CUT_TYPE = 5;
protected static final String PAGE_NAME = "NewAspectWizardPage"; //$NON-NLS-1$
protected static final String PACKAGE = PAGE_NAME + ".package"; //$NON-NLS-1$
protected static final String ASPECT_NAME = PAGE_NAME + ".aspect_name"; //$NON-NLS-1$
protected static final String CROSSCUT_NAME = PAGE_NAME + ".crosscut_name"; //$NON-NLS-1$
protected static final String CROSSCUT_TYPE = PAGE_NAME + ".crosscut_type"; //$NON-NLS-1$
protected static final String POINT_CUTTER = PAGE_NAME + ".point_cutter"; //$NON-NLS-1$
protected static final String[] PC_GENERIC = {"(none)", "NOT", "AND", "OR"};
protected static final String[] PC_ALL = {
"Within.method(\"methodNamePattern\")",
"Within.type(\"ClassNamePattern\")",
"Within.type(Object.class)",
"Within.subType(Object.class)",
"Within.superType(Object.class)",
"Within.packageTypes(\"package.name.pattern\")"
};
protected static final String[] PC_METHOD = {
"Executions.before()",
"Executions.after()"
};
protected static final String[] PC_FIELD = {
"Fields.named(\"fieldNamePattern\")",
"Fields.declaredInClass(\"ClassNamePattern\")",
"Fields.declaredInClass(Object.class)",
"Fields.declaredInSubClass(Object.class)",
"Fields.declaredInSuperClass(Object.class)",
};
protected static final String[] PC_EXCEPTION = {
"Exceptions.type(\"ExceptionNamePattern\")",
"Exceptions.type(Throwable.class)",
"Exceptions.subtypeOf(Throwable.class)",
"Exceptions.supertypeOf(Throwable.class)",
"Exceptions.withMessage(\"message\")",
};
protected static final String[] PC_GENERIC_ALL = concat(PC_GENERIC, PC_ALL);
protected StringButtonStatusDialogField fPackageDialogField;
protected StringDialogField fAspectNameDialogField;
protected ComboDialogField fCrosscutTypeDialogField;
protected ComboDialogField fPointCutterDialogField;
protected ComboDialogField fPointCutter1DialogField;
protected ComboDialogField fPointCutter2DialogField;
protected IStatus fPackageStatus = new StatusInfo();
protected IStatus fAspectNameStatus = new StatusInfo();
protected IStatus fCrosscutTypeStatus = new StatusInfo();
protected IStatus fPointCutterStatus = new StatusInfo();
protected IPackageFragment fPackageFragment;
protected IType fAspect;
protected NewCrosscutWizardPage fCrosscutPage;
/**
* Concatenate two String arrays.
*
* @param strings1 First array
* @param strings2 Second array
* @return Concatenated array
*/
protected static String[] concat(String[] strings1, String[] strings2) {
String[] result = new String[strings1.length + strings2.length];
System.arraycopy(strings1, 0, result, 0, strings1.length);
System.arraycopy(strings2, 0, result, strings1.length, strings2.length);
return result;
}
/**
* Create a new <code>NewAspectWizardPage</code>.
*/
public NewAspectWizardPage() {
super(PAGE_NAME);
setTitle("Prose Aspect");
setDescription("Create or extend a Prose aspect.");
fPackageDialogField = new StringButtonStatusDialogField(new IStringButtonAdapter() {
public void changeControlPressed(DialogField field) {
IPackageFragment pack= choosePackage();
if (pack != null) {
fPackageDialogField.setText(pack.getElementName());
}
}
});
fPackageDialogField.setDialogFieldListener(new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
fPackageStatus = updatePackage();
fAspectNameStatus = updateAspectName();
handleFieldChanged(PACKAGE);
}
});
fPackageDialogField.setLabelText("Package");
fPackageDialogField.setButtonLabel("Browse...");
fPackageDialogField.setStatusWidthHint("(default)");
fAspectNameDialogField = new StringDialogField();
fAspectNameDialogField.setDialogFieldListener(new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
fAspectNameStatus = updateAspectName();
handleFieldChanged(ASPECT_NAME);
}
});
fAspectNameDialogField.setLabelText("Aspect Name:");
fCrosscutTypeDialogField = new ComboDialogField(SWT.READ_ONLY);
fCrosscutTypeDialogField.setDialogFieldListener(new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
fCrosscutTypeStatus = updateCrosscutType();
handleFieldChanged(CROSSCUT_TYPE);
}
});
fCrosscutTypeDialogField.setLabelText("Crosscut Type:");
fCrosscutTypeDialogField.setItems(new String[] { "MethodCut", "MethodRedefineCut", "GetCut", "SetCut", "ThrowCut", "CatchCut"});
fPointCutterDialogField = new ComboDialogField(SWT.READ_ONLY);
fPointCutterDialogField.setDialogFieldListener(new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
fPointCutterStatus = updatePointCutter();
handleFieldChanged(POINT_CUTTER);
}
});
fPointCutterDialogField.setLabelText("Point Cutter:");
fPointCutter1DialogField = new ComboDialogField(SWT.READ_ONLY);
fPointCutter1DialogField.setLabelText("Specifier 1:");
fPointCutter1DialogField.setEnabled(false);
fPointCutter2DialogField = new ComboDialogField(SWT.READ_ONLY);
fPointCutter2DialogField.setLabelText("Specifier 2:");
fPointCutter2DialogField.setEnabled(false);
}
/**
* Initialize all fields provided by the page with a given selection.
*
* @param elem Java element used to initialize this page or <code>null</code>
* if no selection was available
*/
protected void initAspectPage(IJavaElement elem) {
if (elem != null) {
IPackageFragment pack = (IPackageFragment) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
if (pack != null) {
fPackageDialogField.setText(pack.getElementName());
}
IType aspect = null;
IType typeInCU = (IType) elem.getAncestor(IJavaElement.TYPE);
if (typeInCU != null) {
if (typeInCU.getCompilationUnit() != null) {
aspect = typeInCU;
}
} else {
ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
if (cu != null) {
aspect = cu.findPrimaryType();
}
}
if (aspect != null) {
fAspectNameDialogField.setText(aspect.getElementName());
}
}
}
/**
* The wizard owning this page is responsible for calling this method with
* the current selection. The selection is used to initialize the fields of
* the wizard page.
*
* @param selection Selection used to initialize the fields
*/
public void init(IStructuredSelection selection) {
IJavaElement jelem = getInitialJavaElement(selection);
initContainerPage(jelem);
initAspectPage(jelem);
doStatusUpdate();
}
/*
* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(java.lang.String)
*/
protected void handleFieldChanged(String fieldName) {
super.handleFieldChanged(fieldName);
if (fieldName == CONTAINER) {
fPackageStatus = updatePackage();
fAspectNameStatus = updateAspectName();
}
doStatusUpdate();
}
/**
* Collect the status objects and update the whole status.
*/
private void doStatusUpdate() {
IStatus[] status = new IStatus[] { fContainerStatus, fPackageStatus, fAspectNameStatus, fCrosscutTypeStatus,
fPointCutterStatus};
updateStatus(status);
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NONE);
int nColumns = 4;
GridLayout layout = new GridLayout();
layout.numColumns = nColumns;
composite.setLayout(layout);
createContainerControls(composite, nColumns);
createPackageControls(composite, nColumns);
createSeparator(composite, nColumns);
createAspectNameControls(composite, nColumns);
createCrosscutTypeControls(composite, nColumns);
createSeparator(composite, nColumns);
createPointCutterControls(composite, nColumns);
setControl(composite);
Dialog.applyDialogFont(composite);
}
protected void createPackageControls(Composite parent, int nColumns) {
fPackageDialogField.doFillIntoGrid(parent, nColumns);
Text text = fPackageDialogField.getTextControl(null);
LayoutUtil.setWidthHint(text, getMaxFieldWidth());
LayoutUtil.setHorizontalGrabbing(text);
}
protected void createAspectNameControls(Composite parent, int nColumns) {
fAspectNameDialogField.doFillIntoGrid(parent, nColumns - 1);
LayoutUtil.setWidthHint(fAspectNameDialogField.getTextControl(null), getMaxFieldWidth());
DialogField.createEmptySpace(parent);
}
protected void createCrosscutTypeControls(Composite parent, int nColumns) {
fCrosscutTypeDialogField.doFillIntoGrid(parent, nColumns - 1);
fCrosscutTypeDialogField.selectItem(0);
DialogField.createEmptySpace(parent);
}
protected void createPointCutterControls(Composite parent, int nColumns) {
fPointCutterDialogField.doFillIntoGrid(parent, nColumns - 1);
fPointCutterDialogField.selectItem(0);
DialogField.createEmptySpace(parent);
fPointCutter1DialogField.doFillIntoGrid(parent, nColumns - 1);
DialogField.createEmptySpace(parent);
fPointCutter2DialogField.doFillIntoGrid(parent, nColumns - 1);
DialogField.createEmptySpace(parent);
}
/**
* Create a separator line.
*
* @param composite Parent composite
* @param nColumns Number of columns to span (at least one)
*/
protected void createSeparator(Composite composite, int nColumns) {
(new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1));
}
/**
* @return Text of package input field
*/
public String getPackage() {
return fPackageDialogField.getText();
}
/**
* @return Text of aspect name input field
*/
public String getAspectName() {
return fAspectNameDialogField.getText();
}
/**
* @return Package fragment
*/
public IPackageFragment getPackageFragment() {
return fPackageFragment;
}
/**
* @return Aspect type, or <code>null</code>
*/
public IType getAspect() {
return fAspect;
}
/**
* @return Resource handle that corresponds to the compilation unit (aspect)
* that has been created or modified
*/
public IResource getModifiedResource() {
IPackageFragment pack = getPackageFragment();
return pack != null ? pack.getCompilationUnit(getAspectName() + ".java").getResource() : null; //$NON-NLS-1$
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
setFocus();
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.wizard.IWizardPage#getNextPage()
*/
public IWizardPage getNextPage() {
return fCrosscutPage;
}
/**
* Set the focus on the aspect name input field.
*/
protected void setFocus() {
fAspectNameDialogField.setFocus();
}
/**
* Update modification of package input field.
*
* @return Package validation status
*/
protected IStatus updatePackage() {
StatusInfo status = new StatusInfo();
fPackageDialogField.setStatus(getPackage().length() == 0 ? "(default)" : "");
fPackageDialogField.enableButton(getPackageFragmentRoot() != null);
String packName = getPackage();
if (packName.length() > 0) {
IStatus val = JavaConventions.validatePackageName(packName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError("Package name is not valid." + val.getMessage());
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning("This package name is discouraged. " + val.getMessage());
// continue
}
} else {
status.setWarning("The use of the default package is discouraged.");
}
IPackageFragmentRoot root = getPackageFragmentRoot();
if (root != null) {
if (root.getJavaProject().exists() && packName.length() > 0) {
try {
IPath rootPath = root.getPath();
IPath outputPath = root.getJavaProject().getOutputLocation();
if (rootPath.isPrefixOf(outputPath) && !rootPath.equals(outputPath)) {
// if the bin folder is inside of our root, don't allow
// to name a package
// like the bin folder
IPath packagePath = rootPath.append(packName.replace('.', '/'));
if (outputPath.isPrefixOf(packagePath)) {
status.setError("Package clashes with project output folder.");
return status;
}
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
// let pass
}
}
fPackageFragment = root.getPackageFragment(packName);
} else {
status.setError(""); //$NON-NLS-1$
}
return status;
}
/**
* Update modification of aspect name input field.
*
* @return Validation status
*/
protected IStatus updateAspectName() {
StatusInfo status = new StatusInfo();
fAspect = null;
String aspectName = getAspectName();
if (aspectName.length() == 0) {
status.setError("Aspect name is empty.");
return status;
}
if (aspectName.indexOf('.') != -1) {
status.setError("Aspect name must not be qualified.");
return status;
}
IStatus val = JavaConventions.validateJavaTypeName(aspectName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError("Aspect name is not valid. " + val.getMessage());
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning("Aspect name is discouraged. " + val.getMessage());
}
IPackageFragment pack = getPackageFragment();
if (pack != null) {
ICompilationUnit cu = pack.getCompilationUnit(aspectName + ".java"); //$NON-NLS-1$
IResource resource = cu.getResource();
if (resource.exists()) {
status.setWarning("Aspect already exits. Only the crosscut will be created.");
// TODO Check if aspect is a subclass of
// ch.ethz.prose.DefaultAspect.
}
fAspect = cu.findPrimaryType();
}
return status;
}
/**
* Update modification of crosscut type input field.
*
* @return Validation status
*/
protected IStatus updateCrosscutType() {
StatusInfo status = new StatusInfo();
NewAspectCreationWizard wizard = (NewAspectCreationWizard) getWizard();
String[] subItems = null;
if (wizard == null) return status;
switch (fCrosscutTypeDialogField.getSelectionIndex()) {
case 0:
fCrosscutPage = wizard.getMethodPage();
fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_METHOD));
subItems = concat(PC_ALL, PC_METHOD);
break;
case 1:
fCrosscutPage = wizard.getMethodRedefinePage();
fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_METHOD));
subItems = concat(PC_ALL, PC_METHOD);
break;
case 2:
case 3:
fCrosscutPage = wizard.getFieldPage();
fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_FIELD));
subItems = concat(PC_ALL, PC_FIELD);
break;
case 4:
case 5:
fCrosscutPage = wizard.getExceptionPage();
fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_EXCEPTION));
subItems = concat(PC_ALL, PC_EXCEPTION);
break;
default:
status.setError("Unknown crosscut type.");
fCrosscutPage = null;
return status;
}
fPointCutter1DialogField.setItems(subItems);
fPointCutter2DialogField.setItems(subItems);
fPointCutterDialogField.selectItem(0);
return status;
}
/**
* Update modification of point cutter input field.
*
* @return Validation status
*/
protected IStatus updatePointCutter() {
StatusInfo status = new StatusInfo();
switch (fPointCutterDialogField.getSelectionIndex()) {
case 0: // (none)
fPointCutter1DialogField.setEnabled(false);
fPointCutter2DialogField.setEnabled(false);
break;
case 1: // NOT
fPointCutter1DialogField.setEnabled(true);
fPointCutter1DialogField.selectItem(0);
fPointCutter2DialogField.setEnabled(false);
break;
case 2: // AND
case 3: // OR
fPointCutter1DialogField.setEnabled(true);
fPointCutter1DialogField.selectItem(0);
fPointCutter2DialogField.setEnabled(true);
fPointCutter2DialogField.selectItem(0);
break;
default:
fPointCutter1DialogField.setEnabled(false);
fPointCutter2DialogField.setEnabled(false);
break;
}
return status;
}
/**
* @return Package selected by the user in a separate dialog
*/
protected IPackageFragment choosePackage() {
IPackageFragmentRoot froot = getPackageFragmentRoot();
IJavaElement[] packages = null;
try {
if (froot != null && froot.exists()) {
packages = froot.getChildren();
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
}
if (packages == null) {
packages = new IJavaElement[0];
}
ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(
JavaElementLabelProvider.SHOW_DEFAULT));
dialog.setIgnoreCase(false);
dialog.setTitle("Package Selection");
dialog.setMessage("&Choose a folder:");
dialog.setEmptyListMessage("Cannot find packages to select.");
dialog.setElements(packages);
IPackageFragment pack = getPackageFragment();
if (pack != null) {
dialog.setInitialSelections(new Object[] { pack});
}
if (dialog.open() == Window.OK) {
return (IPackageFragment) dialog.getFirstResult();
}
return null;
}
/**
* Create the aspect using the entered field values.
*
* @param monitor Progress monitor
* @throws CoreException
* @throws InterruptedException
*/
public void createAspect(IProgressMonitor monitor) throws CoreException, InterruptedException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask("Creating aspect...", 10);
ICompilationUnit createdWorkingCopy = null;
try {
// Step 1: Process package fragment.
IPackageFragmentRoot root = getPackageFragmentRoot();
IPackageFragment pack = getPackageFragment();
if (pack == null) {
pack = root.getPackageFragment(""); //$NON-NLS-1$
}
if (!pack.exists()) {
String packName = pack.getElementName();
pack = root.createPackageFragment(packName, true, null);
}
monitor.worked(1);
// Step 2: Create aspect if not already existent.
boolean needsCommit = false;
String lineDelimiter = null;
String aspectName = getAspectName();
IType aspect = getAspect();
if (aspect == null) {
lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
ICompilationUnit parentCU = pack.createCompilationUnit(
aspectName + ".java", "", false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$ //$NON-NLS-2$
// create a working copy with a new owner
createdWorkingCopy = parentCU.getWorkingCopy(null);
// use the compiler template a first time to read the imports
String content = CodeGeneration.getCompilationUnitContent(createdWorkingCopy, null, "", lineDelimiter); //$NON-NLS-1$
if (content != null) {
createdWorkingCopy.getBuffer().setContents(content);
}
ImportsManager imports = new ImportsManager(createdWorkingCopy);
// add an import that will be removed again. Having this import solves 14661
imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), aspectName));
String typeContent = writeBasicAspect(imports, lineDelimiter);
String cuContent = constructCUContent(parentCU, typeContent, lineDelimiter);
createdWorkingCopy.getBuffer().setContents(cuContent);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
imports.create(false, new SubProgressMonitor(monitor, 1));
JavaModelUtil.reconcile(createdWorkingCopy);
aspect = createdWorkingCopy.getType(aspectName);
needsCommit = true;
}
if (monitor.isCanceled()) {
throw new InterruptedException();
}
ICompilationUnit cu = aspect.getCompilationUnit();
boolean needsSave = cu.isWorkingCopy();
ImportsManager imports = new ImportsManager(cu);
lineDelimiter = StubUtility.getLineDelimiterUsed(aspect);
// Write crosscut and format it
IField field = fCrosscutPage.writeCrosscut(aspect, fCrosscutTypeDialogField.getSelectionIndex(), imports,
new SubProgressMonitor(monitor, 2), lineDelimiter);
ISourceRange range = field.getSourceRange();
IBuffer buf = cu.getBuffer();
String originalContent = buf.getText(range.getOffset(), range.getLength());
String formattedContent = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, 1, null,
lineDelimiter, field.getJavaProject());
buf.replace(range.getOffset(), range.getLength(), formattedContent);
if (!cu.isWorkingCopy())
buf.save(null, false);
imports.create(needsSave, new SubProgressMonitor(monitor, 1));
removeUnusedImports(cu, needsSave);
if (needsCommit)
cu.commitWorkingCopy(false, new SubProgressMonitor(monitor, 1));
} finally {
if (createdWorkingCopy != null) {
createdWorkingCopy.discardWorkingCopy();
}
monitor.done();
}
}
/**
* Write the body of the pointCutter() method.
*
* @param source Buffer to append the source
* @param imports Imports manager
* @param nl Line delimiter
*/
public void writePointCutterBody(StringBuffer source, ImportsManager imports, String nl) {
source.append("return ");
switch (fPointCutterDialogField.getSelectionIndex()) {
case 0: // (none)
source.append("null;");
return;
case 1: // NOT
source.append("new NegatingPointCutter(");
source.append(fPointCutter1DialogField.getText());
source.append(");");
break;
case 2: // AND
source.append('(');
source.append(fPointCutter1DialogField.getText());
source.append(").AND(");
source.append(fPointCutter2DialogField.getText());
source.append(");");
break;
case 3: // OR
source.append('(');
source.append(fPointCutter1DialogField.getText());
source.append(").OR(");
source.append(fPointCutter2DialogField.getText());
source.append(");");
break;
default:
source.append(fPointCutterDialogField.getText());
source.append(';');
break;
}
imports.addImport("ch.ethz.prose.filter.*");
}
/**
* Write basic aspect class without any decorations like comments
*
* @param imports Imports manager
* @param lineDelimiter Line separator
* @return Source for this aspect
*/
protected String writeBasicAspect(ImportsManager imports, String lineDelimiter) {
imports.addImport("ch.ethz.prose.DefaultAspect");
StringBuffer buf = new StringBuffer();
buf.append("public class "); //$NON-NLS-1$
buf.append(getAspectName());
buf.append(" extends DefaultAspect {");
buf.append(lineDelimiter);
buf.append(lineDelimiter);
buf.append('}');
buf.append(lineDelimiter);
return buf.toString();
}
/**
* Uses the New Java file template from the code template page to generate a
* compilation unit with the given type content.
*
* @param cu The new created compilation unit
* @param typeContent The content of the type, including signature and type
* body.
* @param lineDelimiter The line delimiter to be used.
* @return String Returns the result of evaluating the new file template
* with the given type content.
* @throws CoreException
*/
protected String constructCUContent(ICompilationUnit cu, String typeContent, String lineDelimiter) throws CoreException {
String typeComment = getTypeComment(cu, lineDelimiter);
IPackageFragment pack = (IPackageFragment) cu.getParent();
String content = CodeGeneration.getCompilationUnitContent(cu, typeComment, typeContent, lineDelimiter);
if (content != null) {
ASTParser parser = ASTParser.newParser(AST.JLS2);
parser.setSource(content.toCharArray());
CompilationUnit unit = (CompilationUnit) parser.createAST(null);
if ((pack.isDefaultPackage() || unit.getPackage() != null) && !unit.types().isEmpty()) { return content; }
}
StringBuffer buf = new StringBuffer();
if (!pack.isDefaultPackage()) {
buf.append("package ").append(pack.getElementName()).append(';'); //$NON-NLS-1$
}
buf.append(lineDelimiter).append(lineDelimiter);
if (typeComment != null) {
buf.append(typeComment).append(lineDelimiter);
}
buf.append(typeContent);
return buf.toString();
}
/**
* Get new Java file template comment.
*
* @param parentCU Parent compilation unit
* @param lineDelimiter Line separator
* @return Content of the `type comment' template
*/
protected String getTypeComment(ICompilationUnit parentCU, String lineDelimiter) {
try {
StringBuffer aspectName = new StringBuffer();
aspectName.append(getAspectName());
String comment = CodeGeneration.getTypeComment(parentCU, aspectName.toString(), lineDelimiter);
if (comment != null && isValidComment(comment)) { return comment; }
} catch (CoreException e) {
JavaPlugin.log(e);
}
return null;
}
/**
* @param template Generated comment
* @return Is `template' a valid comment?
*/
protected boolean isValidComment(String template) {
IScanner scanner = ToolFactory.createScanner(true, false, false, false);
scanner.setSource(template.toCharArray());
try {
int next = scanner.getNextToken();
while (TokenScanner.isComment(next)) {
next = scanner.getNextToken();
}
return next == ITerminalSymbols.TokenNameEOF;
} catch (InvalidInputException e) {
}
return false;
}
/**
* Remove unused imports from compilation unit.
*
* @param cu Compilation unit that is processed
* @param needsSave Save needed?
* @throws CoreException
*/
protected void removeUnusedImports(ICompilationUnit cu, boolean needsSave) throws CoreException {
ASTParser parser = ASTParser.newParser(AST.JLS2);
parser.setSource(cu);
parser.setResolveBindings(true);
CompilationUnit root = (CompilationUnit) parser.createAST(null);
IProblem[] problems = root.getProblems();
ArrayList res = new ArrayList();
for (int i = 0; i < problems.length; i++) {
if (problems[i].getID() == IProblem.UnusedImport) {
String imp = problems[i].getArguments()[0];
res.add(imp);
}
}
if (!res.isEmpty()) {
ImportsManager imports = new ImportsManager(cu);
for (int i = 0; i < res.size(); i++) {
String curr = (String) res.get(i);
imports.removeImport(curr);
}
imports.create(needsSave, null);
}
}
}