/* * Copyright 2003-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.groovy.eclipse.wizards; import org.codehaus.groovy.eclipse.core.GroovyCore; import org.codehaus.groovy.eclipse.core.model.GroovyRuntime; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.codehaus.jdt.groovy.model.GroovyNature; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IImportDeclaration; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageDeclaration; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.groovy.core.util.ReflectionUtils; import org.eclipse.jdt.internal.core.ClasspathEntry; import org.eclipse.jdt.internal.core.util.Util; import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup; import org.eclipse.jdt.ui.wizards.NewTypeWizardPage; import org.eclipse.swt.widgets.Composite; import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.ReplaceEdit; /** * @author MelamedZ * @author Thorsten Kamann <thorsten.kamann@googlemail.com> */ public class NewClassWizardPage extends org.eclipse.jdt.ui.wizards.NewClassWizardPage { private static final int FINAL_INDEX = 1; private IStatus fStatus; /** * Creates a new <code>NewClassWizardPage</code> */ public NewClassWizardPage() { super(); setTitle("Groovy Class"); setDescription("Create a new Groovy class"); } @Override protected void createModifierControls(Composite composite, int nColumns) { super.createModifierControls(composite, nColumns); SelectionButtonDialogFieldGroup group = getOtherModifierButtonsFieldGroup(); group.getSelectionButton(FINAL_INDEX).setText("Create Script"); } @Override protected String getCompilationUnitName(String typeName) { return typeName + ".groovy"; } @Override protected void createTypeMembers(IType type, ImportsManager imports, IProgressMonitor monitor) throws CoreException { super.createTypeMembers(type, imports, monitor); if (isCreateMain()) { // replace main method with a more groovy version IMethod main = type.getMethod("main", new String[] {"[QString;"} ); if (main != null && main.exists()) { main.delete(true, monitor); type.createMethod("static main(args) {\n\n}", null, true, monitor); } } } @Override protected IStatus typeNameChanged() { StatusInfo status = (StatusInfo) super.typeNameChanged(); IPackageFragment pack = getPackageFragment(); if (pack == null) { return status; } IJavaProject project = pack.getJavaProject(); try { if (!project.getProject().hasNature(GroovyNature.GROOVY_NATURE)) { status.setWarning(project.getElementName() + " is not a groovy project. Groovy Nature will be added to project upon completion."); } } catch (CoreException e) { status.setError("Exception when accessing project natures for " + project.getElementName()); } String typeName = getTypeNameWithoutParameters(); // must not exist as a .groovy file if (!isEnclosingTypeSelected() && (status.getSeverity() < IStatus.ERROR)) { if (pack != null) { IType type = null; try { type = project.findType(pack.getElementName(), typeName); } catch (JavaModelException e) { // can ignore } if (type != null && type.getPackageFragment().equals(pack)) { status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); } } } // lastly, check exclusion filters to see if Groovy files are allowed in // the source folder if (status.getSeverity() < IStatus.ERROR) { try { ClasspathEntry entry = (ClasspathEntry) ((IPackageFragmentRoot) pack.getParent()).getRawClasspathEntry(); if (entry != null) { char[][] inclusionPatterns = entry.fullInclusionPatternChars(); char[][] exclusionPatterns = entry.fullExclusionPatternChars(); if (Util.isExcluded(pack.getResource().getFullPath().append(getCompilationUnitName(typeName)), inclusionPatterns, exclusionPatterns, false)) { status.setError("Cannot create Groovy type because of exclusion patterns on the source folder."); } } } catch (JavaModelException e) { status.setError(e.getLocalizedMessage()); GroovyCore.logException("Exception inside new Groovy class wizard", e); } } return status; } @Override public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException { IPackageFragment pack = getPackageFragment(); if (pack != null) { IProject project = pack.getJavaProject().getProject(); if (!GroovyNature.hasGroovyNature(project)) { // add groovy nature GroovyRuntime.addGroovyNature(project); } } super.createType(monitor); monitor = new SubProgressMonitor(monitor, 1); GroovyCompilationUnit unit = (GroovyCompilationUnit) pack.getCompilationUnit(getCompilationUnitName(getTypeName())); try { monitor.beginTask("Remove semi-colons", 1); unit.becomeWorkingCopy(new SubProgressMonitor(monitor, 1)); // remove ';' on package declaration IPackageDeclaration[] packs = unit.getPackageDeclarations(); char[] contents = unit.getContents(); MultiTextEdit multi = new MultiTextEdit(); if (packs.length > 0) { ISourceRange range = packs[0].getSourceRange(); int position = range.getOffset() + range.getLength(); if (contents[position] == ';') { multi.addChild(new ReplaceEdit(position, 1, "")); } } // remove ';' on import declaration IImportDeclaration[] imports = unit.getImports(); if (imports != null && imports.length > 0) { ISourceRange range = imports[0].getSourceRange(); int position = range.getOffset() + range.getLength() - 1; if (contents[position] == ';') { multi.addChild(new ReplaceEdit(position, 1, "")); } } // remove type declaration for scripts if (isScript()) { ISourceRange range = unit.getTypes()[0].getSourceRange(); multi.addChild(new DeleteEdit(range.getOffset(), range.getLength())); } if (multi.hasChildren()) { unit.applyTextEdit(multi, new SubProgressMonitor(monitor, 1)); unit.commitWorkingCopy(true, new SubProgressMonitor(monitor, 1)); } monitor.worked(1); } finally { if (unit != null) { unit.discardWorkingCopy(); } monitor.done(); } } private boolean isScript() { // the final check box has been usurped and is now the checkbox for // script SelectionButtonDialogFieldGroup group = getOtherModifierButtonsFieldGroup(); return group.isSelected(FINAL_INDEX); } /** * @return */ public SelectionButtonDialogFieldGroup getOtherModifierButtonsFieldGroup() { return (SelectionButtonDialogFieldGroup) ReflectionUtils.getPrivateField( NewTypeWizardPage.class, "fOtherMdfButtons", this); } private String getTypeNameWithoutParameters() { String typeNameWithParameters= getTypeName(); int angleBracketOffset= typeNameWithParameters.indexOf('<'); if (angleBracketOffset == -1) { return typeNameWithParameters; } else { return typeNameWithParameters.substring(0, angleBracketOffset); } } @Override public int getModifiers() { int modifiers = super.getModifiers(); modifiers &= ~F_PUBLIC; modifiers &= ~F_PRIVATE; modifiers &= ~F_PROTECTED; modifiers &= ~F_FINAL; return modifiers; } /** * Retrieve the current status, as last set by updateStatus. */ public IStatus getStatus() { return fStatus; } @Override protected void updateStatus(IStatus status) { super.updateStatus(status); fStatus = status; } }