diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint.java new file mode 100644 index 000000000000..b03a650084ad --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint.java @@ -0,0 +1,13 @@ +public class Test { + public int test(int x) { + int i; + for (i = 0; i <= x; i++) { + if (i == 42) { + break; + } else if (i == 17) { + break; + } + } + return i; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint_after.java new file mode 100644 index 000000000000..5c9ec1e33e0a --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConditionalExitPoint_after.java @@ -0,0 +1,18 @@ +public class Test { + public int test(int x) { + int i; + for (i = 0; i <= x; i++) { + if (extracted(i)) break; + } + return i; + } + + private boolean extracted(int i) { + if (i == 42) { + return true; + } else if (i == 17) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictRename.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictRename.java new file mode 100644 index 000000000000..c7c8f269f95c --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictRename.java @@ -0,0 +1,9 @@ +class Test { + void test() { + System.out.println(); + } + + void conflict(){ + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered.java new file mode 100644 index 000000000000..1c238fccf273 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered.java @@ -0,0 +1,10 @@ +class Test { + void test() { + int x = 42; + System.out.println(x); + } + + int getX(){ + return 42; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered_after.java new file mode 100644 index 000000000000..47dd53292347 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ConflictedNamesFiltered_after.java @@ -0,0 +1,15 @@ +class Test { + void test() { + int x = getAnInt(); + System.out.println(x); + } + + private int getAnInt() { + int x = 42; + return x; + } + + int getX(){ + return 42; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates.java new file mode 100644 index 000000000000..ee9fb135eaaa --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates.java @@ -0,0 +1,6 @@ +class Test { + void test() { + System.out.println(); + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates_after.java new file mode 100644 index 000000000000..d7e510fd771d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ExactDuplicates_after.java @@ -0,0 +1,10 @@ +class Test { + void test() { + extracted(); + extracted(); + } + + private void extracted() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault.java new file mode 100644 index 000000000000..16031b6278b9 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault.java @@ -0,0 +1,14 @@ +class Test { + void test() { + int x = 42; + System.out.println(x); + } + + int getX(){ + return 0; + } + + int getAnInt(){ + return 0; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault_after.java new file mode 100644 index 000000000000..a77288b0eb08 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/GeneratedDefault_after.java @@ -0,0 +1,19 @@ +class Test { + void test() { + int x = getX1(); + System.out.println(x); + } + + private int getX1() { + int x = 42; + return x; + } + + int getX(){ + return 0; + } + + int getAnInt(){ + return 0; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/InvalidRename.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/InvalidRename.java new file mode 100644 index 000000000000..8fa5c0df2bb7 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/InvalidRename.java @@ -0,0 +1,5 @@ +class Test { + void test() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping.java new file mode 100644 index 000000000000..094bbbb2f502 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping.java @@ -0,0 +1,16 @@ +class Test { + void test1(){ + System.out.println("string"); + System.out.println("string"); + } + + void test2(){ + System.out.println("message"); + System.out.println("message"); + } + + void test3(){ + System.out.println("first"); + System.out.println("second"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping_after.java new file mode 100644 index 000000000000..7621d35dfc15 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ParameterGrouping_after.java @@ -0,0 +1,18 @@ +class Test { + void test1(){ + extracted("string", "string"); + } + + private void extracted(String string, String string2) { + System.out.println(string); + System.out.println(string2); + } + + void test2(){ + extracted("message", "message"); + } + + void test3(){ + extracted("first", "second"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RefactoringListener.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RefactoringListener.java new file mode 100644 index 000000000000..8fa5c0df2bb7 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RefactoringListener.java @@ -0,0 +1,5 @@ +class Test { + void test() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate.java new file mode 100644 index 000000000000..ee9fb135eaaa --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate.java @@ -0,0 +1,6 @@ +class Test { + void test() { + System.out.println(); + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate_after.java new file mode 100644 index 000000000000..0810a342f3b3 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedExactDuplicate_after.java @@ -0,0 +1,10 @@ +class Test { + void test() { + renamed(); + renamed(); + } + + private void renamed() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate.java new file mode 100644 index 000000000000..a27c4d3e59c6 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate.java @@ -0,0 +1,6 @@ +class Test { + void test(){ + int avgA = 10 + 20 / 2; + int avgB = 100 + 200 / 2; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate_after.java new file mode 100644 index 000000000000..d71e6b4681a0 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RenamedParametrizedDuplicate_after.java @@ -0,0 +1,10 @@ +class Test { + void test(){ + int avgA = average(10, 20); + int avgB = average(100, 200); + } + + private int average(int i, int i2) { + return i + i2 / 2; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic1.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic1.java new file mode 100644 index 000000000000..5cdfc8d6e85d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic1.java @@ -0,0 +1,11 @@ +public class Test { + public int test(int x) { + int y = 42; + try { + y = y + x; + y = y / x; + } catch (ArithmeticException e) { + } + return y; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic2.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic2.java new file mode 100644 index 000000000000..41cd3c82292f --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchMayChangeSemantic2.java @@ -0,0 +1,13 @@ +public class Test { + public int test(int x) { + int y = 42; + try { + y = y / x; + foo(); + } catch (ArithmeticException e) { + } + return y; + } + + void foo(){ } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment.java new file mode 100644 index 000000000000..58a69c3baafe --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment.java @@ -0,0 +1,13 @@ +public class Test { + public int test(int x) { + int y = 42; + try { + foo(); + y = y / x; + } catch (ArithmeticException e) { + } + return y; + } + + void foo() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment_after.java new file mode 100644 index 000000000000..9027b8218d8b --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/RuntimeCatchWithLastAssignment_after.java @@ -0,0 +1,18 @@ +public class Test { + public int test(int x) { + int y = 42; + try { + y = getY(x, y); + } catch (ArithmeticException e) { + } + return y; + } + + private int getY(int x, int y) { + foo(); + y = y / x; + return y; + } + + void foo() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences.java new file mode 100644 index 000000000000..147fe461006d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences.java @@ -0,0 +1,8 @@ +import java.util.ArrayList; + +class Test { + void test() { + var s = new ArrayList<>().stream(); + System.out.println(s); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences_after.java new file mode 100644 index 000000000000..a6ab74c55681 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ShortenClassReferences_after.java @@ -0,0 +1,13 @@ +import java.util.ArrayList; +import java.util.stream.Stream; + +class Test { + void test() { + var s = new ArrayList<>().stream(); + extracted(s); + } + + private void extracted(Stream s) { + System.out.println(s); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch.java new file mode 100644 index 000000000000..82dedd992e7d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch.java @@ -0,0 +1,16 @@ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +public class Test { + public int test(int x) { + int y = 42; + try { + new Scanner(new File("file.txt")); + y = y + x; + y = y / x; + } catch (FileNotFoundException e) { + } + return y; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch_after.java new file mode 100644 index 000000000000..ba73d4862733 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/SpecificCatch_after.java @@ -0,0 +1,21 @@ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +public class Test { + public int test(int x) { + int y = 42; + try { + y = getY(x, y); + } catch (FileNotFoundException e) { + } + return y; + } + + private int getY(int x, int y) throws FileNotFoundException { + new Scanner(new File("file.txt")); + y = y + x; + y = y / x; + return y; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement.java new file mode 100644 index 000000000000..8fa5c0df2bb7 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement.java @@ -0,0 +1,5 @@ +class Test { + void test() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement_after.java new file mode 100644 index 000000000000..0ce31a11a430 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/Statement_after.java @@ -0,0 +1,9 @@ +class Test { + void test() { + extracted(); + } + + private void extracted() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced.java new file mode 100644 index 000000000000..8adb77540ac5 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced.java @@ -0,0 +1,6 @@ +class Test { + static void test() { + int x = 42; + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced_after.java new file mode 100644 index 000000000000..d6d7f438fbf8 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/StaticMustBePlaced_after.java @@ -0,0 +1,11 @@ +class Test { + static void test() { + int x = getX(); + System.out.println(x); + } + + private static int getX() { + int x = 42; + return x; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates.java new file mode 100644 index 000000000000..d6b77c803526 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates.java @@ -0,0 +1,16 @@ +class Test { + void test1(){ + System.out.println("Hello!"); + System.out.println("user"); + } + + void test2(String name){ + System.out.println("Hello!"); + System.out.println(name); + } + + void test3(){ + System.out.println("Good morning!"); + System.out.println("user"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates_after.java new file mode 100644 index 000000000000..721e96614cd9 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ThreeDuplicates_after.java @@ -0,0 +1,18 @@ +class Test { + void test1(){ + sayHello("Hello!", "user"); + } + + private void sayHello(String s, String user) { + System.out.println(s); + System.out.println(user); + } + + void test2(String name){ + sayHello("Hello!", name); + } + + void test3(){ + sayHello("Good morning!", "user"); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename.java new file mode 100644 index 000000000000..c7c8f269f95c --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename.java @@ -0,0 +1,9 @@ +class Test { + void test() { + System.out.println(); + } + + void conflict(){ + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename_after.java new file mode 100644 index 000000000000..c17f0e661236 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/ValidRename_after.java @@ -0,0 +1,13 @@ +class Test { + void test() { + valid(); + } + + private void valid() { + System.out.println(); + } + + void conflict(){ + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested.java new file mode 100644 index 000000000000..4fe7d949a10c --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested.java @@ -0,0 +1,6 @@ +class Test { + void test() { + int x = 42; + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested_after.java b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested_after.java new file mode 100644 index 000000000000..7257af399e90 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodAndDuplicatesInplace/VariableGetterSuggested_after.java @@ -0,0 +1,11 @@ +class Test { + void test() { + int x = getX(); + System.out.println(x); + } + + private int getX() { + int x = 42; + return x; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodAndDuplicatesInplaceTest.kt b/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodAndDuplicatesInplaceTest.kt new file mode 100644 index 000000000000..1b54584c769d --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/ExtractMethodAndDuplicatesInplaceTest.kt @@ -0,0 +1,198 @@ +// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.refactoring + +import com.intellij.codeInsight.template.impl.TemplateManagerImpl +import com.intellij.codeInsight.template.impl.TemplateState +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.LanguageLevelProjectExtension +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.TextRange +import com.intellij.pom.java.LanguageLevel +import com.intellij.refactoring.extractMethod.newImpl.MethodExtractor +import com.intellij.refactoring.listeners.RefactoringEventData +import com.intellij.refactoring.listeners.RefactoringEventListener +import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException +import com.intellij.testFramework.LightJavaCodeInsightTestCase +import com.intellij.util.ui.UIUtil +import org.jetbrains.annotations.NonNls + +class ExtractMethodAndDuplicatesInplaceTest: LightJavaCodeInsightTestCase() { + + private val BASE_PATH: @NonNls String = "/refactoring/extractMethodAndDuplicatesInplace" + + fun testStatement(){ + doTest() + } + + fun testConflictedNamesFiltered(){ + doTest() + } + + fun testVariableGetterSuggested(){ + doTest() + } + + fun testExactDuplicates(){ + doTest() + } + + fun testInvalidRename(){ + doTest(changedName = "invalid! name", checkResults = false) + require(getActiveTemplate() != null) + } + + fun testConflictRename(){ + doTest(changedName = "conflict", checkResults = false) + require(getActiveTemplate() != null) + } + + fun testValidRename(){ + doTest(changedName = "valid") + require(getActiveTemplate() == null) + } + + fun testGeneratedDefault(){ + doTest() + } + + fun testRenamedExactDuplicate(){ + doTest(changedName = "renamed") + } + + fun testRenamedParametrizedDuplicate(){ + doTest(changedName = "average") + } + + fun testStaticMustBePlaced(){ + doTest() + } + + fun testShortenClassReferences(){ + withLanguageLevel(project, LanguageLevel.JDK_11) { + doTest() + } + } + + fun testThreeDuplicates(){ + doTest(changedName = "sayHello") + } + + fun testParameterGrouping(){ + doTest() + } + + fun testConditionalExitPoint(){ + doTest() + } + + fun testRuntimeCatchMayChangeSemantic1(){ + assertThrows(RefactoringErrorHintException::class.java, JavaRefactoringBundle.message("extract.method.error.many.exits")) { + doTest() + } + } + + fun testRuntimeCatchMayChangeSemantic2(){ + assertThrows(RefactoringErrorHintException::class.java, JavaRefactoringBundle.message("extract.method.error.many.exits")) { + doTest() + } + } + + fun testRuntimeCatchWithLastAssignment(){ + doTest() + } + + fun testSpecificCatch(){ + doTest() + } + + fun testRefactoringListener(){ + templateTest { + configureByFile("$BASE_PATH/${getTestName(false)}.java") + var startReceived = false + var doneReceived = false + project.messageBus.connect().subscribe(RefactoringEventListener.REFACTORING_EVENT_TOPIC, object : RefactoringEventListener { + override fun refactoringStarted(refactoringId: String, beforeData: RefactoringEventData?) { + startReceived = true + } + override fun refactoringDone(refactoringId: String, afterData: RefactoringEventData?) { + doneReceived = true + } + override fun conflictsDetected(refactoringId: String, conflictsData: RefactoringEventData) = Unit + override fun undoRefactoring(refactoringId: String) = Unit + }) + val template = startRefactoring(editor) + require(startReceived) + finishTemplate(template) + require(doneReceived) + } + } + + private inline fun withLanguageLevel(project: Project, languageLevel: LanguageLevel, body: () -> Unit) { + val extension = LanguageLevelProjectExtension.getInstance(project) + val previousLanguageLevel = extension.languageLevel + try { + extension.languageLevel = languageLevel + body() + } finally { + extension.languageLevel = previousLanguageLevel + } + } + + private fun doTest(checkResults: Boolean = true, changedName: String? = null){ + templateTest { + configureByFile("$BASE_PATH/${getTestName(false)}.java") + val template = startRefactoring(editor) + if (changedName != null) { + renameTemplate(template, changedName) + } + finishTemplate(template) + if (checkResults) { + checkResultByFile("$BASE_PATH/${getTestName(false)}_after.java") + } + } + } + + private fun startRefactoring(editor: Editor): TemplateState { + val selection = with(editor.selectionModel) { TextRange(selectionStart, selectionEnd) } + MethodExtractor().doExtract(file, selection) + val templateState = getActiveTemplate() + require(templateState != null) { "Failed to start refactoring" } + return templateState + } + + private fun getActiveTemplate() = TemplateManagerImpl.getTemplateState(editor) + + private fun finishTemplate(templateState: TemplateState){ + try { + templateState.gotoEnd(false) + UIUtil.dispatchAllInvocationEvents() + } catch (ignore: RefactoringErrorHintException) { + } + } + + private fun renameTemplate(templateState: TemplateState, name: String) { + WriteCommandAction.runWriteCommandAction(project) { + val range = templateState.currentVariableRange!! + editor.document.replaceString(range.startOffset, range.endOffset, name) + } + } + + private inline fun templateTest(test: () -> Unit) { + val disposable = Disposer.newDisposable() + try { + TemplateManagerImpl.setTemplateTesting(disposable) + test() + } + finally { + Disposer.dispose(disposable) + } + } + + override fun tearDown() { + val template = getActiveTemplate() + if (template != null) Disposer.dispose(template) + super.tearDown() + } +} \ No newline at end of file