]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/CompilationUnitRewrite.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / core refactoring / org / eclipse / jdt / internal / corext / refactoring / structure / CompilationUnitRewrite.java
diff --git a/case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/CompilationUnitRewrite.java b/case-study/jdt-before/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/CompilationUnitRewrite.java
new file mode 100644 (file)
index 0000000..074b105
--- /dev/null
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.corext.refactoring.structure;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+
+import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
+import org.eclipse.ltk.core.refactoring.GroupCategorySet;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
+import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
+
+import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
+import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
+import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
+
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
+
+/**
+ * A {@link CompilationUnitRewrite} holds all data structures that are typically
+ * required for non-trivial refactorings. All getters are initialized lazily to
+ * avoid lengthy processing in
+ * {@link org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)}.
+ * <p>
+ * Bindings are resolved by default, but can be disabled with <code>setResolveBindings(false)</code>.
+ * Statements recovery is enabled by default, but can be disabled with <code>setStatementsRecovery(false)</code>.
+ * Bindings recovery is disabled by default, but can be enabled with <code>setBindingRecovery(true)</code>.
+ * </p>
+ */
+public class CompilationUnitRewrite {
+       //TODO: add RefactoringStatus fStatus;?
+       private ICompilationUnit fCu;
+       private List<TextEditGroup> fTextEditGroups= new ArrayList<TextEditGroup>();
+
+       private CompilationUnit fRoot; // lazily initialized
+       private ASTRewrite fRewrite; // lazily initialized
+       private ImportRewrite fImportRewrite; // lazily initialized
+       private ImportRemover fImportRemover; // lazily initialized
+       private boolean fResolveBindings= true;
+       private boolean fStatementsRecovery= true;
+       private boolean fBindingsRecovery= false;
+       private final WorkingCopyOwner fOwner;
+       private IDocument fRememberContent= null;
+
+
+       public CompilationUnitRewrite(ICompilationUnit cu) {
+               this(null, cu, null);
+       }
+
+       public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu) {
+               this(owner, cu, null);
+       }
+
+       public CompilationUnitRewrite(ICompilationUnit cu, CompilationUnit root) {
+               this(null, cu, root);
+       }
+
+       public CompilationUnitRewrite(WorkingCopyOwner owner, ICompilationUnit cu, CompilationUnit root) {
+               fOwner= owner;
+               fCu= cu;
+               fRoot= root;
+       }
+
+       public void rememberContent() {
+               fRememberContent= new Document();
+       }
+
+
+       /**
+        * Controls whether the compiler should provide binding information for the AST
+        * nodes it creates. To be effective, this method must be called before any
+        * of {@link #getRoot()},{@link #getASTRewrite()},
+        * {@link #getImportRemover()}. This method has no effect if the target object
+        * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
+        * <p>
+        * Defaults to <b><code>true</code></b> (do resolve bindings).
+        * </p>
+        *
+        * @param resolve
+        *            <code>true</code> if bindings are wanted, and
+        *            <code>false</code> if bindings are not of interest
+        * @see org.eclipse.jdt.core.dom.ASTParser#setResolveBindings(boolean)
+        *      Note: The default value (<code>true</code>) differs from the one of
+        *      the corresponding method in ASTParser.
+        */
+       public void setResolveBindings(boolean resolve) {
+               fResolveBindings= resolve;
+       }
+
+       /**
+        * Controls whether the compiler should perform statements recovery.
+        * To be effective, this method must be called before any
+        * of {@link #getRoot()},{@link #getASTRewrite()},
+        * {@link #getImportRemover()}. This method has no effect if the target object
+        * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
+        * <p>
+        * Defaults to <b><code>true</code></b> (do perform statements recovery).
+        * </p>
+        *
+        * @param statementsRecovery whether statements recovery should be performed
+        * @see org.eclipse.jdt.core.dom.ASTParser#setStatementsRecovery(boolean)
+        */
+       public void setStatementsRecovery(boolean statementsRecovery) {
+               fStatementsRecovery= statementsRecovery;
+       }
+
+       /**
+        * Controls whether the compiler should perform bindings recovery.
+        * To be effective, this method must be called before any
+        * of {@link #getRoot()},{@link #getASTRewrite()},
+        * {@link #getImportRemover()}. This method has no effect if the target object
+        * has been created with {@link #CompilationUnitRewrite(ICompilationUnit, CompilationUnit)}.
+        * <p>
+        * Defaults to <b><code>false</code></b> (do not perform bindings recovery).
+        * </p>
+        *
+        * @param bindingsRecovery whether bindings recovery should be performed
+        * @see org.eclipse.jdt.core.dom.ASTParser#setBindingsRecovery(boolean)
+        */
+       public void setBindingRecovery(boolean bindingsRecovery) {
+               fBindingsRecovery= bindingsRecovery;
+       }
+
+       public void clearASTRewrite() {
+               fRewrite= null;
+               fTextEditGroups= new ArrayList<TextEditGroup>();
+       }
+
+       public void clearImportRewrites() {
+               fImportRewrite= null;
+       }
+
+       public void clearASTAndImportRewrites() {
+               clearASTRewrite();
+               fImportRewrite= null;
+       }
+
+       public CategorizedTextEditGroup createCategorizedGroupDescription(String name, GroupCategorySet set) {
+               CategorizedTextEditGroup result= new CategorizedTextEditGroup(name, set);
+               fTextEditGroups.add(result);
+               return result;
+       }
+
+       public TextEditGroup createGroupDescription(String name) {
+               TextEditGroup result= new TextEditGroup(name);
+               fTextEditGroups.add(result);
+               return result;
+       }
+
+       /**
+        * Creates a compilation unit change based on the events recorded by this compilation unit
+        * rewrite.
+        * 
+        * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
+        * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
+        * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
+        * @throws IllegalArgumentException when the AST rewrite encounters problems
+        * @since 3.6
+        */
+       public CompilationUnitChange createChange(boolean generateGroups) throws CoreException {
+               return createChange(generateGroups, null);
+       }
+
+       /**
+        * Creates a compilation unit change based on the events recorded by this compilation unit
+        * rewrite.
+        * <p>
+        * DO NOT REMOVE, used in a product.</p>
+        * 
+        * @return a {@link org.eclipse.jdt.core.refactoring.CompilationUnitChange}, or <code>null</code> for an empty change
+        * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
+        * @throws IllegalArgumentException when the AST rewrite encounters problems
+        * @deprecated since 3.5, replaced by {@link #createChange(boolean)}
+        */
+       public org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange createChange() throws CoreException {
+               CompilationUnitChange change= createChange(true);
+               if (change == null)
+                       return null;
+               return new org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange(change);
+       }
+
+       /**
+        * Creates a compilation unit change based on the events recorded by this compilation unit
+        * rewrite.
+        * 
+        * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code>
+        *            otherwise
+        * @param monitor the progress monitor or <code>null</code>
+        * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
+        * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
+        * @throws IllegalArgumentException when the AST rewrite encounters problems
+        */
+       public CompilationUnitChange createChange(boolean generateGroups, IProgressMonitor monitor) throws CoreException {
+               return createChange(fCu.getElementName(), generateGroups, monitor);
+       }
+
+       /**
+        * Creates a compilation unit change based on the events recorded by this compilation unit rewrite.
+        * @param name the name of the change to create
+        * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
+        * @param monitor the progress monitor or <code>null</code>
+        * @return a {@link CompilationUnitChange}, or <code>null</code> for an empty change
+        * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
+        * @throws IllegalArgumentException when the AST rewrite encounters problems
+        */
+       public CompilationUnitChange createChange(String name, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
+               CompilationUnitChange cuChange= new CompilationUnitChange(name, fCu);
+               MultiTextEdit multiEdit= new MultiTextEdit();
+               cuChange.setEdit(multiEdit);
+               return attachChange(cuChange, generateGroups, monitor);
+       }
+
+
+       /**
+        * Attaches the changes of this compilation unit rewrite to the given CU Change. The given
+        * change <b>must</b> either have no root edit, or a MultiTextEdit as a root edit.
+        * The edits in the given change <b>must not</b> overlap with the changes of
+        * this compilation unit.
+        *
+        * @param cuChange existing CompilationUnitChange with a MultiTextEdit root or no root at all.
+        * @param generateGroups <code>true</code> to generate text edit groups, <code>false</code> otherwise
+        * @param monitor the progress monitor or <code>null</code>
+        * @return a change combining the changes of this rewrite and the given rewrite, or <code>null</code> for an empty change
+        * @throws CoreException when text buffer acquisition or import rewrite text edit creation fails
+        */
+       public CompilationUnitChange attachChange(CompilationUnitChange cuChange, boolean generateGroups, IProgressMonitor monitor) throws CoreException {
+               try {
+                       boolean needsAstRewrite= fRewrite != null; // TODO: do we need something like ASTRewrite#hasChanges() here?
+                       boolean needsImportRemoval= fImportRemover != null && fImportRemover.hasRemovedNodes();
+                       boolean needsImportRewrite= fImportRewrite != null && fImportRewrite.hasRecordedChanges() || needsImportRemoval;
+                       if (!needsAstRewrite && !needsImportRemoval && !needsImportRewrite)
+                               return null;
+
+                       MultiTextEdit multiEdit= (MultiTextEdit) cuChange.getEdit();
+                       if (multiEdit == null) {
+                               multiEdit= new MultiTextEdit();
+                               cuChange.setEdit(multiEdit);
+                       }
+
+                       if (needsAstRewrite) {
+                               TextEdit rewriteEdit;
+                               if (fRememberContent != null) {
+                                       rewriteEdit= fRewrite.rewriteAST(fRememberContent, fCu.getJavaProject().getOptions(true));
+                               } else {
+                                       rewriteEdit= fRewrite.rewriteAST();
+                               }
+                               if (!isEmptyEdit(rewriteEdit)) {
+                                       multiEdit.addChild(rewriteEdit);
+                                       if (generateGroups) {
+                                               for (Iterator<TextEditGroup> iter= fTextEditGroups.iterator(); iter.hasNext();) {
+                                                       TextEditGroup group= iter.next();
+                                                       cuChange.addTextEditGroup(group);
+                                               }
+                                       }
+                               }
+                       }
+                       if (needsImportRemoval) {
+                               fImportRemover.applyRemoves(getImportRewrite());
+                       }
+                       if (needsImportRewrite) {
+                               TextEdit importsEdit= fImportRewrite.rewriteImports(monitor);
+                               if (!isEmptyEdit(importsEdit)) {
+                                       multiEdit.addChild(importsEdit);
+                                       String importUpdateName= RefactoringCoreMessages.ASTData_update_imports;
+                                       cuChange.addTextEditGroup(new TextEditGroup(importUpdateName, importsEdit));
+                               }
+                       } else {
+
+                       }
+                       if (isEmptyEdit(multiEdit))
+                               return null;
+                       return cuChange;
+               } finally {
+                       if (monitor != null)
+                               monitor.done();
+               }
+       }
+
+       private static boolean isEmptyEdit(TextEdit edit) {
+               return edit.getClass() == MultiTextEdit.class && ! edit.hasChildren();
+       }
+
+       public ICompilationUnit getCu() {
+               return fCu;
+       }
+
+       public CompilationUnit getRoot() {
+               if (fRoot == null)
+                       fRoot= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(fCu, fOwner, fResolveBindings, fStatementsRecovery, fBindingsRecovery, null);
+               return fRoot;
+       }
+
+       public AST getAST() {
+               return getRoot().getAST();
+       }
+
+       public ASTRewrite getASTRewrite() {
+               if (fRewrite == null) {
+                       fRewrite= ASTRewrite.create(getRoot().getAST());
+                       if (fRememberContent != null) { // wain until ast rewrite is accessed first
+                               try {
+                                       fRememberContent.set(fCu.getSource());
+                               } catch (JavaModelException e) {
+                                       fRememberContent= null;
+                               }
+                       }
+               }
+               return fRewrite;
+       }
+
+       public ImportRewrite getImportRewrite() {
+               if (fImportRewrite == null) {
+                       // lazily initialized to avoid lengthy processing in checkInitialConditions(..)
+                       try {
+                               /* If bindings are to be resolved, then create the AST, so that
+                                * ImportRewrite#setUseContextToFilterImplicitImports(boolean) will be set to true
+                                * and ContextSensitiveImportRewriteContext etc. can be used. */
+                               if (fRoot == null && ! fResolveBindings) {
+                                       fImportRewrite= StubUtility.createImportRewrite(fCu, true);
+                               } else {
+                                       fImportRewrite= StubUtility.createImportRewrite(getRoot(), true);
+                               }
+                       } catch (CoreException e) {
+                               JavaPlugin.log(e);
+                               throw new IllegalStateException(e.getMessage()); // like ASTParser#createAST(..) does
+                       }
+               }
+               return fImportRewrite;
+
+       }
+
+       public ImportRemover getImportRemover() {
+               if (fImportRemover == null) {
+                       fImportRemover= new ImportRemover(fCu.getJavaProject(), getRoot());
+               }
+               return fImportRemover;
+       }
+
+       public void clearGroupDescriptions() {
+               for (Iterator<TextEditGroup> iter= fTextEditGroups.iterator(); iter.hasNext();) {
+                       TextEditGroup group= iter.next();
+                       group.clearTextEdits();
+               }
+       }
+}