| /******************************************************************************* |
| * Copyright (c) 2000, 2014 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Nikolay Metchev <nikolaymetchev@gmail.com> - [introduce indirection] ClassCastException when introducing indirection on method in generic class - https://bugs.eclipse.org/395231 |
| * Nikolay Metchev <nikolaymetchev@gmail.com> - [introduce indirection] Adds unneccessary import when inner class is used as parameter in surrounding class - https://bugs.eclipse.org/395228 |
| *******************************************************************************/ |
| package org.eclipse.jdt.ui.tests.refactoring; |
| |
| import java.io.IOException; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| import org.eclipse.jdt.testplugin.JavaProjectHelper; |
| |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.ISourceRange; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceIndirectionRefactoring; |
| |
| import org.eclipse.jdt.ui.tests.refactoring.infra.TextRangeUtil; |
| |
| public class IntroduceIndirectionTests extends RefactoringTest { |
| |
| private static final Class<IntroduceIndirectionTests> clazz= IntroduceIndirectionTests.class; |
| private static final String REFACTORING_PATH= "IntroduceIndirection/"; |
| |
| public IntroduceIndirectionTests(String name) { |
| super(name); |
| } |
| |
| @Override |
| protected String getRefactoringPath() { |
| return REFACTORING_PATH; |
| } |
| |
| public static Test suite() { |
| return new RefactoringTestSetup(new TestSuite(clazz)); |
| } |
| |
| public static Test setUpTest(Test test) { |
| return new RefactoringTestSetup(test); |
| } |
| |
| /** |
| * |
| * Invokes the introduce indirection ref. Some pointers: |
| * |
| * @param topLevelName This is an array of fully qualified top level(!) type names with exactly one package prefix (e.g. "p.Foo"). |
| * Simple names must correspond to .java files. |
| * The first cu will be used for the invocation of the refactoring (see positioning) |
| * @param newName name of indirection method |
| * @param qTypeName qualified type name of the type for the indirection method. Should be one of the cus in topLevelName. |
| * @param startLine starting line of selection in topLevelName[0] |
| * @param startColumn starting column of selection in topLevelName[0] |
| * @param endLine ending line of selection in topLevelName[0] |
| * @param endColumn ending column of selection in topLevelName[0] |
| * @param updateReferences true if references should be updated |
| * @param shouldWarn if true, warnings will be expected in the result |
| * @param shouldError if true, errors will be expected in the result |
| * @param shouldFail if true, fatal errors will be expected in the result |
| * @throws Exception |
| * @throws JavaModelException |
| * @throws CoreException |
| * @throws IOException |
| */ |
| private void helper(String[] topLevelName, String newName, String qTypeName, int startLine, int startColumn, int endLine, int endColumn, boolean updateReferences, boolean shouldWarn, |
| boolean shouldError, boolean shouldFail) throws Exception, JavaModelException, CoreException, IOException { |
| ICompilationUnit[] cu= new ICompilationUnit[topLevelName.length]; |
| for (int i= 0; i < topLevelName.length; i++) { |
| String packName= topLevelName[i].substring(0, topLevelName[i].indexOf('.')); |
| String className= topLevelName[i].substring(topLevelName[i].indexOf('.') + 1); |
| IPackageFragment cPackage= getRoot().createPackageFragment(packName, true, null); |
| cu[i]= createCUfromTestFile(cPackage, className); |
| } |
| |
| ISourceRange selection= TextRangeUtil.getSelection(cu[0], startLine, startColumn, endLine, endColumn); |
| try { |
| IntroduceIndirectionRefactoring ref= new IntroduceIndirectionRefactoring(cu[0], selection.getOffset(), selection.getLength()); |
| ref.setEnableUpdateReferences(updateReferences); |
| if (qTypeName != null) |
| ref.setIntermediaryTypeName(qTypeName); |
| if (newName != null) |
| ref.setIntermediaryMethodName(newName); |
| |
| boolean failed= false; |
| RefactoringStatus status= performRefactoringWithStatus(ref); |
| if (status.hasFatalError()) { |
| assertTrue("Failed but shouldn't: " + status.getMessageMatchingSeverity(RefactoringStatus.FATAL), shouldFail); |
| failed= true; |
| } else |
| assertFalse("Didn't fail although expected", shouldFail); |
| |
| if (!failed) { |
| |
| if (status.hasError()) |
| assertTrue("Had errors but shouldn't: " + status.getMessageMatchingSeverity(RefactoringStatus.ERROR), shouldError); |
| else |
| assertFalse("No error although expected", shouldError); |
| |
| if (status.hasWarning()) |
| assertTrue("Had warnings but shouldn't: " + status.getMessageMatchingSeverity(RefactoringStatus.WARNING), shouldWarn); |
| else |
| assertFalse("No warning although expected", shouldWarn); |
| |
| for (int i= 0; i < topLevelName.length; i++) { |
| String className= topLevelName[i].substring(topLevelName[i].indexOf('.') + 1); |
| assertEqualLines("invalid output.", getFileContents(getOutputTestFileName(className)), cu[i].getSource()); |
| } |
| } |
| } finally { |
| for (int i= 0; i < topLevelName.length; i++) |
| JavaProjectHelper.delete(cu[i]); |
| } |
| } |
| |
| protected void helperPass(String[] topLevelName, String newName, String target, int startLine, int startColumn, int endLine, int endColumn) throws Exception { |
| helper(topLevelName, newName, target, startLine, startColumn, endLine, endColumn, true, false, false, false); |
| } |
| |
| protected void helperWarn(String[] topLevelName, String newName, String target, int startLine, int startColumn, int endLine, int endColumn) throws Exception { |
| helper(topLevelName, newName, target, startLine, startColumn, endLine, endColumn, true, true, false, false); |
| } |
| |
| protected void helperErr(String[] topLevelName, String newName, String target, int startLine, int startColumn, int endLine, int endColumn) throws Exception { |
| helper(topLevelName, newName, target, startLine, startColumn, endLine, endColumn, true, true, true, false); |
| } |
| |
| protected void helperFail(String[] topLevelName, String newName, String target, int startLine, int startColumn, int endLine, int endColumn) throws Exception { |
| helper(topLevelName, newName, target, startLine, startColumn, endLine, endColumn, true, true, true, true); |
| } |
| |
| public void test01() throws Exception { |
| // very simple test |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 7, 10, 7, 13); |
| } |
| |
| public void test02() throws Exception { |
| // warning if a super call is found |
| helperWarn(new String[] { "p.A", "p.B" }, "bar", "p.A", 8, 15, 8, 18); |
| } |
| |
| public void test03() throws Exception { |
| // add imports to target |
| helperPass(new String[] { "p.Foo", "p.Bar" }, "bar", "p.Bar", 8, 17, 8, 20); |
| } |
| |
| public void test04() throws Exception { |
| // this qualification with outer type, method declaration is in outer type. |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 10, 17, 10, 20); |
| } |
| |
| public void test05() throws Exception { |
| // this qualification with outer type, method declaration is in |
| // super type of outer type |
| helperPass(new String[] { "p.Foo", "p.Bar" }, "bar", "p.Foo", 12, 17, 12, 27); |
| } |
| |
| public void test06() throws Exception { |
| // this qualification with the current type, method declaration is |
| // in super type of current type |
| helperPass(new String[] { "p.Foo", "p.Bar" }, "bar", "p.Foo", 10, 13, 10, 23); |
| } |
| |
| public void test07() throws Exception { |
| // test qualification with anonymous type (=> warning, don't update) |
| helperWarn(new String[] { "p.E1" }, "bar", "p.E1", 30, 16, 30, 19); |
| } |
| |
| public void test08() throws Exception { |
| // open hierarchy failure |
| helperFail(new String[] { "p.SeaLevel", "p.Eiger", "p.Moench" }, "bar", "p.SeaLevel", 13, 11, 13, 14); |
| } |
| |
| public void test09() throws Exception { |
| // create static intermediary |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 7, 17, 7, 20); |
| } |
| |
| public void test10() throws Exception { |
| // error, method already exists |
| helperErr(new String[] { "p.Foo", "p.Bar" }, "foo", "p.Foo", 10, 19, 10, 22); |
| } |
| |
| public void test11() throws Exception { |
| // test name clash with existing argument |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 12, 9, 12, 12); |
| } |
| |
| public void test12() throws Exception { |
| // cannot put the intermediary into an inner non-static type |
| helperFail(new String[] { "p.Foo" }, "bar", "p.Foo.Inner", 9, 10, 9, 13); |
| } |
| |
| public void test13() throws Exception { |
| // create intermediary inside nested static types |
| helperPass(new String[] { "p.Foo", "p.Bar" }, "bar", "p.Foo.Inner.MoreInner", 13, 10, 13, 13); |
| } |
| |
| public void test14() throws Exception { |
| // raise visibility of target so intermediary sees it. |
| helperWarn(new String[] { "p0.Foo", "p1.Bar" }, "bar", "p1.Bar", 8, 18, 8, 23); |
| } |
| |
| public void test15() throws Exception { |
| // raise visibility of intermediary type so |
| // existing references see it |
| helperWarn(new String[] { "p0.Foo", "p0.Bar", "p1.Third" }, "bar", "p0.Bar", 8, 17, 8, 20); |
| } |
| |
| public void test16() throws Exception { |
| // test non-reference mode with a method invocation selected |
| helper(new String[] { "p.Bar", "p.Foo" }, "bar", "p.Bar", 6, 19, 6, 22, false, false, false, false); |
| } |
| |
| public void test17() throws Exception { |
| // generic target method |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 16, 9, 16, 12); |
| } |
| |
| public void test18() throws Exception { |
| // simple test with generic type, unused |
| try { |
| getRoot().getJavaProject().setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_METHOD_TYPE_PARAMETERS, JavaCore.ENABLED); |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 19, 11, 19, 14); |
| } finally { |
| getRoot().getJavaProject().setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_METHOD_TYPE_PARAMETERS, JavaCore.DISABLED); |
| } |
| |
| } |
| |
| public void test19() throws Exception { |
| // simple test with generic type, used |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 19, 11, 19, 14); |
| } |
| |
| public void test20() throws Exception { |
| // complex case with generic type parameters and method parameters used |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 11, 11, 11, 17); |
| } |
| |
| public void test21() throws Exception { |
| // no call updating if type arguments are used |
| helperWarn(new String[] { "p.Foo" }, "bar", "p.Foo", 9, 22, 9, 26); |
| } |
| |
| public void test22() throws Exception { |
| // method using type parameters from enclosing types as well |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 16, 24, 16, 27); |
| } |
| |
| public void test23() throws Exception { |
| // warn about incorrect qualified static calls and don't update them. |
| helperWarn(new String[] { "p.Foo" }, "bar", "p.Foo", 11, 25, 11, 28); |
| } |
| |
| public void test24() throws Exception { |
| // assure common super type is used even if the hierarchy branches downwards |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 11, 11, 11, 14); |
| } |
| |
| public void test25() throws Exception { |
| // increase visibility of overridden methods as well |
| helperWarn(new String[] { "p0.Foo", "p0.SubFoo", "p1.Bar" }, "bar", "p1.Bar", 8, 20, 8, 23); |
| } |
| |
| public void test26() throws Exception { |
| // ensure exceptions are copied |
| helperPass(new String[] { "p.Foo" }, "bar", "p.Foo", 7, 24, 7, 27); |
| } |
| |
| public void test27() throws Exception { |
| // complex visibility adjustment case |
| // target method is not inside target type, and is overridden |
| // target type must be increased, and all overridden methods must be increased. |
| helperWarn(new String[] { "p0.Foo", "p0.RealFoo", "p0.NonOriginalSubFoo", "p0.VerySuperFoo", "p1.Bar" }, "bar", "p1.Bar", 7, 13, 7, 16); |
| } |
| |
| public void test28() throws Exception { |
| // the template for the intermediary must be the method inside the real |
| // target (for parameter names and exceptions) |
| helperWarn(new String[] { "p.Foo", "p.Bar",}, "bar", "p.Foo", 10, 9, 10, 12); |
| } |
| |
| public void test29() throws Exception { |
| // don't adjust visibility twice |
| helperWarn(new String[] { "p0.Test", "p1.Other" }, "bar", "p1.Other", 5, 35, 5, 44); |
| } |
| |
| public void test30() throws Exception { |
| // multiple generic instantiations |
| helperPass(new String[] { "p.MultiGenerics" }, "bar", "p.MultiGenerics", 7, 16, 7, 26); |
| } |
| |
| public void test31() throws Exception { |
| // test for bug 127665 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 13, 20, 13, 23); |
| } |
| |
| public void test32() throws Exception { |
| // test for bug 395231 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 4, 10, 4, 13); |
| } |
| |
| public void test33() throws Exception { |
| // test for bug 395231 |
| helper(new String[] { "p.Test" }, "foo", "p.Test0", 8, 9, 8, 20, false, false, false, false); |
| } |
| |
| public void test34() throws Exception { |
| // test for bug 395231 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 6, 9, 6, 13); |
| } |
| |
| public void test35() throws Exception { |
| // test for bug 395231 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 6, 9, 6, 13); |
| } |
| |
| public void test36() throws Exception { |
| // test for bug 395231 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 6, 9, 6, 13); |
| } |
| |
| public void test37() throws Exception { |
| // test for bug 127665 |
| helperPass(new String[] { "p.Test" }, "foo", "p.Test0", 4, 10, 4, 13); |
| } |
| |
| public void test38() throws Exception { |
| // test for bug 127665 |
| helperPass(new String[] { "p.Test" }, "foo2", "p.Test0", 5, 21, 5, 24); |
| } |
| } |