# HG changeset patch # User Ralph Benjamin Ruijs # Date 1251063319 -7200 # Node ID 8ea0930cae15fe52d414288bab085d0539c936be # Parent 0070d43ef2c0d5693f9926fc5ab8585b860e342b [mq]: 57545.diff diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/api/InlineRefactoring.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/api/InlineRefactoring.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/api/InlineRefactoring.java @@ -0,0 +1,91 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.refactoring.java.api; + +import com.sun.source.tree.Tree; +import org.netbeans.api.java.source.TreePathHandle; +import org.netbeans.modules.refactoring.api.AbstractRefactoring; +import org.openide.util.lookup.Lookups; + +/** + * Refactoring used to inline an element + * It removes the declaration and changes all references with it's body. + * @author ralphbenjamin + */ +public final class InlineRefactoring extends AbstractRefactoring { + private Tree elementBody; + private String name; + + /** + * Creates a new Instance of InlineRefactoring + * @param element element to refactor + */ + public InlineRefactoring(TreePathHandle element) { + super(Lookups.fixed(element)); + } + + /** + * @return the elementBody + */ + public Tree getElementBody() { + return elementBody; + } + + /** + * @param elementBody the elementBody to set + */ + public void setElementBody(Tree elementBody) { + this.elementBody = elementBody; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/api/ui/JavaRefactoringActionsFactory.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/api/ui/JavaRefactoringActionsFactory.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/api/ui/JavaRefactoringActionsFactory.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/api/ui/JavaRefactoringActionsFactory.java @@ -49,6 +49,7 @@ import org.netbeans.modules.refactoring.java.ui.PullUpAction; import org.netbeans.modules.refactoring.java.ui.PushDownAction; import org.netbeans.modules.refactoring.java.ui.UseSuperTypeAction; +import org.netbeans.modules.refactoring.java.ui.InlineAction; import org.openide.util.ContextAwareAction; /** @@ -127,4 +128,12 @@ public static ContextAwareAction extractInterfaceAction() { return ExtractInterfaceAction.findObject(ExtractInterfaceAction.class, true); } + + /** + * Factory method for InlineAction + * @return an instance of InlineAction + */ + public static ContextAwareAction inlineAction() { + return InlineAction.findObject(InlineAction.class, true); + } } diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties @@ -239,3 +239,10 @@ ERR_VarargsFinalPosition=Varargs can be used only in the final argument position. ERR_FindUsagesArrayType=Cannot perform find usages on [] + +# --- INLINE REFACTORING --------------------------------------------------------------- +ERR_InlineNoVarInitializer=Cannot find the field initializer. +ERR_InlineWrongType=Cannot refactor this type of element: {0}. +ERR_InlineNotInIterator=Cannot inline for loop iterator. +ERR_InlineNotCompoundArrayInit=Array declarations without the \"new\" keyword are not supported. +ERR_InlineAssignedOnce=Variable is assigned to more than once. \ No newline at end of file diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineRefactoringPlugin.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineRefactoringPlugin.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineRefactoringPlugin.java @@ -0,0 +1,279 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.refactoring.java.plugins; + +import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.CompoundAssignmentTree; +import com.sun.source.tree.NewArrayTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import org.netbeans.api.java.source.CancellableTask; +import org.netbeans.api.java.source.ClassIndex; +import org.netbeans.api.java.source.ClasspathInfo; +import org.netbeans.api.java.source.CompilationController; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.ElementHandle; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.SourceUtils; +import org.netbeans.api.java.source.TreePathHandle; +import org.netbeans.api.java.source.support.CancellableTreeScanner; +import org.netbeans.modules.refactoring.api.Problem; +import org.netbeans.modules.refactoring.api.ProgressEvent; +import org.netbeans.modules.refactoring.java.RetoucheUtils; +import org.netbeans.modules.refactoring.java.api.InlineRefactoring; +import org.netbeans.modules.refactoring.java.spi.JavaRefactoringPlugin; +import org.netbeans.modules.refactoring.spi.RefactoringElementsBag; +import org.openide.filesystems.FileObject; +import org.openide.util.NbBundle; + +/** + * Plugin that implements the core functionality of Inline refactoring. + * @author ralphbenjamin + */ +public final class InlineRefactoringPlugin extends JavaRefactoringPlugin { + + private final InlineRefactoring refactoring; + private final TreePathHandle treePathHandle; + + public InlineRefactoringPlugin(InlineRefactoring inlineRefactoring) { + this.refactoring = inlineRefactoring; + this.treePathHandle = refactoring.getRefactoringSource().lookup(TreePathHandle.class); + } + + @Override + protected JavaSource getJavaSource(Phase p) { + if (treePathHandle == null) { + return null; + } + switch (p) { + case PRECHECK: + case FASTCHECKPARAMETERS: + return JavaSource.forFileObject(treePathHandle.getFileObject()); + case CHECKPARAMETERS: + ClasspathInfo classpathInfo = getClasspathInfo(refactoring); + JavaSource source = JavaSource.create(classpathInfo, treePathHandle.getFileObject()); + return source; + } + throw new IllegalStateException(); + } + + public Problem prepare(RefactoringElementsBag refactoringElements) { + if (treePathHandle == null) { + return null; + } + Set a = getRelevantFiles(); + fireProgressListenerStart(ProgressEvent.START, a.size()); + TransformTask transform = new TransformTask(new InlineTransformer(refactoring.getElementBody()), treePathHandle); + Problem problem = createAndAddElements(a, transform, refactoringElements, refactoring); + fireProgressListenerStop(); + return problem; + } + private Set> allMethods; + + private Set getRelevantFiles() { + ClasspathInfo cpInfo = getClasspathInfo(refactoring); + final Set set = new HashSet(); + JavaSource source = JavaSource.create(cpInfo, treePathHandle.getFileObject()); + + try { + source.runUserActionTask(new CancellableTask() { + + public void cancel() { + throw new UnsupportedOperationException("Not supported yet."); // NOI18N + } + + public void run(CompilationController info) throws Exception { + final ClassIndex idx = info.getClasspathInfo().getClassIndex(); + info.toPhase(JavaSource.Phase.RESOLVED); + Element el = treePathHandle.resolveElement(info); + ElementKind kind = el.getKind(); + ElementHandle enclosingType; + if (el instanceof TypeElement) { + enclosingType = ElementHandle.create((TypeElement) el); + } else { + enclosingType = ElementHandle.create(info.getElementUtilities().enclosingTypeElement(el)); + } + set.add(SourceUtils.getFile(el, info.getClasspathInfo())); + if (el.getModifiers().contains(Modifier.PRIVATE)) { + if (kind == ElementKind.METHOD) { + //add all references of overriding methods + allMethods = new HashSet>(); + allMethods.add(ElementHandle.create((ExecutableElement) el)); + } + } else { + if (kind.isField()) { + set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.FIELD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); + } else if (el instanceof TypeElement) { + set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES, ClassIndex.SearchKind.IMPLEMENTORS), EnumSet.of(ClassIndex.SearchScope.SOURCE))); + } else if (kind == ElementKind.METHOD) { + //add all references of overriding methods + allMethods = new HashSet>(); + allMethods.add(ElementHandle.create((ExecutableElement) el)); + for (ExecutableElement e : RetoucheUtils.getOverridingMethods((ExecutableElement) el, info)) { + addMethods(e, set, info, idx); + } + //add all references of overriden methods + for (ExecutableElement ov : RetoucheUtils.getOverridenMethods((ExecutableElement) el, info)) { + addMethods(ov, set, info, idx); + for (ExecutableElement e : RetoucheUtils.getOverridingMethods(ov, info)) { + addMethods(e, set, info, idx); + } + } + set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); //????? + } + } + } + }, true); + } catch (IOException ioe) { + throw (RuntimeException) new RuntimeException().initCause(ioe); + } + return set; + } + + private void addMethods(ExecutableElement e, Set set, CompilationInfo info, ClassIndex idx) { + set.add(SourceUtils.getFile(e, info.getClasspathInfo())); + ElementHandle encl = ElementHandle.create(info.getElementUtilities().enclosingTypeElement(e)); + set.addAll(idx.getResources(encl, EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); + allMethods.add(ElementHandle.create(e)); + } + + @Override + protected Problem preCheck(CompilationController javac) throws IOException { + Problem preCheckProblem = null; + javac.toPhase(JavaSource.Phase.RESOLVED); + Element element = treePathHandle.resolveElement(javac); + preCheckProblem = isElementAvail(treePathHandle, javac); + if (preCheckProblem != null) { + return preCheckProblem; + } + + preCheckProblem = JavaPluginUtils.isSourceElement(element, javac); + if (preCheckProblem != null) { + return preCheckProblem; + } + + refactoring.setName(element.getSimpleName().toString()); + switch (element.getKind()) { + // Inline a Variable needs the following preconditions: + // - Not in Iterator + // - Assigned to exactly once + // - Not compound array initialization + case LOCAL_VARIABLE: + case FIELD: + // Assigned to exactly once + VariableTree variableTree = (VariableTree) javac.getTrees().getTree(element); + refactoring.setElementBody(variableTree.getInitializer()); + if (refactoring.getElementBody() == null) { + preCheckProblem = createProblem(preCheckProblem, true, NbBundle.getMessage(InlineRefactoringPlugin.class, "ERR_InlineNoVarInitializer")); + return preCheckProblem; + } + UsageVisitor visitor = new UsageVisitor(javac); + visitor.scan(javac.getCompilationUnit(), element); + if (visitor.assignment > 0) { + preCheckProblem = createProblem(preCheckProblem, true, NbBundle.getMessage(InlineRefactoringPlugin.class, "ERR_InlineAssignedOnce")); + return preCheckProblem; + } + + // Not in Iterator + TreePath treePath = treePathHandle.resolve(javac); + treePath = treePath.getParentPath(); + Tree tree = treePath.getLeaf(); + if (tree.getKind().equals(Tree.Kind.ENHANCED_FOR_LOOP) || tree.getKind().equals(Tree.Kind.FOR_LOOP)) { + preCheckProblem = createProblem(preCheckProblem, true, NbBundle.getMessage(InlineRefactoringPlugin.class, "ERR_InlineNotInIterator")); + return preCheckProblem; + } + // Not compound array initialization + if (variableTree.getInitializer().getKind().equals(Tree.Kind.NEW_ARRAY)) { + NewArrayTree newArrayTree = (NewArrayTree) variableTree.getInitializer(); + if (newArrayTree.getType() == null || newArrayTree.getDimensions() == null) { + preCheckProblem = createProblem(preCheckProblem, true, NbBundle.getMessage(InlineRefactoringPlugin.class, "ERR_InlineNotCompoundArrayInit")); + } + } + break; + default: + preCheckProblem = createProblem(preCheckProblem, true, new MessageFormat(NbBundle.getMessage(InlineRefactoringPlugin.class, "ERR_InlineWrongType")).format(new Object[]{element.getKind().toString()})); + } + return preCheckProblem; + } + + private class UsageVisitor extends CancellableTreeScanner { + + public int assignment = 0; + private final CompilationController workingCopy; + + public UsageVisitor(CompilationController workingCopy) { + this.workingCopy = workingCopy; + } + + @Override + public Tree visitAssignment(AssignmentTree node, Element p) { + if(p.equals(asElement(node.getVariable()))) { + assignment++; + } + return super.visitAssignment(node, p); + } + + @Override + public Tree visitCompoundAssignment(CompoundAssignmentTree node, Element p) { + if(p.equals(asElement(node.getVariable()))) { + assignment++; + } + return super.visitCompoundAssignment(node, p); + } + + private Element asElement(Tree tree) { + Trees treeUtil = workingCopy.getTrees(); + TreePath treePath = treeUtil.getPath(workingCopy.getCompilationUnit(), tree); + Element element = treeUtil.getElement(treePath); + return element; + } + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineTransformer.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineTransformer.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InlineTransformer.java @@ -0,0 +1,156 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.refactoring.java.plugins; + +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.ImportTree; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; +import java.util.Iterator; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Name; +import javax.lang.model.type.TypeMirror; +import org.netbeans.api.java.source.ElementUtilities; +import org.netbeans.modules.refactoring.java.spi.RefactoringVisitor; + +/** + * + * @author ralphbenjamin + */ +public class InlineTransformer extends RefactoringVisitor { + + private final Tree elementBody; + + public InlineTransformer(Tree elementBody) { + this.elementBody = elementBody; + } + + @Override + public Tree visitIdentifier(IdentifierTree node, Element p) { + replaceUsageIfMatch(getCurrentPath(), node, p); + return super.visitIdentifier(node, p); + } + + @Override + public Tree visitMemberSelect(MemberSelectTree node, Element p) { + replaceUsageIfMatch(getCurrentPath(), node, p); + return super.visitMemberSelect(node, p); + } + + private void replaceUsageIfMatch(TreePath path, Tree tree, Element elementToFind) { + if (workingCopy.getTreeUtilities().isSynthetic(path)) { + return; + } + Trees trees = workingCopy.getTrees(); + Element el = workingCopy.getTrees().getElement(path); + if (el == null) { + path = path.getParentPath(); + if (path != null && path.getLeaf().getKind() == Tree.Kind.IMPORT) { + ImportTree impTree = (ImportTree) path.getLeaf(); + if (!impTree.isStatic()) { + return; + } + Tree idTree = impTree.getQualifiedIdentifier(); + if (idTree.getKind() != Tree.Kind.MEMBER_SELECT) { + return; + } + final Name id = ((MemberSelectTree) idTree).getIdentifier(); + if (id == null || id.contentEquals("*")) { // NOI18N + // skip import static java.lang.Math.* + return; + } + Tree classTree = ((MemberSelectTree) idTree).getExpression(); + path = trees.getPath(workingCopy.getCompilationUnit(), classTree); + el = trees.getElement(path); + if (el == null) { + return; + } + Iterator iter = workingCopy.getElementUtilities().getMembers(el.asType(), new ElementUtilities.ElementAcceptor() { + + public boolean accept(Element e, TypeMirror type) { + return id.equals(e.getSimpleName()); + } + }).iterator(); + if (iter.hasNext()) { + el = (Element) iter.next(); + } + if (iter.hasNext()) { + return; + } + } else { + return; + } + } + if (el.equals(elementToFind)) { + rewrite(tree, elementBody); + } + } + + @Override + public Tree visitClass(ClassTree node, Element p) { + Tree tree = workingCopy.getTrees().getTree(p); + if (!node.getMembers().contains(tree)) { + return super.visitClass(node, p); + } + ClassTree nNode = make.removeClassMember(node, tree); + rewrite(node, nNode); + return super.visitClass(node, p); + } + + @Override + public Tree visitVariable(VariableTree node, Element p) { + Element el = workingCopy.getTrees().getElement(getCurrentPath()); + if (!el.getKind().equals(ElementKind.FIELD)) { + if (p.equals(el)) { + Tree parent = getCurrentPath().getParentPath().getLeaf(); + BlockTree newOne = make.removeBlockStatement((BlockTree) parent, node); + if (newOne != null) { + rewrite(parent, newOne); + } + } + } + return super.visitVariable(node, p); + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaRefactoringsFactory.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaRefactoringsFactory.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaRefactoringsFactory.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaRefactoringsFactory.java @@ -49,6 +49,7 @@ import org.netbeans.modules.refactoring.java.api.EncapsulateFieldRefactoring; import org.netbeans.modules.refactoring.java.api.ExtractInterfaceRefactoring; import org.netbeans.modules.refactoring.java.api.ExtractSuperclassRefactoring; +import org.netbeans.modules.refactoring.java.api.InlineRefactoring; import org.netbeans.modules.refactoring.java.api.InnerToOuterRefactoring; import org.netbeans.modules.refactoring.java.api.PullUpRefactoring; import org.netbeans.modules.refactoring.java.api.PushDownRefactoring; @@ -121,6 +122,8 @@ return new EncapsulateFieldRefactoringPlugin((EncapsulateFieldRefactoring) refactoring); } else if (refactoring instanceof EncapsulateFieldsRefactoring) { return new EncapsulateFieldsPlugin((EncapsulateFieldsRefactoring) refactoring); + } else if (refactoring instanceof InlineRefactoring) { + return new InlineRefactoringPlugin((InlineRefactoring) refactoring); } } return null; diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/mf-layer.xml b/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/mf-layer.xml --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/mf-layer.xml +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/resources/mf-layer.xml @@ -75,6 +75,10 @@ + + + + @@ -167,6 +171,9 @@ + + + diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/spi/ui/JavaActionsImplementationProvider.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/spi/ui/JavaActionsImplementationProvider.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/spi/ui/JavaActionsImplementationProvider.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/spi/ui/JavaActionsImplementationProvider.java @@ -197,6 +197,23 @@ */ public void doExtractInterface(Lookup lookup) { throw new UnsupportedOperationException("Not implemented"); // NOI18N - } + } + + /** + * + * @param lookup + * @return true if provider can handle Inline + */ + public boolean canInline(Lookup lookup) { + return false; + } + + /** + * Implementation of Inline + * @param lookup + */ + public void doInline(Lookup lookup) { + throw new UnsupportedOperationException("Not yet implemented"); + } } diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/Bundle.properties b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/Bundle.properties --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/Bundle.properties +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/Bundle.properties @@ -391,3 +391,8 @@ ExtractSuperclassPanel.chooseLabel.AccessibleContext.accessibleDescription=N/A ExtractInterfacePanel.chooseLabel.AccessibleContext.accessibleDescription=N/A + +# *** Inline Refactoring *** +LBL_InlineAction=Inline... +LBL_Inline=Inline +DSC_Inline=Inline instances of {0}? diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineAction.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineAction.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineAction.java @@ -0,0 +1,78 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.refactoring.java.ui; + +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +/** + * Action that invokes Inline Refactoring + * @author ralphbenjamin + */ +public class InlineAction extends JavaRefactoringGlobalAction { + + /** + * Creates a new instance of InlineAction + */ + public InlineAction() { + super(NbBundle.getMessage(InlineAction.class, "LBL_InlineAction"), null); + putValue("noIconInMenu", Boolean.TRUE);// NOI18N + } + + @Override + public final void performAction(Lookup context) { + JavaActionsImplementationFactory.doInline(context); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected boolean enable(Lookup context) { + return JavaActionsImplementationFactory.canInline(context); + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.form b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.form new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.form @@ -0,0 +1,48 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlinePanel.java @@ -0,0 +1,100 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.refactoring.java.ui; + +import java.awt.Component; +import java.text.MessageFormat; +import org.netbeans.modules.refactoring.java.api.InlineRefactoring; +import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel; + +/** + * Panel used for the Inline refactoring. Contains just a confirmation message. + * @author ralphbenjamin + */ +public class InlinePanel extends javax.swing.JPanel implements CustomRefactoringPanel { + private final InlineRefactoring refactoring; + + /** Creates new form InlinePanel */ + public InlinePanel(InlineRefactoring refactoring) { + initComponents(); + this.refactoring = refactoring; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + + jLabel1.setText(org.openide.util.NbBundle.getMessage(InlinePanel.class, "DSC_Inline")); // NOI18N + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(jLabel1) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(jLabel1) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + // End of variables declaration//GEN-END:variables + + public void initialize() { + jLabel1.setText(new MessageFormat(jLabel1.getText()).format(new Object[] {refactoring.getName()}).toString()); + } + + public Component getComponent() { + return this; + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineRefactoringUI.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineRefactoringUI.java new file mode 100644 --- /dev/null +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/InlineRefactoringUI.java @@ -0,0 +1,104 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.refactoring.java.ui; + +import java.text.MessageFormat; +import javax.swing.event.ChangeListener; +import org.netbeans.api.java.source.TreePathHandle; +import org.netbeans.modules.refactoring.api.AbstractRefactoring; +import org.netbeans.modules.refactoring.api.Problem; +import org.netbeans.modules.refactoring.java.api.InlineRefactoring; +import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel; +import org.netbeans.modules.refactoring.spi.ui.RefactoringUI; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; + +/** + * RefactoringUI object for the Inline refactoring. + * @author ralphbenjamin + */ +public class InlineRefactoringUI implements RefactoringUI { + + private final InlineRefactoring refactoring; + private InlinePanel panel; + + public InlineRefactoringUI(TreePathHandle selectedElement) { + this.refactoring = new InlineRefactoring(selectedElement); + } + + public String getDescription() { + return new MessageFormat(NbBundle.getMessage(InnerToOuterAction.class, "DSC_Inline")) + .format(new Object[] {refactoring.getName()}); // NOI18N + } + + public String getName() { + return NbBundle.getMessage(InnerToOuterAction.class, "LBL_Inline"); // NOI18N + } + + public boolean isQuery() { + return false; + } + + public CustomRefactoringPanel getPanel(ChangeListener parent) { + if (panel == null) { + panel = new InlinePanel(refactoring); + } + return panel; + } + + public Problem setParameters() { + return refactoring.fastCheckParameters(); + } + + public Problem checkParameters() { + return refactoring.checkParameters(); + } + + public boolean hasParameters() { + return true; + } + + public AbstractRefactoring getRefactoring() { + return refactoring; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } +} diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaActionsImplementationFactory.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaActionsImplementationFactory.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaActionsImplementationFactory.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaActionsImplementationFactory.java @@ -196,6 +196,22 @@ } return false; } + + public static void doInline(Lookup lookup) { + for (JavaActionsImplementationProvider rafi : implementations.allInstances()) { + if (rafi.canInline(lookup)) { + rafi.doInline(lookup); + return; + } + } + } - + public static boolean canInline(Lookup lookup) { + for (JavaActionsImplementationProvider rafi : implementations.allInstances()) { + if(rafi.canInline(lookup)) { + return true; + } + } + return false; + } } diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaRefactoringActionsProvider.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaRefactoringActionsProvider.java --- a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaRefactoringActionsProvider.java +++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/JavaRefactoringActionsProvider.java @@ -615,6 +615,75 @@ } RetoucheUtils.invokeAfterScanFinished(task, RefactoringActionsProvider.getActionName(JavaRefactoringActionsFactory.encapsulateFieldsAction())); } + + @Override + public boolean canInline(Lookup lookup) { + Collection nodes = new HashSet(lookup.lookupAll(Node.class)); + if (nodes.size() != 1) { + return false; + } + Node n = nodes.iterator().next(); + TreePathHandle tph = n.getLookup().lookup(TreePathHandle.class); + if (tph != null) { + return RetoucheUtils.isRefactorable(tph.getFileObject()); + } + DataObject dob = n.getCookie(DataObject.class); + if (dob == null) { + return false; + } + FileObject fo = dob.getPrimaryFile(); + if (RetoucheUtils.isRefactorable(fo)) { //NOI18N + return true; + } + return false; + } + + @Override + public void doInline(Lookup lookup) { + Runnable task; + EditorCookie ec = lookup.lookup(EditorCookie.class); + if (RefactoringActionsProvider.isFromEditor(ec)) { + task = new RefactoringActionsProvider.TextComponentTask(ec) { + + @Override + protected RefactoringUI createRefactoringUI(TreePathHandle selectedElement, int startOffset, int endOffset, CompilationInfo info) { + return new InlineRefactoringUI(selectedElement); + } + }; + } else if (RefactoringActionsProvider.nodeHandle(lookup)) { + task = new TreePathHandleTask(new HashSet(lookup.lookupAll(Node.class)), true) { + + RefactoringUI ui; + + @Override + protected void treePathHandleResolved(TreePathHandle handle, CompilationInfo javac) { + ui = new InlineRefactoringUI(handle); + } + + @Override + protected RefactoringUI createRefactoringUI(Collection handles) { + return ui; + } + }; + } else { + task = new NodeToFileObjectTask(Collections.singleton(lookup.lookup(Node.class))) { + + RefactoringUI ui; + + @Override + protected void nodeTranslated(Node node, Collection handles, CompilationInfo javac) { + TreePathHandle tph = handles.iterator().next(); + ui = new InlineRefactoringUI(tph); + } + + @Override + protected RefactoringUI createRefactoringUI(FileObject[] selectedElements, Collection handles) { + return ui; + } + }; + } + RetoucheUtils.invokeAfterScanFinished(task, RefactoringActionsProvider.getActionName(JavaRefactoringActionsFactory.inlineAction())); + } private static TreePathHandle findSelectedClassMemberDeclaration(TreePathHandle path, final CompilationInfo info) { TreePath resolved = path.resolve(info);