blob: b95d9cac7512c1ca9e85b6c900b3425bfa65c44a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* IBM Corporation - initial API and implementation
* John Kaplan, johnkaplantech@gmail.com - 108071 [code templates] template for body of newly created class
*******************************************************************************/
package org.eclipse.wst.jsdt.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
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.jface.contentassist.SubjectControlContentAssistant;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
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.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.contentassist.ContentAssistHandler;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.wst.jsdt.core.Flags;
import org.eclipse.wst.jsdt.core.IBuffer;
import org.eclipse.wst.jsdt.core.IFunction;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IPackageFragment;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.ISourceRange;
import org.eclipse.wst.jsdt.core.IType;
import org.eclipse.wst.jsdt.core.JavaScriptConventions;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.Signature;
import org.eclipse.wst.jsdt.core.ToolFactory;
import org.eclipse.wst.jsdt.core.compiler.IProblem;
import org.eclipse.wst.jsdt.core.compiler.IScanner;
import org.eclipse.wst.jsdt.core.compiler.ITerminalSymbols;
import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
import org.eclipse.wst.jsdt.core.dom.AST;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.ASTParser;
import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
import org.eclipse.wst.jsdt.core.dom.ImportDeclaration;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.Type;
import org.eclipse.wst.jsdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;
import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
import org.eclipse.wst.jsdt.core.search.SearchEngine;
import org.eclipse.wst.jsdt.internal.corext.codemanipulation.AddUnimplementedConstructorsOperation;
import org.eclipse.wst.jsdt.internal.corext.codemanipulation.AddUnimplementedMethodsOperation;
import org.eclipse.wst.jsdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.wst.jsdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
import org.eclipse.wst.jsdt.internal.corext.dom.TokenScanner;
import org.eclipse.wst.jsdt.internal.corext.refactoring.StubTypeContext;
import org.eclipse.wst.jsdt.internal.corext.refactoring.TypeContextChecker;
import org.eclipse.wst.jsdt.internal.corext.template.java.JavaContext;
import org.eclipse.wst.jsdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
import org.eclipse.wst.jsdt.internal.corext.util.Messages;
import org.eclipse.wst.jsdt.internal.corext.util.Resources;
import org.eclipse.wst.jsdt.internal.corext.util.Strings;
import org.eclipse.wst.jsdt.internal.ui.JavaPluginImages;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.dialogs.FilteredTypesSelectionDialog;
import org.eclipse.wst.jsdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.wst.jsdt.internal.ui.dialogs.TableTextCellEditor;
import org.eclipse.wst.jsdt.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.wst.jsdt.internal.ui.preferences.CodeTemplatePreferencePage;
import org.eclipse.wst.jsdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.CompletionContextRequestor;
import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.JavaPackageCompletionProcessor;
import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
import org.eclipse.wst.jsdt.internal.ui.util.SWTUtil;
import org.eclipse.wst.jsdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.Separator;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringDialogField;
import org.eclipse.wst.jsdt.ui.CodeGeneration;
import org.eclipse.wst.jsdt.ui.CodeStyleConfiguration;
import org.eclipse.wst.jsdt.ui.JavaScriptElementLabelProvider;
/**
* The class <code>NewTypeWizardPage</code> contains controls and validation routines
* for a 'New Type WizardPage'. Implementors decide which components to add and to enable.
* Implementors can also customize the validation code. <code>NewTypeWizardPage</code>
* is intended to serve as base class of all wizards that create types like applets, servlets, classes,
* interfaces, etc.
* <p>
* See {@link NewClassWizardPage} or {@link NewInterfaceWizardPage} for an
* example usage of the <code>NewTypeWizardPage</code>.
* </p>
*
* Provisional API: This class/interface is part of an interim API that is still under development and expected to
* change significantly before reaching stability. It is being made available at this early stage to solicit feedback
* from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
* (repeatedly) as the API evolves.
*
* @see org.eclipse.wst.jsdt.ui.wizards.NewClassWizardPage
* @see org.eclipse.wst.jsdt.ui.wizards.NewInterfaceWizardPage
*
*/
public abstract class NewTypeWizardPage extends NewContainerWizardPage {
/**
* Class used in stub creation routines to add needed imports to a
* compilation unit.
*/
public static class ImportsManager {
private ImportRewrite fImportsRewrite;
/* package */ ImportsManager(JavaScriptUnit astRoot) throws CoreException {
fImportsRewrite= CodeStyleConfiguration.createImportRewrite(astRoot, true);
}
/* package */ IJavaScriptUnit getCompilationUnit() {
return fImportsRewrite.getCompilationUnit();
}
/**
* Adds a new import declaration that is sorted in the existing imports.
* If an import already exists or the import would conflict with an import
* of an other type with the same simple name, the import is not added.
*
* @param qualifiedTypeName The fully qualified name of the type to import
* (dot separated).
* @return Returns the simple type name that can be used in the code or the
* fully qualified type name if an import conflict prevented the import.
*/
public String addImport(String qualifiedTypeName) {
return fImportsRewrite.addImport(qualifiedTypeName);
}
/**
* Adds a new import declaration that is sorted in the existing imports.
* If an import already exists or the import would conflict with an import
* of an other type with the same simple name, the import is not added.
*
* @param typeBinding the binding of the type to import
*
* @return Returns the simple type name that can be used in the code or the
* fully qualified type name if an import conflict prevented the import.
*/
public String addImport(ITypeBinding typeBinding) {
return fImportsRewrite.addImport(typeBinding);
}
/**
* Adds a new import declaration for a static type that is sorted in the existing imports.
* If an import already exists or the import would conflict with an import
* of an other static import with the same simple name, the import is not added.
*
* @param declaringTypeName The qualified name of the static's member declaring type
* @param simpleName the simple name of the member; either a field or a method name.
* @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
* method.
* @return returns either the simple member name if the import was successful or else the qualified name if
* an import conflict prevented the import.
*
*
*/
public String addStaticImport(String declaringTypeName, String simpleName, boolean isField) {
return fImportsRewrite.addStaticImport(declaringTypeName, simpleName, isField);
}
/* package */ void create(boolean needsSave, IProgressMonitor monitor) throws CoreException {
TextEdit edit= fImportsRewrite.rewriteImports(monitor);
JavaModelUtil.applyEdit(fImportsRewrite.getCompilationUnit(), edit, needsSave, null);
}
/* package */ void removeImport(String qualifiedName) {
fImportsRewrite.removeImport(qualifiedName);
}
/* package */ void removeStaticImport(String qualifiedName) {
fImportsRewrite.removeStaticImport(qualifiedName);
}
}
/** Public access flag. See The JavaScript Virtual Machine Specification for more details. */
public int F_PUBLIC = Flags.AccPublic;
/** Private access flag. See The JavaScript Virtual Machine Specification for more details. */
public int F_PRIVATE = Flags.AccPrivate;
/** Static access flag. See The JavaScript Virtual Machine Specification for more details. */
public int F_STATIC = Flags.AccStatic;
/** Abstract property flag. See The JavaScript Virtual Machine Specification for more details. */
public int F_ABSTRACT = Flags.AccAbstract;
private final static String PAGE_NAME= "NewTypeWizardPage"; //$NON-NLS-1$
/** Field ID of the package input field. */
protected final static String PACKAGE= PAGE_NAME + ".package"; //$NON-NLS-1$
/** Field ID of the enclosing type input field. */
protected final static String ENCLOSING= PAGE_NAME + ".enclosing"; //$NON-NLS-1$
/** Field ID of the enclosing type checkbox. */
protected final static String ENCLOSINGSELECTION= ENCLOSING + ".selection"; //$NON-NLS-1$
/** Field ID of the type name input field. */
protected final static String TYPENAME= PAGE_NAME + ".typename"; //$NON-NLS-1$
/** Field ID of the super type input field. */
protected final static String SUPER= PAGE_NAME + ".superclass"; //$NON-NLS-1$
/** Field ID of the super interfaces input field. */
protected final static String INTERFACES= PAGE_NAME + ".interfaces"; //$NON-NLS-1$
/** Field ID of the modifier check boxes. */
protected final static String MODIFIERS= PAGE_NAME + ".modifiers"; //$NON-NLS-1$
/** Field ID of the method stubs check boxes. */
protected final static String METHODS= PAGE_NAME + ".methods"; //$NON-NLS-1$
private static class InterfaceWrapper {
public String interfaceName;
public InterfaceWrapper(String interfaceName) {
this.interfaceName= interfaceName;
}
public int hashCode() {
return interfaceName.hashCode();
}
public boolean equals(Object obj) {
return obj != null && getClass().equals(obj.getClass()) && ((InterfaceWrapper) obj).interfaceName.equals(interfaceName);
}
}
private static class InterfacesListLabelProvider extends LabelProvider {
private Image fInterfaceImage;
public InterfacesListLabelProvider() {
fInterfaceImage= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE);
}
public String getText(Object element) {
return ((InterfaceWrapper) element).interfaceName;
}
public Image getImage(Object element) {
return fInterfaceImage;
}
}
private StringButtonStatusDialogField fPackageDialogField;
private SelectionButtonDialogField fEnclosingTypeSelection;
private StringButtonDialogField fEnclosingTypeDialogField;
private boolean fCanModifyPackage;
private boolean fCanModifyEnclosingType;
private IPackageFragment fCurrPackage;
private IType fCurrEnclosingType;
/**
* a handle to the type to be created (does usually not exist, can be null)
*/
private IType fCurrType;
private StringDialogField fTypeNameDialogField;
private StringButtonDialogField fSuperClassDialogField;
private ListDialogField fSuperInterfacesDialogField;
private SelectionButtonDialogFieldGroup fAccMdfButtons;
private SelectionButtonDialogFieldGroup fOtherMdfButtons;
private SelectionButtonDialogField fAddCommentButton;
private boolean fUseAddCommentButtonValue; // used for compatibility: Wizards that don't show the comment button control
// will use the preferences settings
private IType fCreatedType;
private JavaPackageCompletionProcessor fCurrPackageCompletionProcessor;
private JavaTypeCompletionProcessor fEnclosingTypeCompletionProcessor;
private StubTypeContext fSuperClassStubTypeContext;
private StubTypeContext fSuperInterfaceStubTypeContext;
protected IStatus fEnclosingTypeStatus;
protected IStatus fPackageStatus;
protected IStatus fTypeNameStatus;
protected IStatus fSuperClassStatus;
protected IStatus fModifierStatus;
protected IStatus fSuperInterfacesStatus;
private final int PUBLIC_INDEX= 0, DEFAULT_INDEX= 1, PRIVATE_INDEX= 2, PROTECTED_INDEX= 3;
private final int ABSTRACT_INDEX= 0, STATIC_INDEX= 2, ENUM_ANNOT_STATIC_INDEX= 1;
private int fTypeKind;
/**
* Constant to signal that the created type is a class.
*
*/
public static final int CLASS_TYPE = 1;
/**
* Constant to signal that the created type is a interface.
*
*/
public static final int INTERFACE_TYPE = 2;
/**
* Constant to signal that the created type is an enum.
*
*/
public static final int ENUM_TYPE = 3;
/**
* Constant to signal that the created type is an annotation.
*
*/
public static final int ANNOTATION_TYPE = 4;
/**
* Creates a new <code>NewTypeWizardPage</code>.
*
* @param isClass <code>true</code> if a new class is to be created; otherwise
* an interface is to be created
* @param pageName the wizard page's name
*/
public NewTypeWizardPage(boolean isClass, String pageName) {
this(isClass ? CLASS_TYPE : INTERFACE_TYPE, pageName);
}
/**
* Creates a new <code>NewTypeWizardPage</code>.
*
* @param typeKind Signals the kind of the type to be created. Valid kinds are
* {@link #CLASS_TYPE}, {@link #INTERFACE_TYPE}, {@link #ENUM_TYPE} and {@link #ANNOTATION_TYPE}
* @param pageName the wizard page's name
*
*/
public NewTypeWizardPage(int typeKind, String pageName) {
super(pageName);
fTypeKind= typeKind;
fCreatedType= null;
TypeFieldsAdapter adapter= new TypeFieldsAdapter();
fPackageDialogField= new StringButtonStatusDialogField(adapter);
fPackageDialogField.setDialogFieldListener(adapter);
fPackageDialogField.setLabelText(getPackageLabel());
fPackageDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_package_button);
fPackageDialogField.setStatusWidthHint(NewWizardMessages.NewTypeWizardPage_default);
fEnclosingTypeSelection= new SelectionButtonDialogField(SWT.CHECK);
fEnclosingTypeSelection.setDialogFieldListener(adapter);
fEnclosingTypeSelection.setLabelText(getEnclosingTypeLabel());
fEnclosingTypeDialogField= new StringButtonDialogField(adapter);
fEnclosingTypeDialogField.setDialogFieldListener(adapter);
fEnclosingTypeDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_enclosing_button);
fTypeNameDialogField= new StringDialogField();
fTypeNameDialogField.setDialogFieldListener(adapter);
fTypeNameDialogField.setLabelText(getTypeNameLabel());
fSuperClassDialogField= new StringButtonDialogField(adapter);
fSuperClassDialogField.setDialogFieldListener(adapter);
fSuperClassDialogField.setLabelText(getSuperClassLabel());
fSuperClassDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_superclass_button);
String[] addButtons= new String[] {
NewWizardMessages.NewTypeWizardPage_interfaces_add,
/* 1 */ null,
NewWizardMessages.NewTypeWizardPage_interfaces_remove
};
fSuperInterfacesDialogField= new ListDialogField(adapter, addButtons, new InterfacesListLabelProvider());
fSuperInterfacesDialogField.setDialogFieldListener(adapter);
fSuperInterfacesDialogField.setTableColumns(new ListDialogField.ColumnsDescription(1, false));
fSuperInterfacesDialogField.setLabelText(getSuperInterfacesLabel());
fSuperInterfacesDialogField.setRemoveButtonIndex(2);
String[] buttonNames1= new String[] {
NewWizardMessages.NewTypeWizardPage_modifiers_public,
NewWizardMessages.NewTypeWizardPage_modifiers_default,
NewWizardMessages.NewTypeWizardPage_modifiers_private,
NewWizardMessages.NewTypeWizardPage_modifiers_protected
};
fAccMdfButtons= new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames1, 4);
fAccMdfButtons.setDialogFieldListener(adapter);
fAccMdfButtons.setLabelText(getModifiersLabel());
fAccMdfButtons.setSelection(0, true);
String[] buttonNames2;
if (fTypeKind == CLASS_TYPE) {
buttonNames2= new String[] {
NewWizardMessages.NewTypeWizardPage_modifiers_abstract,
NewWizardMessages.NewTypeWizardPage_modifiers_final,
NewWizardMessages.NewTypeWizardPage_modifiers_static
};
} else {
if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
buttonNames2= new String[] {
NewWizardMessages.NewTypeWizardPage_modifiers_abstract,
NewWizardMessages.NewTypeWizardPage_modifiers_static
};
}
else
buttonNames2= new String[] {};
}
fOtherMdfButtons= new SelectionButtonDialogFieldGroup(SWT.CHECK, buttonNames2, 4);
fOtherMdfButtons.setDialogFieldListener(adapter);
fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false);
fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false);
fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, false);
if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, false);
fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, false);
}
fAddCommentButton= new SelectionButtonDialogField(SWT.CHECK);
fAddCommentButton.setLabelText(NewWizardMessages.NewTypeWizardPage_addcomment_label);
fUseAddCommentButtonValue= false; // only used when enabled
fCurrPackageCompletionProcessor= new JavaPackageCompletionProcessor();
fEnclosingTypeCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
fPackageStatus= new StatusInfo();
fEnclosingTypeStatus= new StatusInfo();
fCanModifyPackage= true;
fCanModifyEnclosingType= true;
updateEnableState();
fTypeNameStatus= new StatusInfo();
fSuperClassStatus= new StatusInfo();
fSuperInterfacesStatus= new StatusInfo();
fModifierStatus= new StatusInfo();
}
/**
* Initializes all fields provided by the page with a given selection.
*
* @param elem the selection used to initialize this page or <code>
* null</code> if no selection was available
*/
protected void initTypePage(IJavaScriptElement elem) {
String initSuperclass= "java.lang.Object"; //$NON-NLS-1$
ArrayList initSuperinterfaces= new ArrayList(5);
IJavaScriptProject project= null;
IPackageFragment pack= null;
IType enclosingType= null;
if (elem != null) {
// evaluate the enclosing type
project= elem.getJavaScriptProject();
pack= (IPackageFragment) elem.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT);
IType typeInCU= (IType) elem.getAncestor(IJavaScriptElement.TYPE);
if (typeInCU != null) {
if (typeInCU.getJavaScriptUnit() != null) {
enclosingType= typeInCU;
}
} else {
IJavaScriptUnit cu= (IJavaScriptUnit) elem.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT);
if (cu != null) {
enclosingType= cu.findPrimaryType();
}
}
IType type= null;
if (elem.getElementType() == IJavaScriptElement.TYPE) {
type= (IType)elem;
if (type.exists()) {
String superName= JavaModelUtil.getFullyQualifiedName(type);
initSuperclass= superName;
}
}
}
String typeName= ""; //$NON-NLS-1$
ITextSelection selection= getCurrentTextSelection();
if (selection != null) {
String text= selection.getText();
if (text != null && validateJavaTypeName(text, project).isOK()) {
typeName= text;
}
}
setPackageFragment(pack, true);
setEnclosingType(enclosingType, true);
setEnclosingTypeSelection(false, true);
setTypeName(typeName, true);
setSuperClass(initSuperclass, true);
setSuperInterfaces(initSuperinterfaces, true);
setAddComments(StubUtility.doAddComments(project), true); // from project or workspace
}
private static IStatus validateJavaTypeName(String text, IJavaScriptProject project) {
if (project == null || !project.exists()) {
return JavaScriptConventions.validateJavaScriptTypeName(text, JavaScriptCore.VERSION_1_3, JavaScriptCore.VERSION_1_3);
}
String sourceLevel= project.getOption(JavaScriptCore.COMPILER_SOURCE, true);
String compliance= project.getOption(JavaScriptCore.COMPILER_COMPLIANCE, true);
return JavaScriptConventions.validateJavaScriptTypeName(text, sourceLevel, compliance);
}
private static IStatus validatePackageName(String text, IJavaScriptProject project) {
if (project == null || !project.exists()) {
return JavaScriptConventions.validatePackageName(text, JavaScriptCore.VERSION_1_3, JavaScriptCore.VERSION_1_3);
}
String sourceLevel= project.getOption(JavaScriptCore.COMPILER_SOURCE, true);
String compliance= project.getOption(JavaScriptCore.COMPILER_COMPLIANCE, true);
return JavaScriptConventions.validatePackageName(text, sourceLevel, compliance);
}
// -------- UI Creation ---------
/**
* Returns the label that is used for the package input field.
*
* @return the label that is used for the package input field.
*
*/
protected String getPackageLabel() {
return NewWizardMessages.NewTypeWizardPage_package_label;
}
/**
* Returns the label that is used for the enclosing type input field.
*
* @return the label that is used for the enclosing type input field.
*
*/
protected String getEnclosingTypeLabel() {
return NewWizardMessages.NewTypeWizardPage_enclosing_selection_label;
}
/**
* Returns the label that is used for the type name input field.
*
* @return the label that is used for the type name input field.
*
*/
protected String getTypeNameLabel() {
return NewWizardMessages.NewTypeWizardPage_typename_label;
}
/**
* Returns the label that is used for the modifiers input field.
*
* @return the label that is used for the modifiers input field
*
*/
protected String getModifiersLabel() {
return NewWizardMessages.NewTypeWizardPage_modifiers_acc_label;
}
/**
* Returns the label that is used for the super class input field.
*
* @return the label that is used for the super class input field.
*
*/
protected String getSuperClassLabel() {
return NewWizardMessages.NewTypeWizardPage_superclass_label;
}
/**
* Returns the label that is used for the super interfaces input field.
*
* @return the label that is used for the super interfaces input field.
*
*/
protected String getSuperInterfacesLabel() {
if (fTypeKind != INTERFACE_TYPE)
return NewWizardMessages.NewTypeWizardPage_interfaces_class_label;
return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label;
}
/**
* Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createSeparator(Composite composite, int nColumns) {
(new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1));
}
/**
* Creates the controls for the package name field. Expects a <code>GridLayout</code> with at
* least 4 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createPackageControls(Composite composite, int nColumns) {
fPackageDialogField.doFillIntoGrid(composite, nColumns);
Text text= fPackageDialogField.getTextControl(null);
LayoutUtil.setWidthHint(text, getMaxFieldWidth());
LayoutUtil.setHorizontalGrabbing(text);
ControlContentAssistHelper.createTextContentAssistant(text, fCurrPackageCompletionProcessor);
TextFieldNavigationHandler.install(text);
}
/**
* Creates the controls for the enclosing type name field. Expects a <code>GridLayout</code> with at
* least 4 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createEnclosingTypeControls(Composite composite, int nColumns) {
// #6891
Composite tabGroup= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginWidth= 0;
layout.marginHeight= 0;
tabGroup.setLayout(layout);
fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1);
Text text= fEnclosingTypeDialogField.getTextControl(composite);
text.getAccessible().addAccessibleListener(new AccessibleAdapter() {
public void getName(AccessibleEvent e) {
e.result= NewWizardMessages.NewTypeWizardPage_enclosing_field_description;
}
});
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint= getMaxFieldWidth();
gd.horizontalSpan= 2;
text.setLayoutData(gd);
Button button= fEnclosingTypeDialogField.getChangeControl(composite);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.widthHint = SWTUtil.getButtonWidthHint(button);
button.setLayoutData(gd);
ControlContentAssistHelper.createTextContentAssistant(text, fEnclosingTypeCompletionProcessor);
TextFieldNavigationHandler.install(text);
}
/**
* Creates the controls for the type name field. Expects a <code>GridLayout</code> with at
* least 2 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createTypeNameControls(Composite composite, int nColumns) {
fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1);
DialogField.createEmptySpace(composite);
Text text= fTypeNameDialogField.getTextControl(null);
LayoutUtil.setWidthHint(text, getMaxFieldWidth());
TextFieldNavigationHandler.install(text);
}
/**
* Creates the controls for the modifiers radio/checkbox 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 createModifierControls(Composite composite, int nColumns) {
LayoutUtil.setHorizontalSpan(fAccMdfButtons.getLabelControl(composite), 1);
Control control= fAccMdfButtons.getSelectionButtonsGroup(composite);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= nColumns - 2;
control.setLayoutData(gd);
DialogField.createEmptySpace(composite);
if (fTypeKind == CLASS_TYPE) {
DialogField.createEmptySpace(composite);
control= fOtherMdfButtons.getSelectionButtonsGroup(composite);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= nColumns - 2;
control.setLayoutData(gd);
DialogField.createEmptySpace(composite);
}
}
/**
* Creates the controls for the superclass name 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 createSuperClassControls(Composite composite, int nColumns) {
fSuperClassDialogField.doFillIntoGrid(composite, nColumns);
Text text= fSuperClassDialogField.getTextControl(null);
LayoutUtil.setWidthHint(text, getMaxFieldWidth());
JavaTypeCompletionProcessor superClassCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
superClassCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() {
public StubTypeContext getStubTypeContext() {
return getSuperClassStubTypeContext();
}
});
ControlContentAssistHelper.createTextContentAssistant(text, superClassCompletionProcessor);
TextFieldNavigationHandler.install(text);
}
/**
* Creates the controls for the superclass name 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 createSuperInterfacesControls(Composite composite, int nColumns) {
final String INTERFACE= "interface"; //$NON-NLS-1$
fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns);
final TableViewer tableViewer= fSuperInterfacesDialogField.getTableViewer();
tableViewer.setColumnProperties(new String[] {INTERFACE});
TableTextCellEditor cellEditor= new TableTextCellEditor(tableViewer, 0) {
protected void doSetFocus() {
if (text != null) {
text.setFocus();
text.setSelection(text.getText().length());
checkSelection();
checkDeleteable();
checkSelectable();
}
}
};
JavaTypeCompletionProcessor superInterfaceCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
superInterfaceCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() {
public StubTypeContext getStubTypeContext() {
return getSuperInterfacesStubTypeContext();
}
});
SubjectControlContentAssistant contentAssistant= ControlContentAssistHelper.createJavaContentAssistant(superInterfaceCompletionProcessor);
Text cellEditorText= cellEditor.getText();
ContentAssistHandler.createHandlerForText(cellEditorText, contentAssistant);
TextFieldNavigationHandler.install(cellEditorText);
cellEditor.setContentAssistant(contentAssistant);
tableViewer.setCellEditors(new CellEditor[] { cellEditor });
tableViewer.setCellModifier(new ICellModifier() {
public void modify(Object element, String property, Object value) {
if (element instanceof Item)
element = ((Item) element).getData();
((InterfaceWrapper) element).interfaceName= (String) value;
fSuperInterfacesDialogField.elementChanged(element);
}
public Object getValue(Object element, String property) {
return ((InterfaceWrapper) element).interfaceName;
}
public boolean canModify(Object element, String property) {
return true;
}
});
tableViewer.getTable().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent event) {
if (event.keyCode == SWT.F2 && event.stateMask == 0) {
ISelection selection= tableViewer.getSelection();
if (! (selection instanceof IStructuredSelection))
return;
IStructuredSelection structuredSelection= (IStructuredSelection) selection;
tableViewer.editElement(structuredSelection.getFirstElement(), 0);
}
}
});
GridData gd= (GridData) fSuperInterfacesDialogField.getListControl(null).getLayoutData();
if (fTypeKind == CLASS_TYPE) {
gd.heightHint= convertHeightInCharsToPixels(3);
} else {
gd.heightHint= convertHeightInCharsToPixels(6);
}
gd.grabExcessVerticalSpace= false;
gd.widthHint= getMaxFieldWidth();
}
/**
* Creates the controls for the preference page links. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*
*
*/
protected void createCommentControls(Composite composite, int nColumns) {
Link link= new Link(composite, SWT.NONE);
link.setText(NewWizardMessages.NewTypeWizardPage_addcomment_description);
link.addSelectionListener(new TypeFieldsAdapter());
link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, nColumns, 1));
DialogField.createEmptySpace(composite);
fAddCommentButton.doFillIntoGrid(composite, nColumns - 1);
}
/**
* Sets the focus on the type name input field.
*/
protected void setFocus() {
fTypeNameDialogField.setFocus();
}
// -------- TypeFieldsAdapter --------
private class TypeFieldsAdapter implements IStringButtonAdapter, IDialogFieldListener, IListAdapter, SelectionListener {
// -------- IStringButtonAdapter
public void changeControlPressed(DialogField field) {
typePageChangeControlPressed(field);
}
// -------- IListAdapter
public void customButtonPressed(ListDialogField field, int index) {
typePageCustomButtonPressed(field, index);
}
public void selectionChanged(ListDialogField field) {}
// -------- IDialogFieldListener
public void dialogFieldChanged(DialogField field) {
typePageDialogFieldChanged(field);
}
public void doubleClicked(ListDialogField field) {
}
public void widgetSelected(SelectionEvent e) {
typePageLinkActivated(e);
}
public void widgetDefaultSelected(SelectionEvent e) {
typePageLinkActivated(e);
}
}
private void typePageLinkActivated(SelectionEvent e) {
IJavaScriptProject project= getJavaProject();
if (project != null) {
PreferenceDialog dialog= PreferencesUtil.createPropertyDialogOn(getShell(), project.getProject(), CodeTemplatePreferencePage.PROP_ID, null, null);
dialog.open();
} else {
String title= NewWizardMessages.NewTypeWizardPage_configure_templates_title;
String message= NewWizardMessages.NewTypeWizardPage_configure_templates_message;
MessageDialog.openInformation(getShell(), title, message);
}
}
private void typePageChangeControlPressed(DialogField field) {
if (field == fPackageDialogField) {
IPackageFragment pack= choosePackage();
if (pack != null) {
fPackageDialogField.setText(pack.getElementName());
}
} else if (field == fEnclosingTypeDialogField) {
IType type= chooseEnclosingType();
if (type != null) {
fEnclosingTypeDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
}
} else if (field == fSuperClassDialogField) {
IType type= chooseSuperClass();
if (type != null) {
fSuperClassDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
}
}
}
private void typePageCustomButtonPressed(DialogField field, int index) {
if (field == fSuperInterfacesDialogField) {
List interfaces= fSuperInterfacesDialogField.getElements();
if (!interfaces.isEmpty()) {
Object element= interfaces.get(interfaces.size() - 1);
fSuperInterfacesDialogField.editElement(element);
}
}
}
/*
* A field on the type has changed. The fields' status and all dependent
* status are updated.
*/
private void typePageDialogFieldChanged(DialogField field) {
String fieldName= null;
if (field == fPackageDialogField) {
fPackageStatus= packageChanged();
updatePackageStatusLabel();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= PACKAGE;
} else if (field == fEnclosingTypeDialogField) {
fEnclosingTypeStatus= enclosingTypeChanged();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= ENCLOSING;
} else if (field == fEnclosingTypeSelection) {
updateEnableState();
boolean isEnclosedType= isEnclosingTypeSelected();
if (!isEnclosedType) {
if (fAccMdfButtons.isSelected(PRIVATE_INDEX) || fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
fAccMdfButtons.setSelection(PRIVATE_INDEX, false);
fAccMdfButtons.setSelection(PROTECTED_INDEX, false);
fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
}
if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {
fOtherMdfButtons.setSelection(STATIC_INDEX, false);
}
}
fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, isEnclosedType);
fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, isEnclosedType);
fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, isEnclosedType);
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= ENCLOSINGSELECTION;
} else if (field == fTypeNameDialogField) {
fTypeNameStatus= typeNameChanged();
fieldName= TYPENAME;
} else if (field == fSuperClassDialogField) {
fSuperClassStatus= superClassChanged();
fieldName= SUPER;
} else if (field == fSuperInterfacesDialogField) {
fSuperInterfacesStatus= superInterfacesChanged();
fieldName= INTERFACES;
} else if (field == fOtherMdfButtons || field == fAccMdfButtons) {
fModifierStatus= modifiersChanged();
fieldName= MODIFIERS;
} else {
fieldName= METHODS;
}
// tell all others
handleFieldChanged(fieldName);
}
// -------- update message ----------------
/*
* @see org.eclipse.wst.jsdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
*/
protected void handleFieldChanged(String fieldName) {
super.handleFieldChanged(fieldName);
if (fieldName == CONTAINER) {
fPackageStatus= packageChanged();
fEnclosingTypeStatus= enclosingTypeChanged();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fSuperInterfacesStatus= superInterfacesChanged();
}
}
// ---- set / get ----------------
/**
* Returns the text of the package input field.
*
* @return the text of the package input field
*/
public String getPackageText() {
return fPackageDialogField.getText();
}
/**
* Returns the text of the enclosing type input field.
*
* @return the text of the enclosing type input field
*/
public String getEnclosingTypeText() {
return fEnclosingTypeDialogField.getText();
}
/**
* Returns the package fragment corresponding to the current input.
*
* @return a package fragment or <code>null</code> if the input
* could not be resolved.
*/
public IPackageFragment getPackageFragment() {
if (!isEnclosingTypeSelected()) {
return fCurrPackage;
} else {
if (fCurrEnclosingType != null) {
return fCurrEnclosingType.getPackageFragment();
}
}
return null;
}
/**
* Sets the package fragment to the given value. The method updates the model
* and the text of the control.
*
* @param pack the package fragment to be set
* @param canBeModified if <code>true</code> the package fragment is
* editable; otherwise it is read-only.
*/
public void setPackageFragment(IPackageFragment pack, boolean canBeModified) {
fCurrPackage= pack;
fCanModifyPackage= canBeModified;
String str= (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$
fPackageDialogField.setText(str);
updateEnableState();
}
/**
* Returns the enclosing type corresponding to the current input.
*
* @return the enclosing type or <code>null</code> if the enclosing type is
* not selected or the input could not be resolved
*/
public IType getEnclosingType() {
if (isEnclosingTypeSelected()) {
return fCurrEnclosingType;
}
return null;
}
/**
* Sets the enclosing type. The method updates the underlying model
* and the text of the control.
*
* @param type the enclosing type
* @param canBeModified if <code>true</code> the enclosing type field is
* editable; otherwise it is read-only.
*/
public void setEnclosingType(IType type, boolean canBeModified) {
fCurrEnclosingType= type;
fCanModifyEnclosingType= canBeModified;
String str= (type == null) ? "" : JavaModelUtil.getFullyQualifiedName(type); //$NON-NLS-1$
fEnclosingTypeDialogField.setText(str);
updateEnableState();
}
/**
* Returns the selection state of the enclosing type checkbox.
*
* @return the selection state of the enclosing type checkbox
*/
public boolean isEnclosingTypeSelected() {
return fEnclosingTypeSelection.isSelected();
}
/**
* Sets the enclosing type checkbox's selection state.
*
* @param isSelected the checkbox's selection state
* @param canBeModified if <code>true</code> the enclosing type checkbox is
* modifiable; otherwise it is read-only.
*/
public void setEnclosingTypeSelection(boolean isSelected, boolean canBeModified) {
fEnclosingTypeSelection.setSelection(isSelected);
fEnclosingTypeSelection.setEnabled(canBeModified);
updateEnableState();
}
/**
* Returns the type name entered into the type input field.
*
* @return the type name
*/
public String getTypeName() {
return fTypeNameDialogField.getText();
}
/**
* Sets the type name input field's text to the given value. Method doesn't update
* the model.
*
* @param name the new type name
* @param canBeModified if <code>true</code> the type name field is
* editable; otherwise it is read-only.
*/
public void setTypeName(String name, boolean canBeModified) {
fTypeNameDialogField.setText(name);
fTypeNameDialogField.setEnabled(canBeModified);
}
/**
* Returns the selected modifiers.
*
* @return the selected modifiers
* @see Flags
*/
public int getModifiers() {
int mdf= 0;
if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) {
mdf+= F_PUBLIC;
} else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) {
mdf+= F_PRIVATE;
}
if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX)) {
mdf+= F_ABSTRACT;
}
if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {
mdf+= F_STATIC;
}
return mdf;
}
/**
* Sets the modifiers.
*
* @param modifiers <code>F_PUBLIC</code>, <code>F_PRIVATE</code>,
* <code>F_PROTECTED</code>, <code>F_ABSTRACT</code>, <code>F_FINAL</code>
* or <code>F_STATIC</code> or a valid combination.
* @param canBeModified if <code>true</code> the modifier fields are
* editable; otherwise they are read-only
* @see Flags
*/
public void setModifiers(int modifiers, boolean canBeModified) {
if (Flags.isPublic(modifiers)) {
fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
} else if (Flags.isPrivate(modifiers)) {
fAccMdfButtons.setSelection(PRIVATE_INDEX, true);
} else {
fAccMdfButtons.setSelection(DEFAULT_INDEX, true);
}
if (Flags.isAbstract(modifiers)) {
fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true);
}
if (Flags.isStatic(modifiers)) {
fOtherMdfButtons.setSelection(STATIC_INDEX, true);
}
fAccMdfButtons.setEnabled(canBeModified);
fOtherMdfButtons.setEnabled(canBeModified);
}
/**
* Returns the content of the superclass input field.
*
* @return the superclass name
*/
public String getSuperClass() {
return fSuperClassDialogField.getText();
}
/**
* Sets the super class name.
*
* @param name the new superclass name
* @param canBeModified if <code>true</code> the superclass name field is
* editable; otherwise it is read-only.
*/
public void setSuperClass(String name, boolean canBeModified) {
fSuperClassDialogField.setText(name);
fSuperClassDialogField.setEnabled(canBeModified);
}
/**
* Returns the chosen super interfaces.
*
* @return a list of chosen super interfaces. The list's elements
* are of type <code>String</code>
*/
public List getSuperInterfaces() {
List interfaces= fSuperInterfacesDialogField.getElements();
ArrayList result= new ArrayList(interfaces.size());
for (Iterator iter= interfaces.iterator(); iter.hasNext();) {
InterfaceWrapper wrapper= (InterfaceWrapper) iter.next();
result.add(wrapper.interfaceName);
}
return result;
}
/**
* Sets the super interfaces.
*
* @param interfacesNames a list of super interface. The method requires that
* the list's elements are of type <code>String</code>
* @param canBeModified if <code>true</code> the super interface field is
* editable; otherwise it is read-only.
*/
public void setSuperInterfaces(List interfacesNames, boolean canBeModified) {
ArrayList interfaces= new ArrayList(interfacesNames.size());
for (Iterator iter= interfacesNames.iterator(); iter.hasNext();) {
interfaces.add(new InterfaceWrapper((String) iter.next()));
}
fSuperInterfacesDialogField.setElements(interfaces);
fSuperInterfacesDialogField.setEnabled(canBeModified);
}
/**
* Adds a super interface to the end of the list and selects it if it is not in the list yet.
*
* @param superInterface the fully qualified type name of the interface.
* @return returns <code>true</code>if the interfaces has been added, <code>false</code>
* if the interface already is in the list.
*
*/
public boolean addSuperInterface(String superInterface) {
return fSuperInterfacesDialogField.addElement(new InterfaceWrapper(superInterface));
}
/**
* Sets 'Add comment' checkbox. The value set will only be used when creating source when
* the comment control is enabled (see {@link #enableCommentControl(boolean)}
*
* @param doAddComments if <code>true</code>, comments are added.
* @param canBeModified if <code>true</code> check box is
* editable; otherwise it is read-only.
*
*/
public void setAddComments(boolean doAddComments, boolean canBeModified) {
fAddCommentButton.setSelection(doAddComments);
fAddCommentButton.setEnabled(canBeModified);
}
/**
* Sets to use the 'Add comment' checkbox value. Clients that use the 'Add comment' checkbox
* additionally have to enable the control. This has been added for backwards compatibility.
*
* @param useAddCommentValue if <code>true</code>,
*
*/
public void enableCommentControl(boolean useAddCommentValue) {
fUseAddCommentButtonValue= useAddCommentValue;
}
/**
* Returns if comments are added. This method can be overridden by clients.
* The selection of the comment control is taken if enabled (see {@link #enableCommentControl(boolean)}, otherwise
* the settings as specified in the preferences is used.
*
* @return Returns <code>true</code> if comments can be added
*
*/
public boolean isAddComments() {
if (fUseAddCommentButtonValue) {
return fAddCommentButton.isSelected();
}
return StubUtility.doAddComments(getJavaProject());
}
/**
* Returns the resource handle that corresponds to the compilation unit to was or
* will be created or modified.
* @return A resource or null if the page contains illegal values.
*
*/
public IResource getModifiedResource() {
IType enclosing= getEnclosingType();
if (enclosing != null) {
return enclosing.getResource();
}
IPackageFragment pack= getPackageFragment();
if (pack != null) {
String cuName= getCompilationUnitName(getTypeNameWithoutParameters());
return pack.getJavaScriptUnit(cuName).getResource();
}
return null;
}
// ----------- validation ----------
/*
* @see org.eclipse.wst.jsdt.ui.wizards.NewContainerWizardPage#containerChanged()
*/
protected IStatus containerChanged() {
IStatus status= super.containerChanged();
IPackageFragmentRoot root= getPackageFragmentRoot();
if ((fTypeKind == ANNOTATION_TYPE || fTypeKind == ENUM_TYPE) && !status.matches(IStatus.ERROR)) {
if (root != null && !JavaModelUtil.is50OrHigher(root.getJavaScriptProject())) {
// error as createType will fail otherwise (bug 96928)
return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant, root.getJavaScriptProject().getElementName()));
}
if (fTypeKind == ENUM_TYPE) {
try {
// if findType(...) == null then Enum is unavailable
if (findType(root.getJavaScriptProject(), "java.lang.Enum") == null) //$NON-NLS-1$
return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_EnumClassNotFound);
} catch (JavaScriptModelException e) {
JavaScriptPlugin.log(e);
}
}
}
fCurrPackageCompletionProcessor.setPackageFragmentRoot(root);
if (root != null) {
fEnclosingTypeCompletionProcessor.setPackageFragment(root.getPackageFragment("")); //$NON-NLS-1$
}
return status;
}
/**
* A hook method that gets called when the package field has changed. The method
* validates the package name and returns the status of the validation. The validation
* also updates the package fragment model.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus packageChanged() {
StatusInfo status= new StatusInfo();
IPackageFragmentRoot root= getPackageFragmentRoot();
fPackageDialogField.enableButton(root != null);
IJavaScriptProject project= root != null ? root.getJavaScriptProject() : null;
String packName= getPackageText();
if (packName.length() > 0) {
IStatus val= validatePackageName(packName, project);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidPackageName, val.getMessage()));
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_DiscouragedPackageName, val.getMessage()));
// continue
}
} else {
status.setWarning(NewWizardMessages.NewTypeWizardPage_warning_DefaultPackageDiscouraged);
}
if (project != null) {
fCurrPackage= root.getPackageFragment(packName);
} else {
status.setError(""); //$NON-NLS-1$
}
return status;
}
/*
* Updates the 'default' label next to the package field.
*/
private void updatePackageStatusLabel() {
String packName= getPackageText();
if (packName.length() == 0) {
fPackageDialogField.setStatus(NewWizardMessages.NewTypeWizardPage_default);
} else {
fPackageDialogField.setStatus(""); //$NON-NLS-1$
}
}
/*
* Updates the enable state of buttons related to the enclosing type selection checkbox.
*/
private void updateEnableState() {
boolean enclosing= isEnclosingTypeSelected();
fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing);
fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType && enclosing);
if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, enclosing);
fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, enclosing);
}
}
/**
* Hook method that gets called when the enclosing type name has changed. The method
* validates the enclosing type and returns the status of the validation. It also updates the
* enclosing type model.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus enclosingTypeChanged() {
StatusInfo status= new StatusInfo();
fCurrEnclosingType= null;
IPackageFragmentRoot root= getPackageFragmentRoot();
fEnclosingTypeDialogField.enableButton(root != null);
if (root == null) {
status.setError(""); //$NON-NLS-1$
return status;
}
String enclName= getEnclosingTypeText();
if (enclName.length() == 0) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeEnterName);
return status;
}
try {
IType type= findType(root.getJavaScriptProject(), enclName);
if (type == null) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists);
return status;
}
if (type.getJavaScriptUnit() == null) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotInCU);
return status;
}
if (!JavaModelUtil.isEditable(type.getJavaScriptUnit())) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotEditable);
return status;
}
fCurrEnclosingType= type;
IPackageFragmentRoot enclosingRoot= JavaModelUtil.getPackageFragmentRoot(type);
if (!enclosingRoot.equals(root)) {
status.setWarning(NewWizardMessages.NewTypeWizardPage_warning_EnclosingNotInSourceFolder);
}
return status;
} catch (JavaScriptModelException e) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists);
JavaScriptPlugin.log(e);
return status;
}
}
private IType findType(IJavaScriptProject project, String typeName) throws JavaScriptModelException {
if (project.exists()) {
return project.findType(typeName);
}
return null;
}
private String getTypeNameWithoutParameters() {
String typeNameWithParameters= getTypeName();
int angleBracketOffset= typeNameWithParameters.indexOf('<');
if (angleBracketOffset == -1) {
return typeNameWithParameters;
} else {
return typeNameWithParameters.substring(0, angleBracketOffset);
}
}
/**
* Hook method that is called when evaluating the name of the compilation unit to create. By default, a file extension
* <code>java</code> is added to the given type name, but implementors can override this behavior.
*
* @param typeName the name of the type to create the compilation unit for.
* @return the name of the compilation unit to be created for the given name
*
*
*/
protected String getCompilationUnitName(String typeName) {
return typeName + JavaModelUtil.DEFAULT_CU_SUFFIX;
}
/**
* Hook method that gets called when the type name has changed. The method validates the
* type name and 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 typeNameChanged() {
StatusInfo status= new StatusInfo();
fCurrType= null;
String typeNameWithParameters= getTypeName();
// must not be empty
if (typeNameWithParameters.length() == 0) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_EnterTypeName);
return status;
}
String typeName= getTypeNameWithoutParameters();
if (typeName.indexOf('.') != -1) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_QualifiedName);
return status;
}
IJavaScriptProject project= getJavaProject();
IStatus val= validateJavaTypeName(typeName, project);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, val.getMessage()));
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_TypeNameDiscouraged, val.getMessage()));
// continue checking
}
// must not exist
if (!isEnclosingTypeSelected()) {
IPackageFragment pack= getPackageFragment();
if (pack != null) {
IJavaScriptUnit cu= pack.getJavaScriptUnit(getCompilationUnitName(typeName));
fCurrType= cu.getType(typeName);
IResource resource= cu.getResource();
if (resource.exists()) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists);
return status;
}
URI location= resource.getLocationURI();
if (location != null) {
try {
IFileStore store= EFS.getStore(location);
if (store.fetchInfo().exists()) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExistsDifferentCase);
return status;
}
} catch (CoreException e) {
status.setError(Messages.format(
NewWizardMessages.NewTypeWizardPage_error_uri_location_unkown,
Resources.getLocationString(resource)));
}
}
}
} else {
IType type= getEnclosingType();
if (type != null) {
fCurrType= type.getType(typeName);
if (fCurrType.exists()) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists);
return status;
}
}
}
if (!typeNameWithParameters.equals(typeName) && project != null) {
if (!JavaModelUtil.is50OrHigher(project)) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeParameters);
return status;
}
String typeDeclaration= "class " + typeNameWithParameters + " {}"; //$NON-NLS-1$//$NON-NLS-2$
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setSource(typeDeclaration.toCharArray());
parser.setProject(project);
JavaScriptUnit compilationUnit= (JavaScriptUnit) parser.createAST(null);
IProblem[] problems= compilationUnit.getProblems();
if (problems.length > 0) {
status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, problems[0].getMessage()));
return status;
}
}
return status;
}
/**
* Hook method that gets called when the superclass name has changed. The method
* validates the superclass name and 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 superClassChanged() {
StatusInfo status= new StatusInfo();
IPackageFragmentRoot root= getPackageFragmentRoot();
fSuperClassDialogField.enableButton(root != null);
fSuperClassStubTypeContext= null;
String sclassName= getSuperClass();
if (sclassName.length() == 0) {
// accept the empty field (stands for java.lang.Object)
return status;
}
if (root != null) {
Type type= TypeContextChecker.parseSuperClass(sclassName);
if (type == null) {
status.setError(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassName);
return status;
}
} else {
status.setError(""); //$NON-NLS-1$
}
return status;
}
private StubTypeContext getSuperClassStubTypeContext() {
if (fSuperClassStubTypeContext == null) {
String typeName;
if (fCurrType != null) {
typeName= getTypeName();
} else {
typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
}
fSuperClassStubTypeContext= TypeContextChecker.createSuperClassStubTypeContext(typeName, getEnclosingType(), getPackageFragment());
}
return fSuperClassStubTypeContext;
}
/**
* Hook method that gets called when the list of super interface has changed. The method
* validates the super interfaces and 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 superInterfacesChanged() {
StatusInfo status= new StatusInfo();
IPackageFragmentRoot root= getPackageFragmentRoot();
fSuperInterfacesDialogField.enableButton(0, root != null);
if (root != null) {
List elements= fSuperInterfacesDialogField.getElements();
int nElements= elements.size();
for (int i= 0; i < nElements; i++) {
String intfname= ((InterfaceWrapper) elements.get(i)).interfaceName;
Type type= TypeContextChecker.parseSuperInterface(intfname);
if (type == null) {
status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperInterfaceName, intfname));
return status;
}
}
}
return status;
}
private StubTypeContext getSuperInterfacesStubTypeContext() {
if (fSuperInterfaceStubTypeContext == null) {
String typeName;
if (fCurrType != null) {
typeName= getTypeName();
} else {
typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
}
fSuperInterfaceStubTypeContext= TypeContextChecker.createSuperInterfaceStubTypeContext(typeName, getEnclosingType(), getPackageFragment());
}
return fSuperInterfaceStubTypeContext;
}
/**
* Hook method that gets called when the modifiers have changed. The method validates
* the modifiers and 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 modifiersChanged() {
StatusInfo status= new StatusInfo();
return status;
}
// selection dialogs
/**
* Opens a selection dialog that allows to select a package.
*
* @return returns the selected package or <code>null</code> if the dialog has been canceled.
* The caller typically sets the result to the package input field.
* <p>
* Clients can override this method if they want to offer a different dialog.
* </p>
*
*
*/
protected IPackageFragment choosePackage() {
IPackageFragmentRoot froot= getPackageFragmentRoot();
IJavaScriptElement[] packages= null;
try {
if (froot != null && froot.exists()) {
packages= froot.getChildren();
}
} catch (JavaScriptModelException e) {
JavaScriptPlugin.log(e);
}
if (packages == null) {
packages= new IJavaScriptElement[0];
}
ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaScriptElementLabelProvider(JavaScriptElementLabelProvider.SHOW_DEFAULT));
dialog.setIgnoreCase(false);
dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_title);
dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_description);
dialog.setEmptyListMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_empty);
dialog.setElements(packages);
dialog.setHelpAvailable(false);
IPackageFragment pack= getPackageFragment();
if (pack != null) {
dialog.setInitialSelections(new Object[] { pack });
}
if (dialog.open() == Window.OK) {
return (IPackageFragment) dialog.getFirstResult();
}
return null;
}
/**
* Opens a selection dialog that allows to select an enclosing type.
*
* @return returns the selected type or <code>null</code> if the dialog has been canceled.
* The caller typically sets the result to the enclosing type input field.
* <p>
* Clients can override this method if they want to offer a different dialog.
* </p>
*
*
*/
protected IType chooseEnclosingType() {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return null;
}
IJavaScriptSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaScriptElement[] { root });
FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(),
false, getWizard().getContainer(), scope, IJavaScriptSearchConstants.TYPE);
dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_title);
dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_description);
dialog.setInitialPattern(Signature.getSimpleName(getEnclosingTypeText()));
if (dialog.open() == Window.OK) {
return (IType) dialog.getFirstResult();
}
return null;
}
/**
* Opens a selection dialog that allows to select a super class.
*
* @return returns the selected type or <code>null</code> if the dialog has been canceled.
* The caller typically sets the result to the super class input field.
* <p>
* Clients can override this method if they want to offer a different dialog.
* </p>
*
*
*/
protected IType chooseSuperClass() {
IJavaScriptProject project= getJavaProject();
if (project == null) {
return null;
}
IJavaScriptElement[] elements= new IJavaScriptElement[] { project };
IJavaScriptSearchScope scope= SearchEngine.createJavaSearchScope(elements);
FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), false,
getWizard().getContainer(), scope, IJavaScriptSearchConstants.CLASS);
dialog.setTitle(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_title);
dialog.setMessage(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_message);
dialog.setInitialPattern(getSuperClass());
if (dialog.open() == Window.OK) {
return (IType) dialog.getFirstResult();
}
return null;
}
// ---- creation ----------------
/**
* Creates the new type using the entered field values.
*
* @param monitor a progress monitor to report progress.
* @throws CoreException Thrown when the creation failed.
* @throws InterruptedException Thrown when the operation was canceled.
*/
public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
monitor.beginTask(NewWizardMessages.NewTypeWizardPage_operationdesc, 8);
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, new SubProgressMonitor(monitor, 1));
} else {
monitor.worked(1);
}
boolean needsSave;
IJavaScriptUnit connectedCU= null;
try {
String typeName= getTypeNameWithoutParameters();
boolean isInnerClass= isEnclosingTypeSelected();
IType createdType;
ImportsManager imports;
int indent= 0;
Set /* String (import names) */ existingImports;
String lineDelimiter= null;
if (!isInnerClass) {
lineDelimiter= StubUtility.getLineDelimiterUsed(pack.getJavaScriptProject());
String cuName= getCompilationUnitName(typeName);
IJavaScriptUnit parentCU= pack.createCompilationUnit(cuName, "", false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$
// create a working copy with a new owner
needsSave= true;
parentCU.becomeWorkingCopy(new SubProgressMonitor(monitor, 1)); // cu is now a (primary) working copy
connectedCU= parentCU;
IBuffer buffer= parentCU.getBuffer();
String simpleTypeStub= constructSimpleTypeStub();
String cuContent= constructCUContent(parentCU, simpleTypeStub, lineDelimiter);
buffer.setContents(cuContent);
JavaScriptUnit astRoot= createASTForImports(parentCU);
existingImports= getExistingImports(astRoot);
imports= new ImportsManager(astRoot);
// add an import that will be removed again. Having this import solves 14661
imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), typeName));
String typeContent= constructTypeStub(parentCU, imports, lineDelimiter);
int index= cuContent.lastIndexOf(simpleTypeStub);
if (index == -1) {
AbstractTypeDeclaration typeNode= (AbstractTypeDeclaration) astRoot.types().get(0);
int start= ((ASTNode) typeNode.modifiers().get(0)).getStartPosition();
int end= typeNode.getStartPosition() + typeNode.getLength();
buffer.replace(start, end - start, typeContent);
} else {
buffer.replace(index, simpleTypeStub.length(), typeContent);
}
createdType= parentCU.getType(typeName);
} else {
IType enclosingType= getEnclosingType();
IJavaScriptUnit parentCU= enclosingType.getJavaScriptUnit();
needsSave= !parentCU.isWorkingCopy();
parentCU.becomeWorkingCopy(new SubProgressMonitor(monitor, 1)); // cu is now for sure (primary) a working copy
connectedCU= parentCU;
JavaScriptUnit astRoot= createASTForImports(parentCU);
imports= new ImportsManager(astRoot);
existingImports= getExistingImports(astRoot);
// add imports that will be removed again. Having the imports solves 14661
IType[] topLevelTypes= parentCU.getTypes();
for (int i= 0; i < topLevelTypes.length; i++) {
imports.addImport(topLevelTypes[i].getFullyQualifiedName('.'));
}
lineDelimiter= StubUtility.getLineDelimiterUsed(enclosingType);
StringBuffer content= new StringBuffer();
String comment= getTypeComment(parentCU, lineDelimiter);
if (comment != null) {
content.append(comment);
content.append(lineDelimiter);
}
content.append(constructTypeStub(parentCU, imports, lineDelimiter));
IJavaScriptElement sibling= null;
IJavaScriptElement[] elems= enclosingType.getChildren();
sibling = elems.length > 0 ? elems[0] : null;
createdType= enclosingType.createType(content.toString(), sibling, false, new SubProgressMonitor(monitor, 2));
indent= StubUtility.getIndentUsed(enclosingType) + 1;
}
if (monitor.isCanceled()) {
throw new InterruptedException();
}
// add imports for superclass/interfaces, so types can be resolved correctly
IJavaScriptUnit cu= createdType.getJavaScriptUnit();
imports.create(false, new SubProgressMonitor(monitor, 1));
JavaModelUtil.reconcile(cu);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
// set up again
JavaScriptUnit astRoot= createASTForImports(imports.getCompilationUnit());
imports= new ImportsManager(astRoot);
createTypeMembers(createdType, imports, new SubProgressMonitor(monitor, 1));
// add imports
imports.create(false, new SubProgressMonitor(monitor, 1));
removeUnusedImports(cu, existingImports, false);
JavaModelUtil.reconcile(cu);
ISourceRange range= createdType.getSourceRange();
IBuffer buf= cu.getBuffer();
String originalContent= buf.getText(range.getOffset(), range.getLength());
String formattedContent= CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, indent, null, lineDelimiter, pack.getJavaScriptProject());
formattedContent= Strings.trimLeadingTabsAndSpaces(formattedContent);
buf.replace(range.getOffset(), range.getLength(), formattedContent);
if (!isInnerClass) {
String fileComment= getFileComment(cu);
if (fileComment != null && fileComment.length() > 0) {
buf.replace(0, 0, fileComment + lineDelimiter);
}
}
fCreatedType= createdType;
if (needsSave) {
cu.commitWorkingCopy(true, new SubProgressMonitor(monitor, 1));
} else {
monitor.worked(1);
}
} finally {
if (connectedCU != null) {
connectedCU.discardWorkingCopy();
}
monitor.done();
}
}
private JavaScriptUnit createASTForImports(IJavaScriptUnit cu) {
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setSource(cu);
parser.setResolveBindings(false);
parser.setFocalPosition(0);
return (JavaScriptUnit) parser.createAST(null);
}
private Set /* String */ getExistingImports(JavaScriptUnit root) {
List imports= root.imports();
Set res= new HashSet(imports.size());
for (int i= 0; i < imports.size(); i++) {
res.add(ASTNodes.asString((ImportDeclaration) imports.get(i)));
}
return res;
}
private void removeUnusedImports(IJavaScriptUnit cu, Set existingImports, boolean needsSave) throws CoreException {
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setSource(cu);
parser.setResolveBindings(true);
JavaScriptUnit root= (JavaScriptUnit) parser.createAST(null);
if (root.getProblems().length == 0) {
return;
}
List importsDecls= root.imports();
if (importsDecls.isEmpty()) {
return;
}
ImportsManager imports= new ImportsManager(root);
int importsEnd= ASTNodes.getExclusiveEnd((ASTNode) importsDecls.get(importsDecls.size() - 1));
IProblem[] problems= root.getProblems();
for (int i= 0; i < problems.length; i++) {
IProblem curr= problems[i];
if (curr.getSourceEnd() < importsEnd) {
int id= curr.getID();
if( id == IProblem.NotVisibleType) { // not visible problems hide unused -> remove both
int pos= curr.getSourceStart();
for (int k= 0; k < importsDecls.size(); k++) {
ImportDeclaration decl= (ImportDeclaration) importsDecls.get(k);
if (decl.getStartPosition() <= pos && pos < decl.getStartPosition() + decl.getLength()) {
if (existingImports.isEmpty() || !existingImports.contains(ASTNodes.asString(decl))) {
String name= decl.getName().getFullyQualifiedName();
if (decl.isOnDemand()) {
name += ".*"; //$NON-NLS-1$
}
if (decl.isStatic()) {
imports.removeStaticImport(name);
} else {
imports.removeImport(name);
}
}
break;
}
}
}
}
}
imports.create(needsSave, null);
}
/**
* Uses the New JavaScript 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(IJavaScriptUnit cu, String typeContent, String lineDelimiter) throws CoreException {
String fileComment= getFileComment(cu, lineDelimiter);
String typeComment= getTypeComment(cu, lineDelimiter);
IPackageFragment pack= (IPackageFragment) cu.getParent();
String content= CodeGeneration.getCompilationUnitContent(cu, fileComment, typeComment, typeContent, lineDelimiter);
if (content != null) {
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setProject(cu.getJavaScriptProject());
parser.setSource(content.toCharArray());
JavaScriptUnit unit= (JavaScriptUnit) 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();
}
/**
* Returns the created type or <code>null</code> is the type has not been created yet. The method
* only returns a valid type after <code>createType</code> has been called.
*
* @return the created type
* @see #createType(IProgressMonitor)
*/
public IType getCreatedType() {
return fCreatedType;
}
// ---- construct CU body----------------
private void writeSuperClass(StringBuffer buf, ImportsManager imports) {
String superclass= getSuperClass();
if (fTypeKind == CLASS_TYPE && superclass.length() > 0 && !"java.lang.Object".equals(superclass)) { //$NON-NLS-1$
buf.append(" extends "); //$NON-NLS-1$
ITypeBinding binding= null;
if (fCurrType != null) {
binding= TypeContextChecker.resolveSuperClass(superclass, fCurrType, getSuperClassStubTypeContext());
}
if (binding != null) {
buf.append(imports.addImport(binding));
} else {
buf.append(imports.addImport(superclass));
}
}
}
private void writeSuperInterfaces(StringBuffer buf, ImportsManager imports) {
List interfaces= getSuperInterfaces();
int last= interfaces.size() - 1;
if (last >= 0) {
if (fTypeKind != INTERFACE_TYPE) {
buf.append(" implements "); //$NON-NLS-1$
} else {
buf.append(" extends "); //$NON-NLS-1$
}
String[] intfs= (String[]) interfaces.toArray(new String[interfaces.size()]);
ITypeBinding[] bindings;
if (fCurrType != null) {
bindings= TypeContextChecker.resolveSuperInterfaces(intfs, fCurrType, getSuperInterfacesStubTypeContext());
} else {
bindings= new ITypeBinding[intfs.length];
}
for (int i= 0; i <= last; i++) {
ITypeBinding binding= bindings[i];
if (binding != null) {
buf.append(imports.addImport(binding));
} else {
buf.append(imports.addImport(intfs[i]));
}
if (i < last) {
buf.append(',');
}
}
}
}
private String constructSimpleTypeStub() {
StringBuffer buf= new StringBuffer("public class "); //$NON-NLS-1$
buf.append(getTypeName());
buf.append("{ }"); //$NON-NLS-1$
return buf.toString();
}
/*
* Called from createType to construct the source for this type
*/
private String constructTypeStub(IJavaScriptUnit parentCU, ImportsManager imports, String lineDelimiter) throws CoreException {
StringBuffer buf= new StringBuffer();
int modifiers= getModifiers();
buf.append(Flags.toString(modifiers));
if (modifiers != 0) {
buf.append(' ');
}
String type= ""; //$NON-NLS-1$
String templateID= ""; //$NON-NLS-1$
switch (fTypeKind) {
case CLASS_TYPE:
type= "class "; //$NON-NLS-1$
templateID= CodeGeneration.CLASS_BODY_TEMPLATE_ID;
break;
}
buf.append(type);
buf.append(getTypeName());
writeSuperClass(buf, imports);
writeSuperInterfaces(buf, imports);
buf.append(" {").append(lineDelimiter); //$NON-NLS-1$
String typeBody= CodeGeneration.getTypeBody(templateID, parentCU, getTypeName(), lineDelimiter);
if (typeBody != null) {
buf.append(typeBody);
} else {
buf.append(lineDelimiter);
}
buf.append('}').append(lineDelimiter);
return buf.toString();
}
/**
* Hook method that gets called from <code>createType</code> to support adding of
* unanticipated methods, fields, and inner types to the created type.
* <p>
* Implementers can use any methods defined on <code>IType</code> to manipulate the
* new type.
* </p>
* <p>
* The source code of the new type will be formatted using the platform's formatter. Needed
* imports are added by the wizard at the end of the type creation process using the given
* import manager.
* </p>
*
* @param newType the new type created via <code>createType</code>
* @param imports an import manager which can be used to add new imports
* @param monitor a progress monitor to report progress. Must not be <code>null</code>
* @throws CoreException thrown when creation of the type members failed
*
* @see #createType(IProgressMonitor)
*/
protected void createTypeMembers(IType newType, final ImportsManager imports, IProgressMonitor monitor) throws CoreException {
// default implementation does nothing
// example would be
// String mainMathod= "public void foo(Vector vec) {}"
// createdType.createMethod(main, null, false, null);
// imports.addImport("java.lang.Vector");
}
/**
* @param parentCU the current compilation unit
* @return returns the file template or <code>null</code>
* @deprecated Instead of file templates, the new type code template
* specifies the stub for a compilation unit.
*/
protected String getFileComment(IJavaScriptUnit parentCU) {
return null;
}
/**
* Hook method that gets called from <code>createType</code> to retrieve
* a file comment. This default implementation returns the content of the
* 'file comment' template or <code>null</code> if no comment should be created.
*
* @param parentCU the parent compilation unit
* @param lineDelimiter the line delimiter to use
* @return the file comment or <code>null</code> if a file comment
* is not desired
* @throws CoreException
*
*
*/
protected String getFileComment(IJavaScriptUnit parentCU, String lineDelimiter) throws CoreException {
if (isAddComments()) {
return CodeGeneration.getFileComment(parentCU, lineDelimiter);
}
return null;
}
private 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;
}
/**
* Hook method that gets called from <code>createType</code> to retrieve
* a type comment. This default implementation returns the content of the
* 'type comment' template.
*
* @param parentCU the parent compilation unit
* @param lineDelimiter the line delimiter to use
* @return the type comment or <code>null</code> if a type comment
* is not desired
*
*
*/
protected String getTypeComment(IJavaScriptUnit parentCU, String lineDelimiter) {
if (isAddComments()) {
try {
StringBuffer typeName= new StringBuffer();
if (isEnclosingTypeSelected()) {
typeName.append(JavaModelUtil.getTypeQualifiedName(getEnclosingType())).append('.');
}
typeName.append(getTypeNameWithoutParameters());
String comment= CodeGeneration.getTypeComment(parentCU, typeName.toString(), lineDelimiter);
if (comment != null && isValidComment(comment)) {
return comment;
}
} catch (CoreException e) {
JavaScriptPlugin.log(e);
}
}
return null;
}
/**
* Returns the string resulting from evaluation the given template in
* the context of the given compilation unit. This accesses the normal
* template page, not the code templates. To use code templates use
* <code>constructCUContent</code> to construct a compilation unit stub or
* getTypeComment for the comment of the type.
*
* @param name the template to be evaluated
* @param parentCU the templates evaluation context
* @param pos a source offset into the parent compilation unit. The
* template is evaluated at the given source offset
* @return return the template with the given name or <code>null</code> if the template could not be found.
*/
protected String getTemplate(String name, IJavaScriptUnit parentCU, int pos) {
try {
Template template= JavaScriptPlugin.getDefault().getTemplateStore().findTemplate(name);
if (template != null) {
return JavaContext.evaluateTemplate(template, parentCU, pos);
}
} catch (CoreException e) {
JavaScriptPlugin.log(e);
} catch (BadLocationException e) {
JavaScriptPlugin.log(e);
} catch (TemplateException e) {
JavaScriptPlugin.log(e);
}
return null;
}
/**
* Creates the bodies of all unimplemented methods and constructors and adds them to the type.
* Method is typically called by implementers of <code>NewTypeWizardPage</code> to add
* needed method and constructors.
*
* @param type the type for which the new methods and constructor are to be created
* @param doConstructors if <code>true</code> unimplemented constructors are created
* @param doUnimplementedMethods if <code>true</code> unimplemented methods are created
* @param imports an import manager to add all needed import statements
* @param monitor a progress monitor to report progress
* @return the created methods.
* @throws CoreException thrown when the creation fails.
*/
protected IFunction[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
final IJavaScriptUnit cu= type.getJavaScriptUnit();
JavaModelUtil.reconcile(cu);
IFunction[] typeMethods= type.getFunctions();
Set handleIds= new HashSet(typeMethods.length);
for (int index= 0; index < typeMethods.length; index++)
handleIds.add(typeMethods[index].getHandleIdentifier());
ArrayList newMethods= new ArrayList();
CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaScriptProject());
settings.createComments= isAddComments();
ASTParser parser= ASTParser.newParser(AST.JLS3);
parser.setResolveBindings(true);
parser.setSource(cu);
JavaScriptUnit unit= (JavaScriptUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
final ITypeBinding binding= ASTNodes.getTypeBinding(unit, type);
if (binding != null) {
if (doUnimplementedMethods) {
AddUnimplementedMethodsOperation operation= new AddUnimplementedMethodsOperation(unit, binding, null, -1, false, true, false);
operation.setCreateComments(isAddComments());
operation.run(monitor);
createImports(imports, operation.getCreatedImports());
}
if (doConstructors) {
AddUnimplementedConstructorsOperation operation= new AddUnimplementedConstructorsOperation(unit, binding, null, -1, false, true, false);
operation.setOmitSuper(true);
operation.setCreateComments(isAddComments());
operation.run(monitor);
createImports(imports, operation.getCreatedImports());
}
}
JavaModelUtil.reconcile(cu);
typeMethods= type.getFunctions();
for (int index= 0; index < typeMethods.length; index++)
if (!handleIds.contains(typeMethods[index].getHandleIdentifier()))
newMethods.add(typeMethods[index]);
IFunction[] methods= new IFunction[newMethods.size()];
newMethods.toArray(methods);
return methods;
}
private void createImports(ImportsManager imports, String[] createdImports) {
for (int index= 0; index < createdImports.length; index++)
imports.addImport(createdImports[index]);
}
// ---- creation ----------------
/**
* Returns the runnable that creates the type using the current settings.
* The returned runnable must be executed in the UI thread.
*
* @return the runnable to create the new type
*/
public IRunnableWithProgress getRunnable() {
return new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
createType(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
}
}