blob: 2f6b96a13ffaa9bdcfc41dfaaac92b426e831a93 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.refactoring.introduceParameter
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.refactoring.IntroduceParameterRefactoring
import gnu.trove.TIntArrayList
import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureFromClosureProcessor
import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureFromMethodProcessor
import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureHelperImpl
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterHandler
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.IntroduceParameterInfo
import org.jetbrains.plugins.groovy.util.TestUtils
/**
* @author Max Medvedev
*/
public abstract class ExtractClosureTest extends LightGroovyTestCase {
@Override
protected String getBasePath() {
return "${TestUtils.testDataPath}groovy/refactoring/extractMethod/";
}
protected void doTest(String before, String after, List<Integer> toRemove = [], List<Integer> notToUseAsParams = [], boolean forceReturn = true) {
myFixture.configureByText '______________a____________________.groovy', before
def handler = new GrIntroduceParameterHandler() {
@Override
protected void showDialog(IntroduceParameterInfo info) {
GrIntroduceParameterSettings helper = new ExtractClosureHelperImpl(info, "closure", false,
new TIntArrayList(toRemove as int[]), false,
IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE,
forceReturn, false, false)
for (p in notToUseAsParams) {
helper.parameterInfos[p].passAsParameter = false
}
if (helper.toReplaceIn instanceof GrMethod) {
new ExtractClosureFromMethodProcessor(helper).run()
}
else {
new ExtractClosureFromClosureProcessor(helper).run()
}
}
}
WriteCommandAction.runWriteCommandAction project, {
handler.invoke myFixture.project, myFixture.editor, myFixture.file, null
doPostponedFormatting(myFixture.project)
}
myFixture.checkResult after
}
static class MethodTest extends ExtractClosureTest {
void testSimple() {
doTest('''
def foo(String s) {
s+=2
<selection>print s</selection>
}
foo('a')
''', '''
def foo(String s, Closure closure) {
s+=2
closure(s)
}
foo('a') { String s -> print s }
''', [], [], false)
}
void testRemoveUnused() {
doTest('''
class X {
def foo(String s) {
<selection>print s</selection>
}
}
new X().foo('a')
''', '''
class X {
def foo(Closure closure) {
closure()
}
}
new X().foo { print 'a' }
''', [0], [0], false)
}
void testRemoveUnusedAndGenerateLocal() {
doTest('''
def foo(String s) {
<selection>s+=2
print s</selection>
}
foo('a')
''', '''
def foo(Closure closure) {
closure()
}
foo {
String s = 'a'
s += 2
print s
}
''', [0], [0], true)
}
void testInsertQualifier() {
doTest('''
class X {
def foo(String s) {
<selection>bar()</selection>
}
def bar(){}
}
new X().foo('a')
''', '''
class X {
def foo(Closure closure) {
closure()
}
def bar(){}
}
final X x = new X()
x.foo { x.bar() }
''', [0], [], false)
}
void testLocalVarAsParam() {
doTest('''
def foo(int x, int y) {
int a = 5
<selection>print 45+y+a</selection>
}
foo(2, 3)
''', '''
def foo(Closure closure) {
int a = 5
closure(a)
}
foo { int a -> print 45 + 3 + a }
''', [0, 1], [0], false)
}
void testRPG() {
doTest '''
adventure()
def adventure() {
try {
<selection><caret>killMonsters()
collectLoot()</selection>
} catch (ArrowToKneeException) {
becomeTownGuard()
}
}
''', '''
adventure {
killMonsters()
collectLoot()
}
def adventure(Closure closure) {
try {
closure()<caret>
} catch (ArrowToKneeException) {
becomeTownGuard()
}
}
'''
}
void testExpression() {
doTest('''
adventure()
def adventure() {
try {
def skill = <selection>killMonsters()+collectLoot()</selection>
} catch (ArrowToKneeException e) {
becomeTownGuard()
}
}
class ArrowToKneeException extends Exception{}
def killMonsters(){2}
def collectLoot(){3}
def becomeTownGuard(){}
''', '''
adventure { return killMonsters() + collectLoot() }
def adventure(Closure<Integer> closure) {
try {
def skill = closure()
} catch (ArrowToKneeException e) {
becomeTownGuard()
}
}
class ArrowToKneeException extends Exception{}
def killMonsters(){2}
def collectLoot(){3}
def becomeTownGuard(){}
''')
}
void testDontQualify() {
doTest('''
class Some {
private static int smth = 1
private static void doSmth() {}
void m1() {
<selection><caret>println smth
doSmth()</selection>
}
void m2() {
m1()
}
}
''', '''
class Some {
private static int smth = 1
private static void doSmth() {}
void m1(Closure closure) {
closure()<caret>
}
void m2() {
m1 {
println smth
doSmth()
}
}
}
''')
}
void testAppStatement() {
doTest('''
void foo() {
def s = <selection><caret>"zxcvbn".substring 2 charAt(1)</selection>
}
foo()
''', '''
void foo(Closure<Character> closure) {
def s = closure()<caret>
}
foo { return "zxcvbn".substring(2).charAt(1) }
''')
}
void testStringPart0() {
doTest('''\
def cl() {
print 'a<selection>b</selection>c'
}
cl()
''', '''\
def cl(Closure<String> closure) {
print 'a' + closure()<caret> + 'c'
}
cl { return 'b' }
''')
}
void testNull() {
doTest('''\
def foo() {
print <selection>null</selection>
}
foo()
''', '''\
def foo(Closure closure) {
print closure()
}
foo { return null }
''')
}
}
static class ClosureTest extends ExtractClosureTest {
void testSimple() {
doTest('''
def foo = {String s ->
s+=2
<selection>print s</selection>
}
foo('a')
''', '''
def foo = {String s, Closure closure ->
s+=2
<selection>closure(s)</selection>
}
foo('a') { String s -> print s }
''', [], [], false)
}
void testRemoveUnused() {
doTest('''
class X {
def foo = {String s ->
<selection>print s</selection>
}
}
new X().foo('a')
''', '''
class X {
def foo = {Closure closure ->
<selection>closure()</selection>
}
}
final X x = new X()
x.foo { x.print 'a' }
''', [0], [0], false)
}
void testRemoveUnusedAndGenerateLocal() {
doTest('''
def foo = {String s ->
<selection>s+=2
print s</selection>
}
foo('a')
''', '''
def foo = {Closure closure ->
closure()
}
foo {
String s = 'a'
s += 2
print s
}
''', [0], [0], true)
}
void testInsertQualifier() {
doTest('''
class X {
def foo = {String s ->
<selection>bar()</selection>
}
def bar(){}
}
new X().foo('a')
''', '''
class X {
def foo = {Closure closure ->
<selection>closure()</selection>
}
def bar(){}
}
final X x = new X()
x.foo { x.bar() }
''', [0], [], false)
}
void testLocalVarAsParam() {
doTest('''
def foo = {int x, int y ->
int a = 5
<selection>print 45+y+a</selection>
}
foo(2, 3)
''', '''
def foo = {Closure closure ->
int a = 5
<selection>closure(a)</selection>
}
foo { int a -> print 45 + 3 + a }
''', [0, 1], [0], false)
}
void testRPG() {
doTest '''
def adventure = {
try {
<selection><caret>killMonsters()
collectLoot()</selection>
} catch (ArrowToKneeException) {
becomeTownGuard()
}
}
adventure()
''', '''
def adventure = {Closure closure ->
try {
<caret>closure()
} catch (ArrowToKneeException) {
becomeTownGuard()
}
}
adventure {
killMonsters()
collectLoot()
}
'''
}
void testExpression() {
doTest('''
def adventure = {
try {
def skill = <selection>killMonsters()+collectLoot()</selection>
} catch (ArrowToKneeException e) {
becomeTownGuard()
}
}
adventure()
class ArrowToKneeException extends Exception{}
def killMonsters(){2}
def collectLoot(){3}
def becomeTownGuard(){}
''', '''
def adventure = {Closure<Integer> closure ->
try {
def skill = <selection>closure()</selection>
} catch (ArrowToKneeException e) {
becomeTownGuard()
}
}
adventure { return killMonsters() + collectLoot() }
class ArrowToKneeException extends Exception{}
def killMonsters(){2}
def collectLoot(){3}
def becomeTownGuard(){}
''')
}
void testDontQualify() {
doTest('''
class Some {
private static int smth = 1
private static void doSmth() {}
void m1 = {
<selection><caret>println smth
doSmth()</selection>
}
void m2() {
m1()
}
}
''', '''
class Some {
private static int smth = 1
private static void doSmth() {}
void m1 = {<caret>Closure closure ->
closure()
}
void m2() {
m1 {
println smth
doSmth()
}
}
}
''')
}
void testAppStatement() {
doTest('''
void foo = {
def s = <selection><caret>"zxcvbn".substring 2 charAt(1)</selection>
}
foo()
''', '''
void foo = {Closure<Character> closure ->
def s = <selection><caret>closure()</selection>
}
foo { return "zxcvbn".substring(2).charAt(1) }
''')
}
}
}