| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.jsdt.internal.corext.codemanipulation; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.core.filebuffers.ITextFileBuffer; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Assert; |
| 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.Status; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.core.runtime.jobs.ISchedulingRule; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.text.edits.TextEdit; |
| import org.eclipse.wst.jsdt.core.IFunction; |
| import org.eclipse.wst.jsdt.core.IJavaScriptElement; |
| import org.eclipse.wst.jsdt.core.IJavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.IType; |
| import org.eclipse.wst.jsdt.core.dom.ASTNode; |
| import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration; |
| import org.eclipse.wst.jsdt.core.dom.AnonymousClassDeclaration; |
| import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation; |
| import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration; |
| import org.eclipse.wst.jsdt.core.dom.IFunctionBinding; |
| import org.eclipse.wst.jsdt.core.dom.ITypeBinding; |
| import org.eclipse.wst.jsdt.core.dom.IVariableBinding; |
| import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.wst.jsdt.internal.corext.dom.NodeFinder; |
| import org.eclipse.wst.jsdt.internal.corext.refactoring.changes.CompilationUnitChange; |
| import org.eclipse.wst.jsdt.internal.corext.refactoring.structure.CompilationUnitRewrite; |
| import org.eclipse.wst.jsdt.internal.corext.refactoring.util.RefactoringFileBuffers; |
| import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil; |
| import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; |
| |
| /** |
| * |
| * 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. |
| */ |
| public final class AddCustomConstructorOperation implements IWorkspaceRunnable { |
| |
| /** Should the resulting edit be applied? */ |
| private boolean fApply= true; |
| |
| /** The super constructor method binding */ |
| private final IFunctionBinding fBinding; |
| |
| /** The variable bindings to implement */ |
| private final IVariableBinding[] fBindings; |
| |
| /** The variable binding keys for which a constructor was generated */ |
| private final List fCreated= new ArrayList(); |
| |
| /** The resulting text edit */ |
| private TextEdit fEdit= null; |
| |
| /** The insertion point, or <code>null</code> */ |
| private final IJavaScriptElement fInsert; |
| |
| /** Should the call to the super constructor be omitted? */ |
| private boolean fOmitSuper= false; |
| |
| /** Should the compilation unit content be saved? */ |
| private final boolean fSave; |
| |
| /** The code generation settings to use */ |
| private final CodeGenerationSettings fSettings; |
| |
| /** The type declaration to add the constructors to */ |
| private final IType fType; |
| |
| /** The compilation unit ast node */ |
| private final JavaScriptUnit fUnit; |
| |
| /** The visibility flags of the new constructor */ |
| private int fVisibility= 0; |
| |
| /** |
| * Creates a new add custom constructor operation. |
| * |
| * @param type the type to add the methods to |
| * @param insert the insertion point, or <code>null</code> |
| * @param unit the compilation unit ast node |
| * @param bindings the variable bindings to use in the constructor |
| * @param binding the method binding of the super constructor |
| * @param settings the code generation settings to use |
| * @param apply <code>true</code> if the resulting edit should be applied, <code>false</code> otherwise |
| * @param save <code>true</code> if the changed compilation unit should be saved, <code>false</code> otherwise |
| */ |
| public AddCustomConstructorOperation(final IType type, final IJavaScriptElement insert, final JavaScriptUnit unit, final IVariableBinding[] bindings, final IFunctionBinding binding, final CodeGenerationSettings settings, final boolean apply, final boolean save) { |
| Assert.isNotNull(type); |
| Assert.isNotNull(unit); |
| Assert.isNotNull(bindings); |
| Assert.isNotNull(settings); |
| fType= type; |
| fInsert= insert; |
| fUnit= unit; |
| fBindings= bindings; |
| fBinding= binding; |
| fSettings= settings; |
| fSave= save; |
| fApply= apply; |
| } |
| |
| /** |
| * Returns the resulting text edit. |
| * |
| * @return the resulting text edit |
| */ |
| public final TextEdit getResultingEdit() { |
| return fEdit; |
| } |
| |
| /** |
| * Returns the scheduling rule for this operation. |
| * |
| * @return the scheduling rule |
| */ |
| public final ISchedulingRule getSchedulingRule() { |
| return ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| |
| /** |
| * Returns the visibility modifier of the generated constructors. |
| * |
| * @return the visibility modifier |
| */ |
| public final int getVisibility() { |
| return fVisibility; |
| } |
| |
| /** |
| * Should the call to the super constructor be omitted? |
| * |
| * @return <code>true</code> to omit the call, <code>false</code> otherwise |
| */ |
| public final boolean isOmitSuper() { |
| return fOmitSuper; |
| } |
| |
| /* |
| * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public final void run(IProgressMonitor monitor) throws CoreException { |
| if (monitor == null) |
| monitor= new NullProgressMonitor(); |
| try { |
| monitor.beginTask("", 1); //$NON-NLS-1$ |
| monitor.setTaskName(CodeGenerationMessages.AddCustomConstructorOperation_description); |
| fCreated.clear(); |
| final IJavaScriptUnit unit= fType.getJavaScriptUnit(); |
| final CompilationUnitRewrite rewrite= new CompilationUnitRewrite(unit, fUnit); |
| ITypeBinding binding= null; |
| ListRewrite rewriter= null; |
| if (fType.isAnonymous()) { |
| final IJavaScriptElement parent= fType.getParent(); |
| final ClassInstanceCreation creation= (ClassInstanceCreation) ASTNodes.getParent(NodeFinder.perform(rewrite.getRoot(), fType.getNameRange()), ClassInstanceCreation.class); |
| if (creation != null) { |
| binding= creation.resolveTypeBinding(); |
| final AnonymousClassDeclaration declaration= creation.getAnonymousClassDeclaration(); |
| if (declaration != null) |
| rewriter= rewrite.getASTRewrite().getListRewrite(declaration, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY); |
| } |
| } else { |
| final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(NodeFinder.perform(rewrite.getRoot(), fType.getNameRange()), AbstractTypeDeclaration.class); |
| if (declaration != null) { |
| binding= declaration.resolveBinding(); |
| rewriter= rewrite.getASTRewrite().getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); |
| } |
| } |
| if (binding != null && rewriter != null) { |
| ITextFileBuffer buffer= null; |
| IDocument document= null; |
| try { |
| if (!JavaModelUtil.isPrimary(unit)) |
| document= new Document(unit.getBuffer().getContents()); |
| else { |
| buffer= RefactoringFileBuffers.acquire(unit); |
| document= buffer.getDocument(); |
| } |
| ASTNode insertion= null; |
| if (fInsert instanceof IFunction) |
| insertion= ASTNodes.getParent(NodeFinder.perform(rewrite.getRoot(), ((IFunction) fInsert).getNameRange()), FunctionDeclaration.class); |
| FunctionDeclaration stub= StubUtility2.createConstructorStub(rewrite.getCu(), rewrite.getASTRewrite(), rewrite.getImportRewrite(), binding, rewrite.getAST(), fOmitSuper ? null : fBinding, fBindings, fVisibility, fSettings); |
| if (stub != null) { |
| fCreated.addAll(Arrays.asList(fBindings)); |
| if (insertion != null) |
| rewriter.insertBefore(stub, insertion, null); |
| else |
| rewriter.insertLast(stub, null); |
| } |
| final Change result= rewrite.createChange(); |
| if (result instanceof CompilationUnitChange) { |
| final CompilationUnitChange change= (CompilationUnitChange) result; |
| final TextEdit edit= change.getEdit(); |
| if (edit != null) { |
| try { |
| fEdit= edit; |
| if (fApply) |
| edit.apply(document, TextEdit.UPDATE_REGIONS); |
| if (fSave) { |
| if (buffer != null) |
| buffer.commit(new SubProgressMonitor(monitor, 1), true); |
| else |
| unit.getBuffer().setContents(document.get()); |
| } |
| } catch (Exception exception) { |
| throw new CoreException(new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), 0, exception.getLocalizedMessage(), exception)); |
| } |
| } |
| } |
| } finally { |
| if (buffer != null) |
| RefactoringFileBuffers.release(unit); |
| } |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Determines whether the call to the super constructor should be omitted. |
| * |
| * @param omit <code>true</code> to omit the call, <code>false</code> otherwise |
| */ |
| public final void setOmitSuper(final boolean omit) { |
| fOmitSuper= omit; |
| } |
| |
| /** |
| * Sets the visibility modifier of the generated constructors. |
| * |
| * @param visibility the visibility modifier |
| */ |
| public final void setVisibility(final int visibility) { |
| fVisibility= visibility; |
| } |
| } |