blob: 48daf2f3826aa8204f0313a2e048b81ab587ff83 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.junit.wizards;
import java.lang.reflect.InvocationTargetException;
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.core.resources.IFile;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.junit.wizards.NewTestSuiteWizardPage;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
import org.eclipse.jdt.internal.junit.util.CheckedTableSelectionDialog;
import org.eclipse.jdt.internal.junit.util.ExceptionHandler;
import org.eclipse.jdt.internal.junit.util.JUnitStatus;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.Resources;
/**
* An object contribution action that updates existing AllTests classes.
*/
public class UpdateTestSuite implements IObjectActionDelegate {
private Shell fShell;
private IPackageFragment fPack;
private ICompilationUnit fTestSuite;
private IMethod fSuiteMethod;
private static boolean fEmptySelectionAllowed= false;
private Object[] fSelectedTestCases;
private class UpdateAllTestsValidator implements ISelectionStatusValidator {
/*
* @see ISelectionValidator#validate(Object[])
*/
public IStatus validate(Object[] selection) {
int count= 0;
for (int i= 0; i < selection.length; i++) {
if (selection[i] instanceof IType) {
count++;
}
}
if (count == 0 && !fEmptySelectionAllowed) {
return new JUnitStatus(IStatus.ERROR, ""); //$NON-NLS-1$
}
IStatus recursiveInclusionStatus= checkRecursiveSuiteInclusion(selection);
if (recursiveInclusionStatus != null && ! recursiveInclusionStatus.isOK())
return recursiveInclusionStatus;
String message;
if (count == 1) {
message= Messages.format(WizardMessages.UpdateAllTests_selected_methods_label_one, new Integer(count));
} else {
message= Messages.format(WizardMessages.UpdateAllTests_selected_methods_label_many, new Integer(count));
}
return new JUnitStatus(IStatus.INFO, message);
}
private IStatus checkRecursiveSuiteInclusion(Object[] selection){
IType suiteClass= fSuiteMethod.getDeclaringType();
for (int i= 0; i < selection.length; i++) {
if (selection[i] instanceof IType){
if (((IType)selection[i]).equals(suiteClass)){
return new JUnitStatus(IStatus.WARNING, WizardMessages.UpdateTestSuite_infinite_recursion);
}
}
}
return null;
}
}
public UpdateTestSuite() {
super();
}
/*
* @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
*/
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
}
/*
* @see IActionDelegate#run(IAction)
*/
public void run(IAction action) {
ILabelProvider lprovider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
IStructuredContentProvider cprovider= new SuiteClassesContentProvider();
/* find TestClasses already in Test Suite */
IType testSuiteType= fTestSuite.findPrimaryType();
fSuiteMethod= testSuiteType.getMethod("suite", new String[] {}); //$NON-NLS-1$
if (fSuiteMethod.exists()) {
try {
ISourceRange range= fSuiteMethod.getSourceRange();
IBuffer buf= fTestSuite.getBuffer();
String originalContent= buf.getText(range.getOffset(), range.getLength());
buf.close();
if (getTestSuiteClassListRange(originalContent) != null) {
CheckedTableSelectionDialog dialog= new CheckedTableSelectionDialog(fShell, lprovider, cprovider);
dialog.setValidator(new UpdateAllTestsValidator());
dialog.setTitle(WizardMessages.UpdateAllTests_title);
dialog.setMessage(WizardMessages.UpdateAllTests_message);
dialog.setInitialSelections(cprovider.getElements(fPack));
dialog.setSize(60, 25);
dialog.setInput(fPack);
if (dialog.open() == Window.OK) {
fSelectedTestCases= dialog.getResult();
try {
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(getRunnable());
} catch (Exception e) {
JUnitPlugin.log(e);
}
}
} else {
cannotUpdateSuiteError();
}
} catch (JavaModelException e) {
JUnitPlugin.log(e);
}
} else {
noSuiteError();
}
}
/*
* @see IActionDelegate#selectionChanged(IAction, ISelection)
*/
public void selectionChanged(IAction action, ISelection selection) {
fShell= JUnitPlugin.getActiveWorkbenchShell();
if (selection instanceof IStructuredSelection) {
Object testSuiteObj= ((IStructuredSelection) selection).getFirstElement();
if (testSuiteObj != null && testSuiteObj instanceof ICompilationUnit) {
fTestSuite= (ICompilationUnit) testSuiteObj;
IJavaElement packIJE= fTestSuite.getParent();
if (packIJE instanceof IPackageFragment) {
fPack= (IPackageFragment) packIJE;
}
}
}
}
private void updateTestCasesInSuite(IProgressMonitor monitor) {
try {
monitor.beginTask(WizardMessages.UpdateAllTests_beginTask, 5);
if (! checkValidateEditStatus(fTestSuite, fShell))
return;
ISourceRange range= fSuiteMethod.getSourceRange();
IDocument fullSource= new Document(fTestSuite.getBuffer().getContents());
String originalContent= fullSource.get(range.getOffset(), range.getLength());
StringBuffer source= new StringBuffer(originalContent);
TestSuiteClassListRange classRange = getTestSuiteClassListRange(source.toString());
if (classRange != null) {
monitor.worked(1);
// String updatableCode= source.substring(start,end+NewTestSuiteCreationWizardPage.endMarker.length());
source.replace(classRange.getStart(), classRange.getEnd(), getUpdatableString(fSelectedTestCases));
fullSource.replace(range.getOffset(), range.getLength(), source.toString());
monitor.worked(1);
String formattedContent= JUnitStubUtility.formatCompilationUnit(fTestSuite.getJavaProject(), fullSource.get(), fTestSuite.findRecommendedLineSeparator());
//buf.replace(range.getOffset(), range.getLength(), formattedContent);
IBuffer buf= fTestSuite.getBuffer();
buf.replace(0, buf.getLength(), formattedContent);
monitor.worked(1);
fTestSuite.save(new SubProgressMonitor(monitor, 1), true);
monitor.worked(1);
}
} catch (JavaModelException e) {
ExceptionHandler.handle(e, fShell, WizardMessages.UpdateTestSuite_update, WizardMessages.UpdateTestSuite_error);
} catch (BadLocationException e) {
Assert.isTrue(false, "Should never happen"); //$NON-NLS-1$
} finally{
monitor.done();
}
}
public static TestSuiteClassListRange getTestSuiteClassListRange(String source) {
int start= source.indexOf(NewTestSuiteWizardPage.NON_COMMENT_START_MARKER);
if (start <= -1)
return null;
start = source.lastIndexOf(NewTestSuiteWizardPage.COMMENT_START, start);
if (start <= -1)
return null;
int end= source.indexOf(NewTestSuiteWizardPage.NON_COMMENT_END_MARKER, start);
if (end <= -1)
return null;
end += NewTestSuiteWizardPage.NON_COMMENT_END_MARKER.length();
return new TestSuiteClassListRange(start, end);
}
/*
* Returns the new code to be included in a new suite() or which replaces old code in an existing suite().
*/
public static String getUpdatableString(Object[] selectedClasses) {
StringBuffer suite= new StringBuffer();
suite.append(NewTestSuiteWizardPage.START_MARKER+"\n"); //$NON-NLS-1$
for (int i= 0; i < selectedClasses.length; i++) {
if (selectedClasses[i] instanceof IType) {
IType testType= (IType) selectedClasses[i];
IMethod suiteMethod= testType.getMethod("suite", new String[] {}); //$NON-NLS-1$
if (!suiteMethod.exists()) {
suite.append("suite.addTestSuite("+testType.getElementName()+".class);"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
suite.append("suite.addTest("+testType.getElementName()+".suite());"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
suite.append("\n"+NewTestSuiteWizardPage.END_MARKER); //$NON-NLS-1$
return suite.toString();
}
public static boolean checkValidateEditStatus(ICompilationUnit testSuiteCu, Shell shell){
IStatus status= validateModifiesFiles(getTestSuiteFile(testSuiteCu));
if (status.isOK())
return true;
ErrorDialog.openError(shell, WizardMessages.UpdateTestSuite_update, WizardMessages.UpdateTestSuite_could_not_update, status);
return false;
}
private static IFile getTestSuiteFile(ICompilationUnit testSuiteCu) {
return (IFile) testSuiteCu.getResource();
}
private static IStatus validateModifiesFiles(IFile fileToModify) {
IFile[] filesToModify= {fileToModify};
IStatus status= Resources.checkInSync(filesToModify);
if (! status.isOK())
return status;
status= Resources.makeCommittable(filesToModify, null);
if (! status.isOK())
return status;
return new JUnitStatus();
}
public IRunnableWithProgress getRunnable() {
return new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
updateTestCasesInSuite(monitor);
}
};
}
private void cannotUpdateSuiteError() {
MessageDialog.openError(fShell, WizardMessages.UpdateAllTests_cannotUpdate_errorDialog_title,
Messages.format(WizardMessages.UpdateAllTests_cannotUpdate_errorDialog_message, new String[] {NewTestSuiteWizardPage.START_MARKER, NewTestSuiteWizardPage.END_MARKER}));
}
private void noSuiteError() {
MessageDialog.openError(fShell, WizardMessages.UpdateAllTests_cannotFind_errorDialog_title, WizardMessages.UpdateAllTests_cannotFind_errorDialog_message);
}
}