A crude sketch of find and replace method duplicates.
authorJan Lahoda <jlahoda@netbeans.org>
Sat, 06 Jul 2013 15:15:21 +0200
changeset 973ecaacce31034
parent 972 5c7fa3e46c42
child 974 0a968eab2727
A crude sketch of find and replace method duplicates.
java.hints/hintsimpl/nbproject/genfiles.properties
java.hints/hintsimpl/nbproject/project.properties
java.hints/hintsimpl/nbproject/project.xml
java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoring.java
java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringAction.java
java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringPlugin.java
java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringUI.java
java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/RefactoringPluginFactoryImpl.java
java.hints/hintsimpl/test/unit/src/org/netbeans/modules/jackpot30/hintsimpl/borrowed/RefactoringTestBase.java
java.hints/hintsimpl/test/unit/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringPluginTest.java
     1.1 --- a/java.hints/hintsimpl/nbproject/genfiles.properties	Mon Jul 01 23:46:49 2013 +0200
     1.2 +++ b/java.hints/hintsimpl/nbproject/genfiles.properties	Sat Jul 06 15:15:21 2013 +0200
     1.3 @@ -1,8 +1,8 @@
     1.4 -build.xml.data.CRC32=4bedd36b
     1.5 +build.xml.data.CRC32=4ab9923f
     1.6  build.xml.script.CRC32=ef577a91
     1.7 -build.xml.stylesheet.CRC32=a56c6a5b@2.58
     1.8 +build.xml.stylesheet.CRC32=a56c6a5b@2.61
     1.9  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    1.10  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    1.11 -nbproject/build-impl.xml.data.CRC32=4bedd36b
    1.12 +nbproject/build-impl.xml.data.CRC32=4ab9923f
    1.13  nbproject/build-impl.xml.script.CRC32=9204f652
    1.14 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.58
    1.15 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.61
     2.1 --- a/java.hints/hintsimpl/nbproject/project.properties	Mon Jul 01 23:46:49 2013 +0200
     2.2 +++ b/java.hints/hintsimpl/nbproject/project.properties	Sat Jul 06 15:15:21 2013 +0200
     2.3 @@ -2,3 +2,4 @@
     2.4  javac.compilerargs=-Xlint -Xlint:-serial
     2.5  requires.nb.javac=true
     2.6  spec.version.base=1.0
     2.7 +test.runner=junit
     3.1 --- a/java.hints/hintsimpl/nbproject/project.xml	Mon Jul 01 23:46:49 2013 +0200
     3.2 +++ b/java.hints/hintsimpl/nbproject/project.xml	Sat Jul 06 15:15:21 2013 +0200
     3.3 @@ -16,6 +16,15 @@
     3.4                      </run-dependency>
     3.5                  </dependency>
     3.6                  <dependency>
     3.7 +                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
     3.8 +                    <build-prerequisite/>
     3.9 +                    <compile-dependency/>
    3.10 +                    <run-dependency>
    3.11 +                        <release-version>1</release-version>
    3.12 +                        <specification-version>1.39</specification-version>
    3.13 +                    </run-dependency>
    3.14 +                </dependency>
    3.15 +                <dependency>
    3.16                      <code-name-base>org.netbeans.libs.javacapi</code-name-base>
    3.17                      <build-prerequisite/>
    3.18                      <compile-dependency/>
    3.19 @@ -41,6 +50,41 @@
    3.20                      </run-dependency>
    3.21                  </dependency>
    3.22                  <dependency>
    3.23 +                    <code-name-base>org.netbeans.modules.java.sourceui</code-name-base>
    3.24 +                    <build-prerequisite/>
    3.25 +                    <compile-dependency/>
    3.26 +                    <run-dependency>
    3.27 +                        <release-version>1</release-version>
    3.28 +                        <specification-version>1.33.0.1.25</specification-version>
    3.29 +                    </run-dependency>
    3.30 +                </dependency>
    3.31 +                <dependency>
    3.32 +                    <code-name-base>org.netbeans.modules.queries</code-name-base>
    3.33 +                    <build-prerequisite/>
    3.34 +                    <compile-dependency/>
    3.35 +                    <run-dependency>
    3.36 +                        <release-version>1</release-version>
    3.37 +                        <specification-version>1.36</specification-version>
    3.38 +                    </run-dependency>
    3.39 +                </dependency>
    3.40 +                <dependency>
    3.41 +                    <code-name-base>org.netbeans.modules.refactoring.api</code-name-base>
    3.42 +                    <build-prerequisite/>
    3.43 +                    <compile-dependency/>
    3.44 +                    <run-dependency>
    3.45 +                        <specification-version>1.37.0.1</specification-version>
    3.46 +                    </run-dependency>
    3.47 +                </dependency>
    3.48 +                <dependency>
    3.49 +                    <code-name-base>org.netbeans.modules.refactoring.java</code-name-base>
    3.50 +                    <build-prerequisite/>
    3.51 +                    <compile-dependency/>
    3.52 +                    <run-dependency>
    3.53 +                        <release-version>1</release-version>
    3.54 +                        <implementation-version/>
    3.55 +                    </run-dependency>
    3.56 +                </dependency>
    3.57 +                <dependency>
    3.58                      <code-name-base>org.netbeans.spi.editor.hints</code-name-base>
    3.59                      <build-prerequisite/>
    3.60                      <compile-dependency/>
    3.61 @@ -58,6 +102,46 @@
    3.62                      </run-dependency>
    3.63                  </dependency>
    3.64                  <dependency>
    3.65 +                    <code-name-base>org.openide.awt</code-name-base>
    3.66 +                    <build-prerequisite/>
    3.67 +                    <compile-dependency/>
    3.68 +                    <run-dependency>
    3.69 +                        <specification-version>7.59</specification-version>
    3.70 +                    </run-dependency>
    3.71 +                </dependency>
    3.72 +                <dependency>
    3.73 +                    <code-name-base>org.openide.filesystems</code-name-base>
    3.74 +                    <build-prerequisite/>
    3.75 +                    <compile-dependency/>
    3.76 +                    <run-dependency>
    3.77 +                        <specification-version>8.8</specification-version>
    3.78 +                    </run-dependency>
    3.79 +                </dependency>
    3.80 +                <dependency>
    3.81 +                    <code-name-base>org.openide.loaders</code-name-base>
    3.82 +                    <build-prerequisite/>
    3.83 +                    <compile-dependency/>
    3.84 +                    <run-dependency>
    3.85 +                        <specification-version>7.50</specification-version>
    3.86 +                    </run-dependency>
    3.87 +                </dependency>
    3.88 +                <dependency>
    3.89 +                    <code-name-base>org.openide.nodes</code-name-base>
    3.90 +                    <build-prerequisite/>
    3.91 +                    <compile-dependency/>
    3.92 +                    <run-dependency>
    3.93 +                        <specification-version>7.36</specification-version>
    3.94 +                    </run-dependency>
    3.95 +                </dependency>
    3.96 +                <dependency>
    3.97 +                    <code-name-base>org.openide.text</code-name-base>
    3.98 +                    <build-prerequisite/>
    3.99 +                    <compile-dependency/>
   3.100 +                    <run-dependency>
   3.101 +                        <specification-version>6.57</specification-version>
   3.102 +                    </run-dependency>
   3.103 +                </dependency>
   3.104 +                <dependency>
   3.105                      <code-name-base>org.openide.util</code-name-base>
   3.106                      <build-prerequisite/>
   3.107                      <compile-dependency/>
   3.108 @@ -65,19 +149,48 @@
   3.109                          <specification-version>8.32</specification-version>
   3.110                      </run-dependency>
   3.111                  </dependency>
   3.112 +                <dependency>
   3.113 +                    <code-name-base>org.openide.util.lookup</code-name-base>
   3.114 +                    <build-prerequisite/>
   3.115 +                    <compile-dependency/>
   3.116 +                    <run-dependency>
   3.117 +                        <specification-version>8.22</specification-version>
   3.118 +                    </run-dependency>
   3.119 +                </dependency>
   3.120 +                <dependency>
   3.121 +                    <code-name-base>org.openide.windows</code-name-base>
   3.122 +                    <build-prerequisite/>
   3.123 +                    <compile-dependency/>
   3.124 +                    <run-dependency>
   3.125 +                        <specification-version>6.64</specification-version>
   3.126 +                    </run-dependency>
   3.127 +                </dependency>
   3.128              </module-dependencies>
   3.129              <test-dependencies>
   3.130                  <test-type>
   3.131                      <name>unit</name>
   3.132                      <test-dependency>
   3.133 +                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
   3.134 +                        <compile-dependency/>
   3.135 +                    </test-dependency>
   3.136 +                    <test-dependency>
   3.137                          <code-name-base>org.netbeans.libs.testng</code-name-base>
   3.138                          <compile-dependency/>
   3.139                      </test-dependency>
   3.140                      <test-dependency>
   3.141 +                        <code-name-base>org.netbeans.modules.jackpot30.test.borrowed</code-name-base>
   3.142 +                        <compile-dependency/>
   3.143 +                    </test-dependency>
   3.144 +                    <test-dependency>
   3.145                          <code-name-base>org.netbeans.modules.java.hints.test</code-name-base>
   3.146                          <recursive/>
   3.147                          <compile-dependency/>
   3.148                      </test-dependency>
   3.149 +                    <test-dependency>
   3.150 +                        <code-name-base>org.netbeans.spi.java.hints</code-name-base>
   3.151 +                        <compile-dependency/>
   3.152 +                        <test/>
   3.153 +                    </test-dependency>
   3.154                  </test-type>
   3.155              </test-dependencies>
   3.156              <public-packages/>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoring.java	Sat Jul 06 15:15:21 2013 +0200
     4.3 @@ -0,0 +1,58 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
     4.8 + *
     4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    4.10 + * Other names may be trademarks of their respective owners.
    4.11 + *
    4.12 + * The contents of this file are subject to the terms of either the GNU
    4.13 + * General Public License Version 2 only ("GPL") or the Common
    4.14 + * Development and Distribution License("CDDL") (collectively, the
    4.15 + * "License"). You may not use this file except in compliance with the
    4.16 + * License. You can obtain a copy of the License at
    4.17 + * http://www.netbeans.org/cddl-gplv2.html
    4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.19 + * specific language governing permissions and limitations under the
    4.20 + * License.  When distributing the software, include this License Header
    4.21 + * Notice in each file and include the License file at
    4.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    4.23 + * particular file as subject to the "Classpath" exception as provided
    4.24 + * by Oracle in the GPL Version 2 section of the License file that
    4.25 + * accompanied this code. If applicable, add the following below the
    4.26 + * License Header, with the fields enclosed by brackets [] replaced by
    4.27 + * your own identifying information:
    4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.29 + *
    4.30 + * If you wish your version of this file to be governed by only the CDDL
    4.31 + * or only the GPL Version 2, indicate your decision by adding
    4.32 + * "[Contributor] elects to include this software in this distribution
    4.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.34 + * single choice of license, a recipient has the option to distribute
    4.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.36 + * to extend the choice of license to its licensees as provided above.
    4.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.38 + * Version 2 license, then the option applies only if the new code is
    4.39 + * made subject to such option by the copyright holder.
    4.40 + *
    4.41 + * Contributor(s):
    4.42 + *
    4.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
    4.44 + */
    4.45 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
    4.46 +
    4.47 +import org.netbeans.api.java.source.TreePathHandle;
    4.48 +import org.netbeans.modules.refactoring.api.AbstractRefactoring;
    4.49 +import org.openide.util.lookup.Lookups;
    4.50 +
    4.51 +/**
    4.52 + *
    4.53 + * @author lahvac
    4.54 + */
    4.55 +public class DuplicateMethodRefactoring extends AbstractRefactoring {
    4.56 +
    4.57 +    public DuplicateMethodRefactoring(TreePathHandle source) {
    4.58 +        super(Lookups.singleton(source));
    4.59 +    }
    4.60 +
    4.61 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringAction.java	Sat Jul 06 15:15:21 2013 +0200
     5.3 @@ -0,0 +1,84 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
     5.8 + *
     5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    5.10 + * Other names may be trademarks of their respective owners.
    5.11 + *
    5.12 + * The contents of this file are subject to the terms of either the GNU
    5.13 + * General Public License Version 2 only ("GPL") or the Common
    5.14 + * Development and Distribution License("CDDL") (collectively, the
    5.15 + * "License"). You may not use this file except in compliance with the
    5.16 + * License. You can obtain a copy of the License at
    5.17 + * http://www.netbeans.org/cddl-gplv2.html
    5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.19 + * specific language governing permissions and limitations under the
    5.20 + * License.  When distributing the software, include this License Header
    5.21 + * Notice in each file and include the License file at
    5.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    5.23 + * particular file as subject to the "Classpath" exception as provided
    5.24 + * by Oracle in the GPL Version 2 section of the License file that
    5.25 + * accompanied this code. If applicable, add the following below the
    5.26 + * License Header, with the fields enclosed by brackets [] replaced by
    5.27 + * your own identifying information:
    5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    5.29 + *
    5.30 + * If you wish your version of this file to be governed by only the CDDL
    5.31 + * or only the GPL Version 2, indicate your decision by adding
    5.32 + * "[Contributor] elects to include this software in this distribution
    5.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    5.34 + * single choice of license, a recipient has the option to distribute
    5.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    5.36 + * to extend the choice of license to its licensees as provided above.
    5.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    5.38 + * Version 2 license, then the option applies only if the new code is
    5.39 + * made subject to such option by the copyright holder.
    5.40 + *
    5.41 + * Contributor(s):
    5.42 + *
    5.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
    5.44 + */
    5.45 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
    5.46 +
    5.47 +import com.sun.source.tree.Tree.Kind;
    5.48 +import java.awt.event.ActionEvent;
    5.49 +import java.awt.event.ActionListener;
    5.50 +import org.netbeans.api.fileinfo.NonRecursiveFolder;
    5.51 +import org.netbeans.api.java.source.CompilationInfo;
    5.52 +import org.netbeans.api.java.source.TreePathHandle;
    5.53 +import org.netbeans.api.java.source.ui.ScanDialog;
    5.54 +import org.netbeans.modules.refactoring.java.ui.ContextAnalyzer;
    5.55 +import org.netbeans.modules.refactoring.java.ui.JavaRefactoringUIFactory;
    5.56 +import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
    5.57 +import org.openide.awt.ActionID;
    5.58 +import org.openide.awt.ActionReference;
    5.59 +import org.openide.awt.ActionRegistration;
    5.60 +import org.openide.filesystems.FileObject;
    5.61 +import org.openide.util.NbBundle.Messages;
    5.62 +import org.openide.util.Utilities;
    5.63 +
    5.64 +@ActionID(
    5.65 +        category = "Refactoring",
    5.66 +        id = "org.netbeans.modules.jackpot30.hintsimpl.duplicates.DuplicateMethodRefactoringAction")
    5.67 +@ActionRegistration(
    5.68 +        displayName = "#CTL_DuplicateMethodRefactoringAction")
    5.69 +@ActionReference(path = "Menu/Refactoring", position = 1120)
    5.70 +@Messages("CTL_DuplicateMethodRefactoringAction=Find and Replace Duplicates...")
    5.71 +public final class DuplicateMethodRefactoringAction implements ActionListener {
    5.72 +
    5.73 +    @Override
    5.74 +    public void actionPerformed(ActionEvent e) {
    5.75 +        Runnable task = ContextAnalyzer.createTask(Utilities.actionsGlobalContext()/*!!!*/, new JavaRefactoringUIFactory() {
    5.76 +            @Override public RefactoringUI create(CompilationInfo info, TreePathHandle[] handles, FileObject[] files, NonRecursiveFolder[] packages) {
    5.77 +                //todo: more precise verification of refactoring feasibility:
    5.78 +                return handles.length == 1 && handles[0].getKind() == Kind.METHOD ? new DuplicateMethodRefactoringUI(handles[0]) : null;
    5.79 +            }
    5.80 +        });
    5.81 +        ScanDialog.runWhenScanFinished(task, "Find&Replace Duplicates");
    5.82 +    }
    5.83 +
    5.84 +    public boolean isEnabled() {
    5.85 +        return ContextAnalyzer.canRefactorSingle(Utilities.actionsGlobalContext()/*!!!*/, true, true);
    5.86 +    }
    5.87 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringPlugin.java	Sat Jul 06 15:15:21 2013 +0200
     6.3 @@ -0,0 +1,183 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
     6.8 + *
     6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    6.10 + * Other names may be trademarks of their respective owners.
    6.11 + *
    6.12 + * The contents of this file are subject to the terms of either the GNU
    6.13 + * General Public License Version 2 only ("GPL") or the Common
    6.14 + * Development and Distribution License("CDDL") (collectively, the
    6.15 + * "License"). You may not use this file except in compliance with the
    6.16 + * License. You can obtain a copy of the License at
    6.17 + * http://www.netbeans.org/cddl-gplv2.html
    6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    6.19 + * specific language governing permissions and limitations under the
    6.20 + * License.  When distributing the software, include this License Header
    6.21 + * Notice in each file and include the License file at
    6.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    6.23 + * particular file as subject to the "Classpath" exception as provided
    6.24 + * by Oracle in the GPL Version 2 section of the License file that
    6.25 + * accompanied this code. If applicable, add the following below the
    6.26 + * License Header, with the fields enclosed by brackets [] replaced by
    6.27 + * your own identifying information:
    6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    6.29 + *
    6.30 + * If you wish your version of this file to be governed by only the CDDL
    6.31 + * or only the GPL Version 2, indicate your decision by adding
    6.32 + * "[Contributor] elects to include this software in this distribution
    6.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    6.34 + * single choice of license, a recipient has the option to distribute
    6.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    6.36 + * to extend the choice of license to its licensees as provided above.
    6.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    6.38 + * Version 2 license, then the option applies only if the new code is
    6.39 + * made subject to such option by the copyright holder.
    6.40 + *
    6.41 + * Contributor(s):
    6.42 + *
    6.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
    6.44 + */
    6.45 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
    6.46 +
    6.47 +import com.sun.source.tree.BlockTree;
    6.48 +import com.sun.source.tree.ExpressionTree;
    6.49 +import com.sun.source.tree.MethodInvocationTree;
    6.50 +import com.sun.source.tree.MethodTree;
    6.51 +import com.sun.source.tree.StatementTree;
    6.52 +import com.sun.source.util.TreePath;
    6.53 +import java.net.URL;
    6.54 +import java.util.ArrayList;
    6.55 +import java.util.Collection;
    6.56 +import java.util.Collections;
    6.57 +import java.util.Enumeration;
    6.58 +import java.util.HashSet;
    6.59 +import java.util.List;
    6.60 +import java.util.Set;
    6.61 +import javax.lang.model.element.Element;
    6.62 +import javax.lang.model.element.ExecutableElement;
    6.63 +import javax.lang.model.element.VariableElement;
    6.64 +import org.netbeans.api.java.source.CancellableTask;
    6.65 +import org.netbeans.api.java.source.ClasspathInfo;
    6.66 +import org.netbeans.api.java.source.ClasspathInfo.PathKind;
    6.67 +import org.netbeans.api.java.source.JavaSource;
    6.68 +import org.netbeans.api.java.source.SourceUtils;
    6.69 +import org.netbeans.api.java.source.TreeMaker;
    6.70 +import org.netbeans.api.java.source.TreePathHandle;
    6.71 +import org.netbeans.api.java.source.WorkingCopy;
    6.72 +import org.netbeans.api.java.source.matching.Matcher;
    6.73 +import org.netbeans.api.java.source.matching.Occurrence;
    6.74 +import org.netbeans.api.java.source.matching.Pattern;
    6.75 +import org.netbeans.modules.refactoring.api.Problem;
    6.76 +import org.netbeans.modules.refactoring.java.spi.JavaRefactoringPlugin;
    6.77 +import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
    6.78 +import org.openide.filesystems.FileObject;
    6.79 +import org.openide.filesystems.FileUtil;
    6.80 +import org.openide.filesystems.URLMapper;
    6.81 +
    6.82 +/**
    6.83 + *
    6.84 + * @author lahvac
    6.85 + */
    6.86 +public class DuplicateMethodRefactoringPlugin extends JavaRefactoringPlugin {
    6.87 +    private final DuplicateMethodRefactoring refactoring;
    6.88 +
    6.89 +    DuplicateMethodRefactoringPlugin(DuplicateMethodRefactoring refactoring) {
    6.90 +        this.refactoring = refactoring;
    6.91 +    }
    6.92 +
    6.93 +    @Override
    6.94 +    public Problem preCheck() {
    6.95 +        return null;
    6.96 +    }
    6.97 +
    6.98 +    @Override
    6.99 +    public Problem checkParameters() {
   6.100 +        return null;
   6.101 +    }
   6.102 +
   6.103 +    @Override
   6.104 +    public Problem fastCheckParameters() {
   6.105 +        return null;
   6.106 +    }
   6.107 +
   6.108 +    @Override
   6.109 +    public void cancelRequest() {
   6.110 +    }
   6.111 +
   6.112 +    @Override
   6.113 +    public Problem prepare(RefactoringElementsBag refactoringElements) {
   6.114 +        final TreePathHandle source = refactoring.getRefactoringSource().lookup(TreePathHandle.class);
   6.115 +        Set<URL> dependent = new HashSet<>();
   6.116 +
   6.117 +        for (FileObject root : ClasspathInfo.create(source.getFileObject()).getClassPath(PathKind.SOURCE).getRoots()) {
   6.118 +            dependent.add(root.toURL());
   6.119 +            dependent.addAll(SourceUtils.getDependentRoots(root.toURL()));
   6.120 +        }
   6.121 +
   6.122 +        Set<FileObject> files = new HashSet<>();
   6.123 +
   6.124 +        for (URL root : dependent) {
   6.125 +            FileObject rootFO = URLMapper.findFileObject(root);
   6.126 +
   6.127 +            if (rootFO == null) continue;
   6.128 +
   6.129 +            for (Enumeration<? extends FileObject> en = rootFO.getChildren(true); en.hasMoreElements(); ){
   6.130 +                FileObject file = en.nextElement();
   6.131 +
   6.132 +                if (file.isData() && "text/x-java".equals(FileUtil.getMIMEType(file, "text/x-java"))) {
   6.133 +                    files.add(file);
   6.134 +                }
   6.135 +            }
   6.136 +        }
   6.137 +
   6.138 +        return createAndAddElements(files, new CancellableTask<WorkingCopy>() {
   6.139 +            @Override public void cancel() {
   6.140 +                //TODO - is used? if yes, implement.
   6.141 +            }
   6.142 +            @Override public void run(WorkingCopy parameter) throws Exception {
   6.143 +                if (parameter.toPhase(org.netbeans.api.java.source.JavaSource.Phase.RESOLVED).compareTo(org.netbeans.api.java.source.JavaSource.Phase.RESOLVED) < 0) {
   6.144 +                    return ;
   6.145 +                }
   6.146 +
   6.147 +                Element methodElement = source.getElementHandle().resolve(parameter);
   6.148 +                TreePath method = parameter.getTrees().getPath(methodElement);
   6.149 +
   6.150 +                if (method == null) {
   6.151 +                    //nothing to do
   6.152 +                    //TODO: create a problem
   6.153 +                    return ;
   6.154 +                }
   6.155 +
   6.156 +                BlockTree content = ((MethodTree) method.getLeaf()).getBody();
   6.157 +                TreePath bodyPath = new TreePath(method, content);
   6.158 +                List<TreePath> statements = new ArrayList<>();
   6.159 +
   6.160 +                for (StatementTree st : content.getStatements()) {
   6.161 +                    statements.add(new TreePath(bodyPath, st));
   6.162 +                }
   6.163 +
   6.164 +                List<? extends VariableElement> formalParameters = ((ExecutableElement) methodElement).getParameters();
   6.165 +                Pattern pattern = Pattern.createPatternWithRemappableVariables(statements, formalParameters, true);
   6.166 +                Collection<? extends Occurrence> found = Matcher.create(parameter).setCancel(cancelRequested).setSearchRoot(new TreePath(parameter.getCompilationUnit())).match(pattern);
   6.167 +                TreeMaker make = parameter.getTreeMaker();
   6.168 +
   6.169 +                for (Occurrence occ : found) {
   6.170 +                    List<ExpressionTree> newParams = new ArrayList<>();
   6.171 +                    for (VariableElement p : formalParameters) {
   6.172 +                        newParams.add((ExpressionTree) occ.getVariablesRemapToTrees().get(p).getLeaf());
   6.173 +                    }
   6.174 +                    MethodInvocationTree newCall = make.MethodInvocation(Collections.<ExpressionTree>emptyList(), make.QualIdent(methodElement), newParams);
   6.175 +                    parameter.rewrite(occ.getOccurrenceRoot().getLeaf(), make.ExpressionStatement(newCall));
   6.176 +                }
   6.177 +            }
   6.178 +        }, refactoringElements, refactoring);
   6.179 +    }
   6.180 +
   6.181 +    @Override
   6.182 +    protected JavaSource getJavaSource(Phase p) {
   6.183 +        return null;
   6.184 +    }
   6.185 +
   6.186 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringUI.java	Sat Jul 06 15:15:21 2013 +0200
     7.3 @@ -0,0 +1,108 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
     7.8 + *
     7.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    7.10 + * Other names may be trademarks of their respective owners.
    7.11 + *
    7.12 + * The contents of this file are subject to the terms of either the GNU
    7.13 + * General Public License Version 2 only ("GPL") or the Common
    7.14 + * Development and Distribution License("CDDL") (collectively, the
    7.15 + * "License"). You may not use this file except in compliance with the
    7.16 + * License. You can obtain a copy of the License at
    7.17 + * http://www.netbeans.org/cddl-gplv2.html
    7.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.19 + * specific language governing permissions and limitations under the
    7.20 + * License.  When distributing the software, include this License Header
    7.21 + * Notice in each file and include the License file at
    7.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    7.23 + * particular file as subject to the "Classpath" exception as provided
    7.24 + * by Oracle in the GPL Version 2 section of the License file that
    7.25 + * accompanied this code. If applicable, add the following below the
    7.26 + * License Header, with the fields enclosed by brackets [] replaced by
    7.27 + * your own identifying information:
    7.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    7.29 + *
    7.30 + * If you wish your version of this file to be governed by only the CDDL
    7.31 + * or only the GPL Version 2, indicate your decision by adding
    7.32 + * "[Contributor] elects to include this software in this distribution
    7.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    7.34 + * single choice of license, a recipient has the option to distribute
    7.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    7.36 + * to extend the choice of license to its licensees as provided above.
    7.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    7.38 + * Version 2 license, then the option applies only if the new code is
    7.39 + * made subject to such option by the copyright holder.
    7.40 + *
    7.41 + * Contributor(s):
    7.42 + *
    7.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
    7.44 + */
    7.45 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
    7.46 +
    7.47 +import javax.swing.event.ChangeListener;
    7.48 +import org.netbeans.api.java.source.TreePathHandle;
    7.49 +import org.netbeans.modules.refactoring.api.AbstractRefactoring;
    7.50 +import org.netbeans.modules.refactoring.api.Problem;
    7.51 +import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
    7.52 +import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
    7.53 +import org.openide.util.HelpCtx;
    7.54 +
    7.55 +/**
    7.56 + *
    7.57 + * @author lahvac
    7.58 + */
    7.59 +public class DuplicateMethodRefactoringUI implements RefactoringUI {
    7.60 +    private final TreePathHandle treePathHandle;
    7.61 +
    7.62 +    DuplicateMethodRefactoringUI(TreePathHandle treePathHandle) {
    7.63 +        this.treePathHandle = treePathHandle;
    7.64 +    }
    7.65 +
    7.66 +    @Override
    7.67 +    public String getName() {
    7.68 +        return "Duplicate Method Refactoring";
    7.69 +    }
    7.70 +
    7.71 +    @Override
    7.72 +    public String getDescription() {
    7.73 +        return "Duplicate Method Refactoring";
    7.74 +    }
    7.75 +
    7.76 +    @Override
    7.77 +    public boolean isQuery() {
    7.78 +        return false;
    7.79 +    }
    7.80 +
    7.81 +    @Override
    7.82 +    public CustomRefactoringPanel getPanel(ChangeListener parent) {
    7.83 +        return null;
    7.84 +    }
    7.85 +
    7.86 +    @Override
    7.87 +    public Problem setParameters() {
    7.88 +        return null;
    7.89 +    }
    7.90 +
    7.91 +    @Override
    7.92 +    public Problem checkParameters() {
    7.93 +        return null;
    7.94 +    }
    7.95 +
    7.96 +    @Override
    7.97 +    public boolean hasParameters() {
    7.98 +        return false;
    7.99 +    }
   7.100 +
   7.101 +    @Override
   7.102 +    public AbstractRefactoring getRefactoring() {
   7.103 +        return new DuplicateMethodRefactoring(treePathHandle);
   7.104 +    }
   7.105 +
   7.106 +    @Override
   7.107 +    public HelpCtx getHelpCtx() {
   7.108 +        return HelpCtx.DEFAULT_HELP;
   7.109 +    }
   7.110 +
   7.111 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/java.hints/hintsimpl/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/RefactoringPluginFactoryImpl.java	Sat Jul 06 15:15:21 2013 +0200
     8.3 @@ -0,0 +1,62 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2008-2010 Sun Microsystems, Inc. All rights reserved.
     8.8 + *
     8.9 + * The contents of this file are subject to the terms of either the GNU
    8.10 + * General Public License Version 2 only ("GPL") or the Common
    8.11 + * Development and Distribution License("CDDL") (collectively, the
    8.12 + * "License"). You may not use this file except in compliance with the
    8.13 + * License. You can obtain a copy of the License at
    8.14 + * http://www.netbeans.org/cddl-gplv2.html
    8.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    8.16 + * specific language governing permissions and limitations under the
    8.17 + * License.  When distributing the software, include this License Header
    8.18 + * Notice in each file and include the License file at
    8.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    8.20 + * particular file as subject to the "Classpath" exception as provided
    8.21 + * by Sun in the GPL Version 2 section of the License file that
    8.22 + * accompanied this code. If applicable, add the following below the
    8.23 + * License Header, with the fields enclosed by brackets [] replaced by
    8.24 + * your own identifying information:
    8.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    8.26 + *
    8.27 + * If you wish your version of this file to be governed by only the CDDL
    8.28 + * or only the GPL Version 2, indicate your decision by adding
    8.29 + * "[Contributor] elects to include this software in this distribution
    8.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.31 + * single choice of license, a recipient has the option to distribute
    8.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.33 + * to extend the choice of license to its licensees as provided above.
    8.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.35 + * Version 2 license, then the option applies only if the new code is
    8.36 + * made subject to such option by the copyright holder.
    8.37 + *
    8.38 + * Contributor(s):
    8.39 + *
    8.40 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
    8.41 + */
    8.42 +
    8.43 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
    8.44 +
    8.45 +import org.netbeans.modules.refactoring.api.AbstractRefactoring;
    8.46 +import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
    8.47 +import org.netbeans.modules.refactoring.spi.RefactoringPluginFactory;
    8.48 +import org.openide.util.lookup.ServiceProvider;
    8.49 +
    8.50 +/**
    8.51 + *
    8.52 + * @author Jan Lahoda
    8.53 + */
    8.54 +@ServiceProvider(service=RefactoringPluginFactory.class)
    8.55 +public class RefactoringPluginFactoryImpl implements RefactoringPluginFactory {
    8.56 +
    8.57 +    public RefactoringPlugin createInstance(AbstractRefactoring refactoring) {
    8.58 +        if (refactoring instanceof DuplicateMethodRefactoring) {
    8.59 +            return new DuplicateMethodRefactoringPlugin((DuplicateMethodRefactoring) refactoring);
    8.60 +        }
    8.61 +
    8.62 +        return null;
    8.63 +    }
    8.64 +
    8.65 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/java.hints/hintsimpl/test/unit/src/org/netbeans/modules/jackpot30/hintsimpl/borrowed/RefactoringTestBase.java	Sat Jul 06 15:15:21 2013 +0200
     9.3 @@ -0,0 +1,387 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2009-2010 Sun Microsystems, Inc. All rights reserved.
     9.8 + *
     9.9 + * The contents of this file are subject to the terms of either the GNU
    9.10 + * General Public License Version 2 only ("GPL") or the Common
    9.11 + * Development and Distribution License("CDDL") (collectively, the
    9.12 + * "License"). You may not use this file except in compliance with the
    9.13 + * License. You can obtain a copy of the License at
    9.14 + * http://www.netbeans.org/cddl-gplv2.html
    9.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.16 + * specific language governing permissions and limitations under the
    9.17 + * License.  When distributing the software, include this License Header
    9.18 + * Notice in each file and include the License file at
    9.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    9.20 + * particular file as subject to the "Classpath" exception as provided
    9.21 + * by Sun in the GPL Version 2 section of the License file that
    9.22 + * accompanied this code. If applicable, add the following below the
    9.23 + * License Header, with the fields enclosed by brackets [] replaced by
    9.24 + * your own identifying information:
    9.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.26 + *
    9.27 + * If you wish your version of this file to be governed by only the CDDL
    9.28 + * or only the GPL Version 2, indicate your decision by adding
    9.29 + * "[Contributor] elects to include this software in this distribution
    9.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.31 + * single choice of license, a recipient has the option to distribute
    9.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.33 + * to extend the choice of license to its licensees as provided above.
    9.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.35 + * Version 2 license, then the option applies only if the new code is
    9.36 + * made subject to such option by the copyright holder.
    9.37 + *
    9.38 + * Contributor(s):
    9.39 + *
    9.40 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
    9.41 + */
    9.42 +package org.netbeans.modules.jackpot30.hintsimpl.borrowed;
    9.43 +
    9.44 +import java.io.EOFException;
    9.45 +import java.io.FileInputStream;
    9.46 +import java.io.IOException;
    9.47 +import java.nio.charset.Charset;
    9.48 +import java.util.Arrays;
    9.49 +import java.util.Collections;
    9.50 +import java.util.HashMap;
    9.51 +import java.util.HashSet;
    9.52 +import java.util.Iterator;
    9.53 +import java.util.LinkedList;
    9.54 +import java.util.List;
    9.55 +import java.util.Map;
    9.56 +import java.util.logging.Level;
    9.57 +import java.util.logging.Logger;
    9.58 +import javax.swing.event.ChangeListener;
    9.59 +import org.netbeans.api.editor.mimelookup.MimePath;
    9.60 +import org.netbeans.api.java.classpath.ClassPath;
    9.61 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
    9.62 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
    9.63 +import org.netbeans.api.java.source.TestUtilities;
    9.64 +import org.netbeans.api.java.source.TreeUtilities;
    9.65 +import org.netbeans.api.project.Project;
    9.66 +import org.netbeans.api.project.ProjectManager;
    9.67 +import org.netbeans.api.project.SourceGroup;
    9.68 +import org.netbeans.api.project.Sources;
    9.69 +import org.netbeans.core.startup.Main;
    9.70 +import org.netbeans.junit.NbTestCase;
    9.71 +import org.netbeans.modules.java.source.indexing.JavaCustomIndexer;
    9.72 +import org.netbeans.modules.parsing.api.indexing.IndexingManager;
    9.73 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
    9.74 +import org.netbeans.modules.parsing.impl.indexing.MimeTypes;
    9.75 +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
    9.76 +import org.netbeans.modules.refactoring.api.Problem;
    9.77 +import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
    9.78 +import org.netbeans.spi.gototest.TestLocator;
    9.79 +import org.netbeans.spi.gototest.TestLocator.FileType;
    9.80 +import org.netbeans.spi.gototest.TestLocator.LocationListener;
    9.81 +import org.netbeans.spi.gototest.TestLocator.LocationResult;
    9.82 +import org.netbeans.spi.java.classpath.ClassPathProvider;
    9.83 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
    9.84 +import org.netbeans.spi.project.ProjectFactory;
    9.85 +import org.netbeans.spi.project.ProjectState;
    9.86 +import org.netbeans.spi.project.support.GenericSources;
    9.87 +import org.openide.filesystems.FileObject;
    9.88 +import org.openide.filesystems.FileUtil;
    9.89 +import org.openide.util.Lookup;
    9.90 +import org.openide.util.NbBundle;
    9.91 +import org.openide.util.lookup.Lookups;
    9.92 +import org.openide.util.lookup.ServiceProvider;
    9.93 +
    9.94 +public class RefactoringTestBase extends NbTestCase {
    9.95 +    // Turning off annoying info messages from treeutilities
    9.96 +    private static final Logger TREEUTILITIESLOGGER = Logger.getLogger(TreeUtilities.class.getName());
    9.97 +
    9.98 +    public RefactoringTestBase(String name) {
    9.99 +        super(name);
   9.100 +    }
   9.101 +
   9.102 +    protected static void writeFilesAndWaitForScan(FileObject sourceRoot, File... files) throws Exception {
   9.103 +        for (FileObject c : sourceRoot.getChildren()) {
   9.104 +            c.delete();
   9.105 +        }
   9.106 +
   9.107 +        for (File f : files) {
   9.108 +            FileObject fo = FileUtil.createData(sourceRoot, f.filename);
   9.109 +            TestUtilities.copyStringToFile(fo, f.content);
   9.110 +        }
   9.111 +
   9.112 +        IndexingManager.getDefault().refreshIndexAndWait(sourceRoot.toURL(), null, true);
   9.113 +    }
   9.114 +
   9.115 +    protected void verifyContent(FileObject sourceRoot, File... files) throws Exception {
   9.116 +        List<FileObject> todo = new LinkedList<FileObject>();
   9.117 +
   9.118 +        todo.add(sourceRoot);
   9.119 +
   9.120 +        Map<String, String> content = new HashMap<String, String>();
   9.121 +
   9.122 +        FileUtil.refreshFor(FileUtil.toFile(sourceRoot));
   9.123 +
   9.124 +        while (!todo.isEmpty()) {
   9.125 +            FileObject file = todo.remove(0);
   9.126 +
   9.127 +            if (file.isData()) {
   9.128 +                content.put(FileUtil.getRelativePath(sourceRoot, file), copyFileToString(FileUtil.toFile(file)));
   9.129 +            } else {
   9.130 +                todo.addAll(Arrays.asList(file.getChildren()));
   9.131 +            }
   9.132 +        }
   9.133 +
   9.134 +        for (File f : files) {
   9.135 +            String fileContent = content.remove(f.filename);
   9.136 +
   9.137 +            assertNotNull(f);
   9.138 +            assertNotNull(f.content);
   9.139 +            assertNotNull("Cannot find " + f.filename + " in map " + content, fileContent);
   9.140 +            assertEquals(getName() ,f.content.replaceAll("[ \t\r\n\n]+", " "), fileContent.replaceAll("[ \t\r\n\n]+", " "));
   9.141 +        }
   9.142 +
   9.143 +        assertTrue(content.toString(), content.isEmpty());
   9.144 +    }
   9.145 +    
   9.146 +    /**
   9.147 +     * Returns a string which contains the contents of a file.
   9.148 +     *
   9.149 +     * @param f the file to be read
   9.150 +     * @return the contents of the file(s).
   9.151 +     */
   9.152 +    private static String copyFileToString(java.io.File f) throws java.io.IOException {
   9.153 +        int s = (int) f.length();
   9.154 +        byte[] data = new byte[s];
   9.155 +        int len = new FileInputStream(f).read(data);
   9.156 +        if (len != s) {
   9.157 +            throw new EOFException("truncated file");
   9.158 +        }
   9.159 +        return new String(data, Charset.forName("UTF8"));
   9.160 +    }
   9.161 +
   9.162 +    protected static void addAllProblems(List<Problem> problems, Problem head) {
   9.163 +        while (head != null) {
   9.164 +            problems.add(head);
   9.165 +            head = head.getNext();
   9.166 +        }
   9.167 +    }
   9.168 +
   9.169 +    protected static void assertProblems(Iterable<? extends Problem> golden, Iterable<? extends Problem> real) {
   9.170 +        Iterator<? extends Problem> g = golden.iterator();
   9.171 +        Iterator<? extends Problem> r = real.iterator();
   9.172 +
   9.173 +        while (g.hasNext() && r.hasNext()) {
   9.174 +            Problem gp = g.next();
   9.175 +            Problem rp = r.next();
   9.176 +
   9.177 +            assertEquals(gp.isFatal(), rp.isFatal());
   9.178 +            assertEquals(gp.getMessage(), rp.getMessage());
   9.179 +        }
   9.180 +        boolean goldenHasNext = g.hasNext();
   9.181 +        boolean realHasNext = r.hasNext();
   9.182 +
   9.183 +        assertFalse(goldenHasNext?"Expected: " + g.next().getMessage():"", goldenHasNext);
   9.184 +        assertFalse(realHasNext?"Unexpected: " + r.next().getMessage():"", realHasNext);
   9.185 +    }
   9.186 +
   9.187 +    static {
   9.188 +        NbBundle.setBranding("test");
   9.189 +    }
   9.190 +
   9.191 +    protected static final class File {
   9.192 +        public final String filename;
   9.193 +        public final String content;
   9.194 +
   9.195 +        public File(String filename, String content) {
   9.196 +            this.filename = filename;
   9.197 +            this.content = content;
   9.198 +        }
   9.199 +    }
   9.200 +
   9.201 +    protected FileObject src;
   9.202 +    protected FileObject test;
   9.203 +    protected Project prj;
   9.204 +    private ClassPath sourcePath;
   9.205 +
   9.206 +    @Override
   9.207 +    protected void setUp() throws Exception {
   9.208 +        System.setProperty("org.netbeans.modules.java.source.usages.SourceAnalyser.fullIndex", "true");
   9.209 +        TREEUTILITIESLOGGER.setLevel(Level.SEVERE);
   9.210 +        MimeTypes.setAllMimeTypes(new HashSet<String>());
   9.211 +        SourceUtilsTestUtil.prepareTest(new String[] {"org/netbeans/modules/openide/loaders/layer.xml",
   9.212 +                    "org/netbeans/modules/java/source/resources/layer.xml",
   9.213 +                    "org/netbeans/modules/java/editor/resources/layer.xml",
   9.214 +            /*"org/netbeans/modules/refactoring/java/test/resources/layer.xml", */"META-INF/generated-layer.xml"}, new Object[] {
   9.215 +                    new ClassPathProvider() {
   9.216 +                        @Override
   9.217 +                        public ClassPath findClassPath(FileObject file, String type) {
   9.218 +                    if (sourcePath != null && sourcePath.contains(file)){
   9.219 +                                if (ClassPath.BOOT.equals(type)) {
   9.220 +                                    return ClassPathSupport.createClassPath(System.getProperty("sun.boot.class.path"));
   9.221 +                                }
   9.222 +                                if (ClassPath.COMPILE.equals(type)) {
   9.223 +                                    return ClassPathSupport.createClassPath(new FileObject[0]);
   9.224 +                                }
   9.225 +                                if (ClassPath.SOURCE.equals(type)) {
   9.226 +                                    return sourcePath;
   9.227 +                                }
   9.228 +                            }
   9.229 +
   9.230 +                            return null;
   9.231 +                        }
   9.232 +                    },
   9.233 +                    new ProjectFactory() {
   9.234 +                        @Override
   9.235 +                        public boolean isProject(FileObject projectDirectory) {
   9.236 +                            return src != null && src.getParent() == projectDirectory;
   9.237 +                        }
   9.238 +                        @Override
   9.239 +                        public Project loadProject(final FileObject projectDirectory, ProjectState state) throws IOException {
   9.240 +                if (!isProject(projectDirectory)) {
   9.241 +                    return null;
   9.242 +                }
   9.243 +                            return new Project() {
   9.244 +                                @Override
   9.245 +                                public FileObject getProjectDirectory() {
   9.246 +                                    return projectDirectory;
   9.247 +                                }
   9.248 +                                @Override
   9.249 +                                public Lookup getLookup() {
   9.250 +                                    final Project p = this;
   9.251 +                                    return Lookups.singleton(new Sources() {
   9.252 +
   9.253 +                                        @Override
   9.254 +                                        public SourceGroup[] getSourceGroups(String type) {
   9.255 +                                return new SourceGroup[] {GenericSources.group(p, src.getParent(), "source", "Java Sources", null, null),
   9.256 +                                                        GenericSources.group(p, test, "testsources", "Test Sources", null, null)};
   9.257 +                                        }
   9.258 +
   9.259 +                                        @Override
   9.260 +                                        public void addChangeListener(ChangeListener listener) {
   9.261 +                                        }
   9.262 +
   9.263 +                                        @Override
   9.264 +                                        public void removeChangeListener(ChangeListener listener) {
   9.265 +                                        }
   9.266 +                                    });
   9.267 +                                }
   9.268 +                            };
   9.269 +                        }
   9.270 +                        @Override
   9.271 +            public void saveProject(Project project) throws IOException, ClassCastException {}
   9.272 +                    },
   9.273 +                    new TestLocator() {
   9.274 +
   9.275 +                        @Override
   9.276 +                        public boolean appliesTo(FileObject fo) {
   9.277 +                            return true;
   9.278 +                        }
   9.279 +
   9.280 +                        @Override
   9.281 +                        public boolean asynchronous() {
   9.282 +                            return false;
   9.283 +                        }
   9.284 +
   9.285 +                        @Override
   9.286 +                        public LocationResult findOpposite(FileObject fo, int caretOffset) {
   9.287 +                            ClassPath srcCp;
   9.288 +
   9.289 +                            if ((srcCp = ClassPath.getClassPath(fo, ClassPath.SOURCE)) == null) {
   9.290 +                                return new LocationResult("File not found"); //NOI18N
   9.291 +                            }
   9.292 +
   9.293 +                            String baseResName = srcCp.getResourceName(fo, '/', false);
   9.294 +                            String testResName = getTestResName(baseResName, fo.getExt());
   9.295 +                            assert testResName != null;
   9.296 +                            FileObject fileObject = test.getFileObject(testResName);
   9.297 +                if(fileObject != null) {
   9.298 +                                return new LocationResult(fileObject, -1);
   9.299 +                            }
   9.300 +
   9.301 +                            return new LocationResult("File not found"); //NOI18N
   9.302 +                        }
   9.303 +
   9.304 +                        @Override
   9.305 +                        public void findOpposite(FileObject fo, int caretOffset, LocationListener callback) {
   9.306 +                            throw new UnsupportedOperationException("This should not be called on synchronous locators.");
   9.307 +                        }
   9.308 +
   9.309 +                        @Override
   9.310 +                        public FileType getFileType(FileObject fo) {
   9.311 +                if(FileUtil.isParentOf(test, fo)) {
   9.312 +                                return FileType.TEST;
   9.313 +                } else if(FileUtil.isParentOf(src, fo)) {
   9.314 +                                return FileType.TESTED;
   9.315 +                            }
   9.316 +                            return FileType.NEITHER;
   9.317 +                        }
   9.318 +
   9.319 +                        private String getTestResName(String baseResName, String ext) {
   9.320 +                StringBuilder buf
   9.321 +                        = new StringBuilder(baseResName.length() + ext.length() + 10);
   9.322 +                            buf.append(baseResName).append("Test");                         //NOI18N
   9.323 +                            if (ext.length() != 0) {
   9.324 +                                buf.append('.').append(ext);
   9.325 +                            }
   9.326 +                            return buf.toString();
   9.327 +                        }
   9.328 +                    }});
   9.329 +        Main.initializeURLFactory();
   9.330 +        org.netbeans.api.project.ui.OpenProjects.getDefault().getOpenProjects();
   9.331 +        prepareTest();
   9.332 +        org.netbeans.api.project.ui.OpenProjects.getDefault().open(new Project[] {prj = ProjectManager.getDefault().findProject(src.getParent())}, false);
   9.333 +        MimeTypes.setAllMimeTypes(Collections.singleton("text/x-java"));
   9.334 +        sourcePath = ClassPathSupport.createClassPath(src, test);
   9.335 +        GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {sourcePath});
   9.336 +        RepositoryUpdater.getDefault().start(true);
   9.337 +        super.setUp();
   9.338 +        FileUtil.createData(FileUtil.getConfigRoot(), "Templates/Classes/Empty.java");
   9.339 +        System.setProperty("org.netbeans.modules.parsing.impl.Source.excludedTasks", ".*");
   9.340 +    }
   9.341 +
   9.342 +    @Override
   9.343 +    protected void tearDown() throws Exception {
   9.344 +        super.tearDown();
   9.345 +        GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, new ClassPath[] {sourcePath});
   9.346 +        org.netbeans.api.project.ui.OpenProjects.getDefault().close(new Project[] {prj});
   9.347 +        prj = null;
   9.348 +    }
   9.349 +
   9.350 +    private void prepareTest() throws Exception {
   9.351 +        FileObject workdir = SourceUtilsTestUtil.makeScratchDir(this);
   9.352 +
   9.353 +        FileObject projectFolder = FileUtil.createFolder(workdir, "testProject");
   9.354 +        src = FileUtil.createFolder(projectFolder, "src");
   9.355 +        test = FileUtil.createFolder(projectFolder, "test");
   9.356 +
   9.357 +        FileObject cache = FileUtil.createFolder(workdir, "cache");
   9.358 +
   9.359 +        CacheFolder.setCacheFolder(cache);
   9.360 +    }
   9.361 +
   9.362 +    @ServiceProvider(service=MimeDataProvider.class)
   9.363 +    public static final class MimeDataProviderImpl implements MimeDataProvider {
   9.364 +
   9.365 +        private static final Lookup L = Lookups.singleton(new JavaCustomIndexer.Factory());
   9.366 +
   9.367 +        @Override
   9.368 +        public Lookup getLookup(MimePath mimePath) {
   9.369 +            if ("text/x-java".equals(mimePath.getPath())) {
   9.370 +                return L;
   9.371 +            }
   9.372 +
   9.373 +            return null;
   9.374 +        }
   9.375 +        
   9.376 +    }
   9.377 +
   9.378 +    protected static boolean problemIsFatal(List<Problem> problems) {
   9.379 +        for (Problem problem : problems) {
   9.380 +            Problem next = problem;
   9.381 +            do {
   9.382 +                if (next.isFatal()) {
   9.383 +                    return true;
   9.384 +                }
   9.385 +                next = next.getNext();
   9.386 +            } while (next != null);
   9.387 +        }
   9.388 +        return false;
   9.389 +    }
   9.390 +}
   9.391 \ No newline at end of file
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/java.hints/hintsimpl/test/unit/src/org/netbeans/modules/jackpot30/hintsimpl/duplicates/DuplicateMethodRefactoringPluginTest.java	Sat Jul 06 15:15:21 2013 +0200
    10.3 @@ -0,0 +1,165 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
    10.8 + *
    10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   10.10 + * Other names may be trademarks of their respective owners.
   10.11 + *
   10.12 + * The contents of this file are subject to the terms of either the GNU
   10.13 + * General Public License Version 2 only ("GPL") or the Common
   10.14 + * Development and Distribution License("CDDL") (collectively, the
   10.15 + * "License"). You may not use this file except in compliance with the
   10.16 + * License. You can obtain a copy of the License at
   10.17 + * http://www.netbeans.org/cddl-gplv2.html
   10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.19 + * specific language governing permissions and limitations under the
   10.20 + * License.  When distributing the software, include this License Header
   10.21 + * Notice in each file and include the License file at
   10.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   10.23 + * particular file as subject to the "Classpath" exception as provided
   10.24 + * by Oracle in the GPL Version 2 section of the License file that
   10.25 + * accompanied this code. If applicable, add the following below the
   10.26 + * License Header, with the fields enclosed by brackets [] replaced by
   10.27 + * your own identifying information:
   10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.29 + *
   10.30 + * If you wish your version of this file to be governed by only the CDDL
   10.31 + * or only the GPL Version 2, indicate your decision by adding
   10.32 + * "[Contributor] elects to include this software in this distribution
   10.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.34 + * single choice of license, a recipient has the option to distribute
   10.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.36 + * to extend the choice of license to its licensees as provided above.
   10.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.38 + * Version 2 license, then the option applies only if the new code is
   10.39 + * made subject to such option by the copyright holder.
   10.40 + *
   10.41 + * Contributor(s):
   10.42 + *
   10.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
   10.44 + */
   10.45 +package org.netbeans.modules.jackpot30.hintsimpl.duplicates;
   10.46 +
   10.47 +import java.util.Arrays;
   10.48 +import java.util.LinkedList;
   10.49 +import java.util.List;
   10.50 +import javax.lang.model.element.ExecutableElement;
   10.51 +import javax.lang.model.util.ElementFilter;
   10.52 +import org.netbeans.api.java.source.CompilationController;
   10.53 +import org.netbeans.api.java.source.JavaSource;
   10.54 +import org.netbeans.api.java.source.Task;
   10.55 +import org.netbeans.api.java.source.TreePathHandle;
   10.56 +import org.netbeans.modules.jackpot30.hintsimpl.borrowed.RefactoringTestBase;
   10.57 +import org.netbeans.modules.refactoring.api.Problem;
   10.58 +import org.netbeans.modules.refactoring.api.RefactoringSession;
   10.59 +
   10.60 +/**
   10.61 + *
   10.62 + * @author lahvac
   10.63 + */
   10.64 +public class DuplicateMethodRefactoringPluginTest extends RefactoringTestBase {
   10.65 +
   10.66 +    public DuplicateMethodRefactoringPluginTest(String name) {
   10.67 +        super(name);
   10.68 +    }
   10.69 +
   10.70 +    public void testSimple() throws Exception {
   10.71 +        writeFilesAndWaitForScan(src,
   10.72 +                                 new File("test/Test.java",
   10.73 +                                          "package test;\n" +
   10.74 +                                          "public class Test {\n" +
   10.75 +                                          "    public static void toCall() {\n" +
   10.76 +                                          "        System.err.println(1);\n" +
   10.77 +                                          "    }\n" +
   10.78 +                                          "    public static void test1() {\n" +
   10.79 +                                          "        System.err.println(1);\n" +
   10.80 +                                          "    }\n" +
   10.81 +                                          "    public static void test2() {\n" +
   10.82 +                                          "        System.out.println(1);\n" +
   10.83 +                                          "    }\n" +
   10.84 +                                          "    public static void test3() {\n" +
   10.85 +                                          "        System.err.println(2);\n" +
   10.86 +                                          "    }\n" +
   10.87 +                                          "}\n"));
   10.88 +        performDuplicateMethod("toCall");
   10.89 +        verifyContent(src,
   10.90 +                      new File("test/Test.java",
   10.91 +                               "package test;\n" +
   10.92 +                               "public class Test {\n" +
   10.93 +                               "    public static void toCall() {\n" +
   10.94 +                               "        System.err.println(1);\n" +
   10.95 +                               "    }\n" +
   10.96 +                               "    public static void test1() {\n" +
   10.97 +                               "        toCall();\n" +
   10.98 +                               "    }\n" +
   10.99 +                               "    public static void test2() {\n" +
  10.100 +                               "        System.out.println(1);\n" +
  10.101 +                               "    }\n" +
  10.102 +                               "    public static void test3() {\n" +
  10.103 +                               "        System.err.println(2);\n" +
  10.104 +                               "    }\n" +
  10.105 +                               "}\n"));
  10.106 +    }
  10.107 +
  10.108 +    public void testParams() throws Exception {
  10.109 +        writeFilesAndWaitForScan(src,
  10.110 +                                 new File("test/Test.java",
  10.111 +                                          "package test;\n" +
  10.112 +                                          "public class Test {\n" +
  10.113 +                                          "    public static void toCall(int i) {\n" +
  10.114 +                                          "        System.err.println(i);\n" +
  10.115 +                                          "    }\n" +
  10.116 +                                          "    public static void test1(int j) {\n" +
  10.117 +                                          "        System.err.println(1 + j);\n" +
  10.118 +                                          "    }\n" +
  10.119 +                                          "    public static void test3() {\n" +
  10.120 +                                          "        System.err.println(2);\n" +
  10.121 +                                          "    }\n" +
  10.122 +                                          "}\n"));
  10.123 +        performDuplicateMethod("toCall");
  10.124 +        verifyContent(src,
  10.125 +                      new File("test/Test.java",
  10.126 +                               "package test;\n" +
  10.127 +                               "public class Test {\n" +
  10.128 +                               "    public static void toCall(int i) {\n" +
  10.129 +                               "        System.err.println(i);\n" +
  10.130 +                               "    }\n" +
  10.131 +                               "    public static void test1(int j) {\n" +
  10.132 +                               "        toCall(1 + j);\n" +
  10.133 +                               "    }\n" +
  10.134 +                               "    public static void test3() {\n" +
  10.135 +                               "        toCall(2);\n" +
  10.136 +                               "    }\n" +
  10.137 +                               "}\n"));
  10.138 +    }
  10.139 +
  10.140 +    private void performDuplicateMethod(final String methodName, Problem... expectedProblems) throws Exception {
  10.141 +        final DuplicateMethodRefactoring[] r = new DuplicateMethodRefactoring[1];
  10.142 +
  10.143 +        JavaSource.forFileObject(src.getFileObject("test/Test.java")).runUserActionTask(new Task<CompilationController>() {
  10.144 +            @Override public void run(CompilationController javac) throws Exception {
  10.145 +                javac.toPhase(JavaSource.Phase.RESOLVED);
  10.146 +
  10.147 +                for (ExecutableElement method : ElementFilter.methodsIn(javac.getTopLevelElements().get(0).getEnclosedElements())) {
  10.148 +                    if (method.getSimpleName().contentEquals(methodName)) {
  10.149 +                        r[0] = new DuplicateMethodRefactoring(TreePathHandle.create(javac.getTrees().getPath(method), javac));
  10.150 +                    }
  10.151 +                }
  10.152 +            }
  10.153 +        }, true);
  10.154 +
  10.155 +        RefactoringSession rs = RefactoringSession.create("Session");
  10.156 +        List<Problem> problems = new LinkedList<Problem>();
  10.157 +
  10.158 +        addAllProblems(problems, r[0].preCheck());
  10.159 +        if (!problemIsFatal(problems)) {
  10.160 +            addAllProblems(problems, r[0].prepare(rs));
  10.161 +        }
  10.162 +        if (!problemIsFatal(problems)) {
  10.163 +            addAllProblems(problems, rs.doRefactoring(true));
  10.164 +        }
  10.165 +
  10.166 +        assertProblems(Arrays.asList(expectedProblems), problems);
  10.167 +    }
  10.168 +}