blob: 25411489323676e445a409f5ac86f8753c7f987c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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
* Sebastian Davids, sdavids@gmx.de - bug 38507
* Sebastian Davids, sdavids@gmx.de - 113998 [JUnit] New Test Case Wizard: Class Under Test Dialog -- allow Enums
*******************************************************************************/
package org.eclipse.jdt.junit.wizards;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.buildpath.BuildPathSupport;
import org.eclipse.jdt.internal.junit.ui.IJUnitHelpContextIds;
import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
import org.eclipse.jdt.internal.junit.util.JUnitStatus;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.LayoutUtil;
import org.eclipse.jdt.internal.junit.util.TestSearchEngine;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility.GenStubSettings;
import org.eclipse.jdt.internal.junit.wizards.MethodStubsSelectionButtonGroup;
import org.eclipse.jdt.internal.junit.wizards.WizardMessages;
/**
* The class <code>NewTestCaseWizardPageOne</code> contains controls and validation routines
* for the first page of the 'New JUnit TestCase Wizard'.
*
* Clients can use the page as-is and add it to their own wizard, or extend it to modify
* validation or add and remove controls.
*
* @since 3.1
*/
public class NewTestCaseWizardPageOne extends NewTypeWizardPage {
private final static String PAGE_NAME= "NewTestCaseCreationWizardPage"; //$NON-NLS-1$
/** Field ID of the class under test field. */
public final static String CLASS_UNDER_TEST= PAGE_NAME + ".classundertest"; //$NON-NLS-1$
/**
* Field ID of the Junit4 toggle
* @since 3.2
*/
public final static String JUNIT4TOGGLE= PAGE_NAME + ".junit4toggle"; //$NON-NLS-1$
private static final String COMPLIANCE_PAGE_ID= "org.eclipse.jdt.ui.propertyPages.CompliancePreferencePage"; //$NON-NLS-1$
private static final String BUILD_PATH_PAGE_ID= "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$
private static final Object BUILD_PATH_KEY_ADD_ENTRY= "add_classpath_entry"; //$NON-NLS-1$
private static final Object BUILD_PATH_BLOCK= "block_until_buildpath_applied"; //$NON-NLS-1$
private static final String KEY_NO_LINK= "PropertyAndPreferencePage.nolink"; //$NON-NLS-1$
private final static String QUESTION_MARK_TAG= "Q"; //$NON-NLS-1$
private final static String OF_TAG= "Of"; //$NON-NLS-1$
private final static String TEST_SUFFIX= "Test"; //$NON-NLS-1$
private final static String PREFIX= "test"; //$NON-NLS-1$
private final static String STORE_SETUP= PAGE_NAME + ".USE_SETUP"; //$NON-NLS-1$
private final static String STORE_TEARDOWN= PAGE_NAME + ".USE_TEARDOWN"; //$NON-NLS-1$
private final static String STORE_SETUP_CLASS= PAGE_NAME + ".USE_SETUPCLASS"; //$NON-NLS-1$
private final static String STORE_TEARDOWN_CLASS= PAGE_NAME + ".USE_TEARDOWNCLASS"; //$NON-NLS-1$
private final static String STORE_CONSTRUCTOR= PAGE_NAME + ".USE_CONSTRUCTOR"; //$NON-NLS-1$
private final static int IDX_SETUP_CLASS= 0;
private final static int IDX_TEARDOWN_CLASS= 1;
private final static int IDX_SETUP= 2;
private final static int IDX_TEARDOWN= 3;
private final static int IDX_CONSTRUCTOR= 4;
private NewTestCaseWizardPageTwo fPage2;
private MethodStubsSelectionButtonGroup fMethodStubsButtons;
private String fClassUnderTestText; // model
private IType fClassUnderTest; // resolved model, can be null
private Text fClassUnderTestControl; // control
private IStatus fClassUnderTestStatus; // status
private Button fClassUnderTestButton;
private JavaTypeCompletionProcessor fClassToTestCompletionProcessor;
private Button fJUnit4Toggle;
private boolean fIsJunit4;
private IStatus fJunit4Status; // status
private boolean fIsJunit4Enabled;
private Link fLink;
private Label fImage;
/**
* Creates a new <code>NewTestCaseCreationWizardPage</code>.
* @param page2 The second page
*
* @since 3.1
*/
public NewTestCaseWizardPageOne(NewTestCaseWizardPageTwo page2) {
super(true, PAGE_NAME);
fPage2= page2;
setTitle(WizardMessages.NewTestCaseWizardPageOne_title);
setDescription(WizardMessages.NewTestCaseWizardPageOne_description);
String[] buttonNames= new String[] {
/* IDX_SETUP_CLASS */ WizardMessages.NewTestCaseWizardPageOne_methodStub_setUpBeforeClass,
/* IDX_TEARDOWN_CLASS */ WizardMessages.NewTestCaseWizardPageOne_methodStub_tearDownAfterClass,
/* IDX_SETUP */ WizardMessages.NewTestCaseWizardPageOne_methodStub_setUp,
/* IDX_TEARDOWN */ WizardMessages.NewTestCaseWizardPageOne_methodStub_tearDown,
/* IDX_CONSTRUCTOR */ WizardMessages.NewTestCaseWizardPageOne_methodStub_constructor
};
enableCommentControl(true);
fMethodStubsButtons= new MethodStubsSelectionButtonGroup(SWT.CHECK, buttonNames, 2);
fMethodStubsButtons.setLabelText(WizardMessages.NewTestCaseWizardPageOne_method_Stub_label);
fClassToTestCompletionProcessor= new JavaTypeCompletionProcessor(false, false);
fClassUnderTestStatus= new JUnitStatus();
fClassUnderTestText= ""; //$NON-NLS-1$
fJunit4Status= new JUnitStatus();
fIsJunit4= false;
}
/**
* Initialized the page with the current selection
* @param selection The selection
*/
public void init(IStructuredSelection selection) {
IJavaElement element= getInitialJavaElement(selection);
initContainerPage(element);
initTypePage(element);
// put default class to test
if (element != null) {
IType classToTest= null;
// evaluate the enclosing type
IType typeInCompUnit= (IType) element.getAncestor(IJavaElement.TYPE);
if (typeInCompUnit != null) {
if (typeInCompUnit.getCompilationUnit() != null) {
classToTest= typeInCompUnit;
}
} else {
ICompilationUnit cu= (ICompilationUnit) element.getAncestor(IJavaElement.COMPILATION_UNIT);
if (cu != null)
classToTest= cu.findPrimaryType();
else {
if (element instanceof IClassFile) {
try {
IClassFile cf= (IClassFile) element;
if (cf.isStructureKnown())
classToTest= cf.getType();
} catch(JavaModelException e) {
JUnitPlugin.log(e);
}
}
}
}
if (classToTest != null) {
try {
if (!TestSearchEngine.isTestImplementor(classToTest)) {
setClassUnderTest(classToTest.getFullyQualifiedName('.'));
}
} catch (JavaModelException e) {
JUnitPlugin.log(e);
}
}
}
restoreWidgetValues();
boolean isJunit4= false;
if (element != null && element.getElementType() != IJavaElement.JAVA_MODEL) {
IJavaProject project= element.getJavaProject();
try {
isJunit4= project.findType(JUnitPlugin.JUNIT4_ANNOTATION_NAME) != null;
} catch (JavaModelException e) {
// ignore
}
}
setJUnit4(isJunit4, true);
updateStatus(getStatusList());
}
private IStatus junit4Changed() {
JUnitStatus status= new JUnitStatus();
return status;
}
/**
* Specifies if the test should be created as JUnit 4 test.
* @param isJUnit4 If set, a Junit 4 test will be created
* @param isEnabled if <code>true</code> the modifier fields are
* editable; otherwise they are read-only
*
* @since 3.2
*/
public void setJUnit4(boolean isJUnit4, boolean isEnabled) {
fIsJunit4Enabled= isEnabled;
if (fJUnit4Toggle != null && !fJUnit4Toggle.isDisposed()) {
fJUnit4Toggle.setSelection(isJUnit4);
fJUnit4Toggle.setEnabled(isEnabled);
}
internalSetJUnit4(isJUnit4);
}
/**
* Returns <code>true</code> if the test should be created as Junit 4 test
* @return returns <code>true</code> if the test should be created as Junit 4 test
*
* @since 3.2
*/
public boolean isJUnit4() {
return fIsJunit4;
}
private void internalSetJUnit4(boolean isJUnit4) {
fIsJunit4= isJUnit4;
fJunit4Status= junit4Changed();
if (fIsJunit4) {
setSuperClass("java.lang.Object", false); //$NON-NLS-1$
} else {
setSuperClass(JUnitPlugin.TEST_SUPERCLASS_NAME, true);
}
handleFieldChanged(JUNIT4TOGGLE);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
*/
protected void handleFieldChanged(String fieldName) {
super.handleFieldChanged(fieldName);
if (fieldName.equals(CONTAINER)) {
fClassUnderTestStatus= classUnderTestChanged();
if (fClassUnderTestButton != null && !fClassUnderTestButton.isDisposed()) {
fClassUnderTestButton.setEnabled(getPackageFragmentRoot() != null);
}
fJunit4Status= junit4Changed();
updateBuildPathMessage();
} else if (fieldName.equals(JUNIT4TOGGLE)) {
updateBuildPathMessage();
fMethodStubsButtons.setEnabled(IDX_SETUP_CLASS, isJUnit4());
fMethodStubsButtons.setEnabled(IDX_TEARDOWN_CLASS, isJUnit4());
fMethodStubsButtons.setEnabled(IDX_CONSTRUCTOR, !isJUnit4());
}
updateStatus(getStatusList());
}
/**
* Returns all status to be consider for the validation. Clients can override.
* @return The list of status to consider for the validation.
*/
protected IStatus[] getStatusList() {
return new IStatus[] {
fContainerStatus,
fPackageStatus,
fTypeNameStatus,
fClassUnderTestStatus,
fModifierStatus,
fSuperClassStatus,
fJunit4Status
};
}
/* (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);
createJUnit4Controls(composite, nColumns);
createContainerControls(composite, nColumns);
createPackageControls(composite, nColumns);
createSeparator(composite, nColumns);
createTypeNameControls(composite, nColumns);
createSuperClassControls(composite, nColumns);
createMethodStubSelectionControls(composite, nColumns);
createCommentControls(composite, nColumns);
createSeparator(composite, nColumns);
createClassUnderTestControls(composite, nColumns);
createBuildPathConfigureControls(composite, nColumns);
setControl(composite);
//set default and focus
String classUnderTest= getClassUnderTestText();
if (classUnderTest.length() > 0) {
setTypeName(Signature.getSimpleName(classUnderTest)+TEST_SUFFIX, true);
}
Dialog.applyDialogFont(composite);
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJUnitHelpContextIds.NEW_TESTCASE_WIZARD_PAGE);
setFocus();
}
/**
* Creates the controls for the method stub selection buttons. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createMethodStubSelectionControls(Composite composite, int nColumns) {
LayoutUtil.setHorizontalSpan(fMethodStubsButtons.getLabelControl(composite), nColumns);
LayoutUtil.createEmptySpace(composite, 1);
LayoutUtil.setHorizontalSpan(fMethodStubsButtons.getSelectionButtonsGroup(composite), nColumns - 1);
}
/**
* Creates the controls for the 'class under test' field. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createClassUnderTestControls(Composite composite, int nColumns) {
Label classUnderTestLabel= new Label(composite, SWT.LEFT | SWT.WRAP);
classUnderTestLabel.setFont(composite.getFont());
classUnderTestLabel.setText(WizardMessages.NewTestCaseWizardPageOne_class_to_test_label);
classUnderTestLabel.setLayoutData(new GridData());
fClassUnderTestControl= new Text(composite, SWT.SINGLE | SWT.BORDER);
fClassUnderTestControl.setEnabled(true);
fClassUnderTestControl.setFont(composite.getFont());
fClassUnderTestControl.setText(fClassUnderTestText);
fClassUnderTestControl.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
internalSetClassUnderText(((Text) e.widget).getText());
}
});
GridData gd= new GridData();
gd.horizontalAlignment= GridData.FILL;
gd.grabExcessHorizontalSpace= true;
gd.horizontalSpan= nColumns - 2;
fClassUnderTestControl.setLayoutData(gd);
fClassUnderTestButton= new Button(composite, SWT.PUSH);
fClassUnderTestButton.setText(WizardMessages.NewTestCaseWizardPageOne_class_to_test_browse);
fClassUnderTestButton.setEnabled(true);
fClassUnderTestButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
classToTestButtonPressed();
}
public void widgetSelected(SelectionEvent e) {
classToTestButtonPressed();
}
});
gd= new GridData();
gd.horizontalAlignment= GridData.FILL;
gd.grabExcessHorizontalSpace= false;
gd.horizontalSpan= 1;
gd.widthHint = LayoutUtil.getButtonWidthHint(fClassUnderTestButton);
fClassUnderTestButton.setLayoutData(gd);
ControlContentAssistHelper.createTextContentAssistant(fClassUnderTestControl, fClassToTestCompletionProcessor);
}
/**
* Creates the controls for the JUnit 4 toggle control. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*
* @since 3.2
*/
protected void createJUnit4Controls(Composite composite, int nColumns) {
Composite inner= new Composite(composite, SWT.NONE);
inner.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, nColumns, 1));
GridLayout layout= new GridLayout(2, false);
layout.marginHeight= 0;
layout.marginWidth= 0;
inner.setLayout(layout);
SelectionAdapter listener= new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
boolean isSelected= ((Button) e.widget).getSelection();
internalSetJUnit4(isSelected);
}
};
Button junti3Toggle= new Button(inner, SWT.RADIO);
junti3Toggle.setText(WizardMessages.NewTestCaseWizardPageOne_junit3_radio_label);
junti3Toggle.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, 1, 1));
junti3Toggle.setSelection(!fIsJunit4);
junti3Toggle.setEnabled(fIsJunit4Enabled);
fJUnit4Toggle= new Button(inner, SWT.RADIO);
fJUnit4Toggle.setText(WizardMessages.NewTestCaseWizardPageOne_junit4_radio_label);
fJUnit4Toggle.setSelection(fIsJunit4);
fJUnit4Toggle.setEnabled(fIsJunit4Enabled);
fJUnit4Toggle.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, 1, 1));
fJUnit4Toggle.addSelectionListener(listener);
}
/**
* Creates the controls for the JUnit 4 toggle control. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*
* @since 3.2
*/
protected void createBuildPathConfigureControls(Composite composite, int nColumns) {
Composite inner= new Composite(composite, SWT.NONE);
inner.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, nColumns, 1));
GridLayout layout= new GridLayout(2, false);
layout.marginWidth= 0;
layout.marginHeight= 0;
inner.setLayout(layout);
fImage= new Label(inner, SWT.NONE);
fImage.setImage(JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING));
fImage.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false, 1, 1));
fLink= new Link(inner, SWT.WRAP);
fLink.setText("\n\n"); //$NON-NLS-1$
fLink.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
performBuildpathConfiguration(e.text);
}
});
GridData gd= new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1);
gd.widthHint= convertWidthInCharsToPixels(60);
fLink.setLayoutData(gd);
updateBuildPathMessage();
}
private void performBuildpathConfiguration(Object data) {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return; // should not happen. Link shouldn't be visible
}
IJavaProject javaProject= root.getJavaProject();
if ("a3".equals(data)) { // add and configure JUnit 3 //$NON-NLS-1$
String id= BUILD_PATH_PAGE_ID;
Map input= new HashMap();
IClasspathEntry newEntry= BuildPathSupport.getJUnit3ClasspathEntry();
input.put(BUILD_PATH_KEY_ADD_ENTRY, newEntry);
input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
} else if ("a4".equals(data)) { // add and configure JUnit 4 //$NON-NLS-1$
String id= BUILD_PATH_PAGE_ID;
Map input= new HashMap();
IClasspathEntry newEntry= BuildPathSupport.getJUnit4ClasspathEntry();
input.put(BUILD_PATH_KEY_ADD_ENTRY, newEntry);
input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
} else if ("b".equals(data)) { // open build path //$NON-NLS-1$
String id= BUILD_PATH_PAGE_ID;
Map input= new HashMap();
input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, id, new String[] { id }, input).open();
} else if ("c".equals(data)) { // open compliance //$NON-NLS-1$
String buildPath= BUILD_PATH_PAGE_ID;
String complianceId= COMPLIANCE_PAGE_ID;
Map input= new HashMap();
input.put(BUILD_PATH_BLOCK, Boolean.TRUE);
input.put(KEY_NO_LINK, Boolean.TRUE);
PreferencesUtil.createPropertyDialogOn(getShell(), javaProject, complianceId, new String[] { buildPath, complianceId }, data).open();
}
updateBuildPathMessage();
}
private void updateBuildPathMessage() {
if (fLink == null || fLink.isDisposed()) {
return;
}
String message= null;
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root != null) {
try {
IJavaProject project= root.getJavaProject();
if (isJUnit4()) {
if (!JUnitStubUtility.is50OrHigher(project)) {
message= WizardMessages.NewTestCaseWizardPageOne_linkedtext_java5required;
} else if (project.findType(JUnitPlugin.JUNIT4_ANNOTATION_NAME) == null) {
message= Messages.format(WizardMessages.NewTestCaseWizardPageOne_linkedtext_junit4_notonbuildpath, project.getElementName());
}
} else {
if (project.findType(JUnitPlugin.TEST_SUPERCLASS_NAME) == null) {
message= Messages.format(WizardMessages.NewTestCaseWizardPageOne_linkedtext_junit3_notonbuildpath, project.getElementName());
}
}
} catch (JavaModelException e) {
}
}
fLink.setVisible(message != null);
fImage.setVisible(message != null);
if (message != null) {
fLink.setText(message);
}
}
private void classToTestButtonPressed() {
IType type= chooseClassToTestType();
if (type != null) {
setClassUnderTest(type.getFullyQualifiedName('.'));
}
}
private IType chooseClassToTestType() {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null)
return null;
IJavaElement[] elements= new IJavaElement[] { root.getJavaProject() };
IJavaSearchScope scope= SearchEngine.createJavaSearchScope(elements);
try {
SelectionDialog dialog= JavaUI.createTypeDialog(getShell(), getWizard().getContainer(), scope, IJavaElementSearchConstants.CONSIDER_CLASSES_AND_ENUMS, false, getClassUnderTestText());
dialog.setTitle(WizardMessages.NewTestCaseWizardPageOne_class_to_test_dialog_title);
dialog.setMessage(WizardMessages.NewTestCaseWizardPageOne_class_to_test_dialog_message);
if (dialog.open() == Window.OK) {
Object[] resultArray= dialog.getResult();
if (resultArray != null && resultArray.length > 0)
return (IType) resultArray[0];
}
} catch (JavaModelException e) {
JUnitPlugin.log(e);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#packageChanged()
*/
protected IStatus packageChanged() {
IStatus status= super.packageChanged();
fClassToTestCompletionProcessor.setPackageFragment(getPackageFragment());
return status;
}
/**
* Hook method that gets called when the class under test has changed. The method class under test
* returns the status of the validation.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus classUnderTestChanged() {
JUnitStatus status= new JUnitStatus();
fClassUnderTest= null;
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return status;
}
String classToTestName= getClassUnderTestText();
if (classToTestName.length() == 0) {
return status;
}
IStatus val= JavaConventions.validateJavaTypeName(classToTestName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_valid);
return status;
}
IPackageFragment pack= getPackageFragment(); // can be null
try {
IType type= resolveClassNameToType(root.getJavaProject(), pack, classToTestName);
if (type == null) {
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_exist);
return status;
}
if (type.isInterface()) {
status.setWarning(Messages.format(WizardMessages.NewTestCaseWizardPageOne_warning_class_to_test_is_interface, classToTestName));
}
if (pack != null && !JUnitStubUtility.isVisible(type, pack)) {
status.setWarning(Messages.format(WizardMessages.NewTestCaseWizardPageOne_warning_class_to_test_not_visible, classToTestName));
}
fClassUnderTest= type;
fPage2.setClassUnderTest(fClassUnderTest);
} catch (JavaModelException e) {
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_class_to_test_not_valid);
}
return status;
}
/**
* Returns the content of the class to test text field.
*
* @return the name of the class to test
*/
public String getClassUnderTestText() {
return fClassUnderTestText;
}
/**
* Returns the class to be tested.
*
* @return the class under test or <code>null</code> if the entered values are not valid
*/
public IType getClassUnderTest() {
return fClassUnderTest;
}
/**
* Sets the name of the class under test.
*
* @param name The name to set
*/
public void setClassUnderTest(String name) {
if (fClassUnderTestControl != null && !fClassUnderTestControl.isDisposed()) {
fClassUnderTestControl.setText(name);
}
internalSetClassUnderText(name);
}
private void internalSetClassUnderText(String name) {
fClassUnderTestText= name;
fClassUnderTestStatus= classUnderTestChanged();
handleFieldChanged(CLASS_UNDER_TEST);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#createTypeMembers(org.eclipse.jdt.core.IType, org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager, org.eclipse.core.runtime.IProgressMonitor)
*/
protected void createTypeMembers(IType type, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
if (fMethodStubsButtons.isSelected(IDX_CONSTRUCTOR))
createConstructor(type, imports);
if (fMethodStubsButtons.isSelected(IDX_SETUP_CLASS)) {
createSetUpClass(type, imports);
}
if (fMethodStubsButtons.isSelected(IDX_TEARDOWN_CLASS)) {
createTearDownClass(type, imports);
}
if (fMethodStubsButtons.isSelected(IDX_SETUP)) {
createSetUp(type, imports);
}
if (fMethodStubsButtons.isSelected(IDX_TEARDOWN)) {
createTearDown(type, imports);
}
if (fClassUnderTest != null) {
createTestMethodStubs(type, imports);
}
if (isJUnit4()) {
imports.addStaticImport("org.junit.Assert", "*", false); //$NON-NLS-1$ //$NON-NLS-2$
}
}
private void createConstructor(IType type, ImportsManager imports) throws CoreException {
ITypeHierarchy typeHierarchy= null;
IType[] superTypes= null;
String content;
IMethod methodTemplate= null;
if (type.exists()) {
typeHierarchy= type.newSupertypeHierarchy(null);
superTypes= typeHierarchy.getAllSuperclasses(type);
for (int i= 0; i < superTypes.length; i++) {
if (superTypes[i].exists()) {
IMethod constrMethod= superTypes[i].getMethod(superTypes[i].getElementName(), new String[] {"Ljava.lang.String;"}); //$NON-NLS-1$
if (constrMethod.exists() && constrMethod.isConstructor()) {
methodTemplate= constrMethod;
break;
}
}
}
}
GenStubSettings settings= JUnitStubUtility.getCodeGenerationSettings(type.getJavaProject());
settings.createComments= isAddComments();
if (methodTemplate != null) {
settings.callSuper= true;
settings.methodOverwrites= true;
content= JUnitStubUtility.genStub(type.getCompilationUnit(), getTypeName(), methodTemplate, settings, null, imports);
} else {
final String delimiter= getLineDelimiter();
StringBuffer buffer= new StringBuffer(32);
buffer.append("public "); //$NON-NLS-1$
buffer.append(getTypeName());
buffer.append('(');
if (!isJUnit4()) {
buffer.append(imports.addImport("java.lang.String")).append(" name"); //$NON-NLS-1$ //$NON-NLS-2$
}
buffer.append(") {"); //$NON-NLS-1$
buffer.append(delimiter);
if (!isJUnit4()) {
buffer.append("super(name);").append(delimiter); //$NON-NLS-1$
}
buffer.append('}');
buffer.append(delimiter);
content= buffer.toString();
}
type.createMethod(content, null, true, null);
}
private IMethod findInHierarchy(IType type, String methodName) throws JavaModelException {
ITypeHierarchy typeHierarchy= null;
IType[] superTypes= null;
if (type.exists()) {
typeHierarchy= type.newSupertypeHierarchy(null);
superTypes= typeHierarchy.getAllSuperclasses(type);
for (int i= 0; i < superTypes.length; i++) {
if (superTypes[i].exists()) {
IMethod testMethod= superTypes[i].getMethod(methodName, new String[] {});
if (testMethod.exists()) {
return testMethod;
}
}
}
}
return null;
}
private void createSetupStubs(IType type, String methodName, boolean isStatic, String annotationType, ImportsManager imports) throws CoreException {
String content= null;
IMethod methodTemplate= findInHierarchy(type, methodName);
String annotation= null;
if (isJUnit4()) {
annotation= '@' + imports.addImport(annotationType);
}
GenStubSettings settings= JUnitStubUtility.getCodeGenerationSettings(type.getJavaProject());
settings.createComments= isAddComments();
if (methodTemplate != null) {
settings.callSuper= true;
settings.methodOverwrites= true;
content= JUnitStubUtility.genStub(type.getCompilationUnit(), getTypeName(), methodTemplate, settings, annotation, imports);
} else {
final String delimiter= getLineDelimiter();
StringBuffer buffer= new StringBuffer();
if (settings.createComments) {
String[] excSignature= { Signature.createTypeSignature("java.lang.Exception", true) }; //$NON-NLS-1$
String comment= CodeGeneration.getMethodComment(type.getCompilationUnit(), type.getElementName(), methodName, new String[0], excSignature, Signature.SIG_VOID, null, delimiter);
if (comment != null) {
buffer.append(comment);
}
}
if (annotation != null) {
buffer.append(annotation).append(delimiter);
}
if (isJUnit4()) {
buffer.append("public "); //$NON-NLS-1$
} else {
buffer.append("protected "); //$NON-NLS-1$
}
if (isStatic) {
buffer.append("static "); //$NON-NLS-1$
}
buffer.append("void "); //$NON-NLS-1$
buffer.append(methodName);
buffer.append("() throws "); //$NON-NLS-1$
buffer.append(imports.addImport("java.lang.Exception")); //$NON-NLS-1$
buffer.append(" {}"); //$NON-NLS-1$
buffer.append(delimiter);
content= buffer.toString();
}
type.createMethod(content, null, false, null);
}
private void createSetUp(IType type, ImportsManager imports) throws CoreException {
createSetupStubs(type, "setUp", false, "org.junit.Before", imports); //$NON-NLS-1$ //$NON-NLS-2$
}
private void createTearDown(IType type, ImportsManager imports) throws CoreException {
createSetupStubs(type, "tearDown", false, "org.junit.After", imports); //$NON-NLS-1$ //$NON-NLS-2$
}
private void createSetUpClass(IType type, ImportsManager imports) throws CoreException {
createSetupStubs(type, "setUpBeforeClass", true, "org.junit.BeforeClass", imports); //$NON-NLS-1$ //$NON-NLS-2$
}
private void createTearDownClass(IType type, ImportsManager imports) throws CoreException {
createSetupStubs(type, "tearDownAfterClass", true, "org.junit.AfterClass", imports); //$NON-NLS-1$ //$NON-NLS-2$
}
private void createTestMethodStubs(IType type, ImportsManager imports) throws CoreException {
IMethod[] methods= fPage2.getCheckedMethods();
if (methods.length == 0)
return;
/* find overloaded methods */
IMethod[] allMethodsArray= fPage2.getAllMethods();
List allMethods= new ArrayList();
allMethods.addAll(Arrays.asList(allMethodsArray));
List overloadedMethods= getOverloadedMethods(allMethods);
/* used when for example both sum and Sum methods are present. Then
* sum -> testSum
* Sum -> testSum1
*/
List names= new ArrayList();
for (int i = 0; i < methods.length; i++) {
IMethod method= methods[i];
String elementName= method.getElementName();
StringBuffer name= new StringBuffer(PREFIX).append(Character.toUpperCase(elementName.charAt(0))).append(elementName.substring(1));
StringBuffer buffer= new StringBuffer();
final boolean contains= overloadedMethods.contains(method);
if (contains)
appendParameterNamesToMethodName(name, method.getParameterTypes());
replaceIllegalCharacters(name);
/* void foo(java.lang.StringBuffer sb) {}
* void foo(mypackage1.StringBuffer sb) {}
* void foo(mypackage2.StringBuffer sb) {}
* ->
* testFooStringBuffer()
* testFooStringBuffer1()
* testFooStringBuffer2()
*/
String testName= name.toString();
if (names.contains(testName)) {
int suffix= 1;
while (names.contains(testName + Integer.toString(suffix)))
suffix++;
name.append(Integer.toString(suffix));
}
testName= name.toString();
names.add(testName);
if (isAddComments()) {
appendMethodComment(buffer, method);
}
if (isJUnit4()) {
buffer.append('@').append(imports.addImport(JUnitPlugin.JUNIT4_ANNOTATION_NAME)).append(getLineDelimiter());
}
buffer.append("public ");//$NON-NLS-1$
if (fPage2.getCreateFinalMethodStubsButtonSelection())
buffer.append("final "); //$NON-NLS-1$
buffer.append("void ");//$NON-NLS-1$
buffer.append(testName);
buffer.append("()");//$NON-NLS-1$
appendTestMethodBody(buffer, testName, method, type.getCompilationUnit(), imports);
type.createMethod(buffer.toString(), null, false, null);
}
}
private void replaceIllegalCharacters(StringBuffer buffer) {
char character= 0;
for (int index= buffer.length() - 1; index >= 0; index--) {
character= buffer.charAt(index);
if (Character.isWhitespace(character))
buffer.deleteCharAt(index);
else if (character == '<')
buffer.replace(index, index + 1, OF_TAG);
else if (character == '?')
buffer.replace(index, index + 1, QUESTION_MARK_TAG);
else if (!Character.isJavaIdentifierPart(character))
buffer.deleteCharAt(index);
}
}
private String getLineDelimiter() throws JavaModelException{
IType classToTest= getClassUnderTest();
if (classToTest != null && classToTest.exists() && classToTest.getCompilationUnit() != null)
return classToTest.getCompilationUnit().findRecommendedLineSeparator();
return getPackageFragment().findRecommendedLineSeparator();
}
private void appendTestMethodBody(StringBuffer buffer, String name, IMethod method, ICompilationUnit targetCu, ImportsManager imports) throws CoreException {
final String delimiter= getLineDelimiter();
buffer.append('{').append(delimiter);
String todoTask= ""; //$NON-NLS-1$
if (fPage2.isCreateTasks()) {
String todoTaskTag= JUnitStubUtility.getTodoTaskTag(targetCu.getJavaProject());
if (todoTaskTag != null) {
todoTask= " // " + todoTaskTag; //$NON-NLS-1$
}
}
String message= WizardMessages.NewTestCaseWizardPageOne_not_yet_implemented_string;
buffer.append(Messages.format("fail(\"{0}\");", message)).append(todoTask).append(delimiter); //$NON-NLS-1$
buffer.append('}').append(delimiter);
}
private void appendParameterNamesToMethodName(StringBuffer buffer, String[] parameters) {
for (int i= 0; i < parameters.length; i++) {
final StringBuffer buf= new StringBuffer(Signature.getSimpleName(Signature.toString(Signature.getElementType(parameters[i]))));
final char character= buf.charAt(0);
if (buf.length() > 0 && !Character.isUpperCase(character))
buf.setCharAt(0, Character.toUpperCase(character));
buffer.append(buf.toString());
for (int j= 0, arrayCount= Signature.getArrayCount(parameters[i]); j < arrayCount; j++) {
buffer.append("Array"); //$NON-NLS-1$
}
}
}
private void appendMethodComment(StringBuffer buffer, IMethod method) throws JavaModelException {
final String delimiter= getLineDelimiter();
final StringBuffer buf= new StringBuffer("{@link "); //$NON-NLS-1$
JavaElementLabels.getTypeLabel(method.getDeclaringType(), JavaElementLabels.T_FULLY_QUALIFIED, buf);
buf.append('#');
buf.append(method.getElementName());
buf.append('(');
String[] paramTypes= JUnitStubUtility.getParameterTypeNamesForSeeTag(method);
for (int i= 0; i < paramTypes.length; i++) {
if (i != 0) {
buf.append(", "); //$NON-NLS-1$
}
buf.append(paramTypes[i]);
}
buf.append(')');
buf.append('}');
buffer.append("/**");//$NON-NLS-1$
buffer.append(delimiter);
buffer.append(" * ");//$NON-NLS-1$
buffer.append(Messages.format(WizardMessages.NewTestCaseWizardPageOne_comment_class_to_test, buf.toString()));
buffer.append(delimiter);
buffer.append(" */");//$NON-NLS-1$
buffer.append(delimiter);
}
private List getOverloadedMethods(List allMethods) {
List overloadedMethods= new ArrayList();
for (int i= 0; i < allMethods.size(); i++) {
IMethod current= (IMethod) allMethods.get(i);
String currentName= current.getElementName();
boolean currentAdded= false;
for (ListIterator iter= allMethods.listIterator(i+1); iter.hasNext(); ) {
IMethod iterMethod= (IMethod) iter.next();
if (iterMethod.getElementName().equals(currentName)) {
//method is overloaded
if (!currentAdded) {
overloadedMethods.add(current);
currentAdded= true;
}
overloadedMethods.add(iterMethod);
iter.remove();
}
}
}
return overloadedMethods;
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if (!visible) {
saveWidgetValues();
}
//if (visible) setFocus();
}
/**
* The method is called when the container has changed to validate if the project
* is suited for the JUnit test class. Clients can override to modify or remove that validation.
*
* @return the status of the validation
*/
protected IStatus validateIfJUnitProject() {
JUnitStatus status= new JUnitStatus();
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root != null) {
try {
IJavaProject project= root.getJavaProject();
if (isJUnit4()) {
if (!JUnitStubUtility.is50OrHigher(project)) {
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_java5required);
return status;
}
if (project.findType(JUnitPlugin.JUNIT4_ANNOTATION_NAME) == null) {
status.setWarning(WizardMessages.NewTestCaseWizardPageOne__error_junit4NotOnbuildpath);
return status;
}
} else {
if (project.findType(JUnitPlugin.TEST_SUPERCLASS_NAME) == null) {
status.setWarning(WizardMessages.NewTestCaseWizardPageOne_error_junitNotOnbuildpath);
return status;
}
}
} catch (JavaModelException e) {
}
}
return status;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#superClassChanged()
*/
protected IStatus superClassChanged() {
// replaces the super class validation of of the normal type wizard
if (isJUnit4()) {
return new JUnitStatus();
}
String superClassName= getSuperClass();
JUnitStatus status= new JUnitStatus();
if (superClassName == null || superClassName.trim().equals("")) { //$NON-NLS-1$
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_superclass_empty);
return status;
}
if (getPackageFragmentRoot() != null) {
try {
IType type= resolveClassNameToType(getPackageFragmentRoot().getJavaProject(), getPackageFragment(), superClassName);
if (type == null) {
status.setWarning(WizardMessages.NewTestCaseWizardPageOne_error_superclass_not_exist);
return status;
}
if (type.isInterface()) {
status.setError(WizardMessages.NewTestCaseWizardPageOne_error_superclass_is_interface);
return status;
}
if (!TestSearchEngine.isTestImplementor(type)) { // TODO: expensive!
status.setError(Messages.format(WizardMessages.NewTestCaseWizardPageOne_error_superclass_not_implementing_test_interface, JUnitPlugin.TEST_INTERFACE_NAME));
return status;
}
} catch (JavaModelException e) {
JUnitPlugin.log(e);
}
}
return status;
}
/* (non-Javadoc)
* @see org.eclipse.jface.wizard.IWizardPage#canFlipToNextPage()
*/
public boolean canFlipToNextPage() {
return super.canFlipToNextPage() && getClassUnderTest() != null;
}
private IType resolveClassNameToType(IJavaProject jproject, IPackageFragment pack, String classToTestName) throws JavaModelException {
if (!jproject.exists()) {
return null;
}
IType type= jproject.findType(classToTestName);
// search in current package
if (type == null && pack != null && !pack.isDefaultPackage()) {
type= jproject.findType(pack.getElementName(), classToTestName);
}
// search in java.lang
if (type == null) {
type= jproject.findType("java.lang", classToTestName); //$NON-NLS-1$
}
return type;
}
/**
* Use the dialog store to restore widget values to the values that they held
* last time this wizard was used to completion
*/
private void restoreWidgetValues() {
IDialogSettings settings= getDialogSettings();
if (settings != null) {
fMethodStubsButtons.setSelection(IDX_SETUP, settings.getBoolean(STORE_SETUP));
fMethodStubsButtons.setSelection(IDX_TEARDOWN, settings.getBoolean(STORE_TEARDOWN));
fMethodStubsButtons.setSelection(IDX_SETUP_CLASS, settings.getBoolean(STORE_SETUP_CLASS));
fMethodStubsButtons.setSelection(IDX_TEARDOWN_CLASS, settings.getBoolean(STORE_TEARDOWN_CLASS));
fMethodStubsButtons.setSelection(IDX_CONSTRUCTOR, settings.getBoolean(STORE_CONSTRUCTOR));
} else {
fMethodStubsButtons.setSelection(IDX_SETUP, false); //setUp
fMethodStubsButtons.setSelection(IDX_TEARDOWN, false); //tearDown
fMethodStubsButtons.setSelection(IDX_SETUP_CLASS, false); //setUpBeforeClass
fMethodStubsButtons.setSelection(IDX_TEARDOWN_CLASS, false); //setUpAfterClass
fMethodStubsButtons.setSelection(IDX_CONSTRUCTOR, false); //constructor
}
}
/**
* Since Finish was pressed, write widget values to the dialog store so that they
* will persist into the next invocation of this wizard page
*/
private void saveWidgetValues() {
IDialogSettings settings= getDialogSettings();
if (settings != null) {
settings.put(STORE_SETUP, fMethodStubsButtons.isSelected(IDX_SETUP));
settings.put(STORE_TEARDOWN, fMethodStubsButtons.isSelected(IDX_TEARDOWN));
settings.put(STORE_SETUP_CLASS, fMethodStubsButtons.isSelected(IDX_SETUP_CLASS));
settings.put(STORE_TEARDOWN_CLASS, fMethodStubsButtons.isSelected(IDX_TEARDOWN_CLASS));
settings.put(STORE_CONSTRUCTOR, fMethodStubsButtons.isSelected(IDX_CONSTRUCTOR));
}
}
}