2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.groovy.refactoring.introduce.field
18 import com.intellij.openapi.application.WriteAction
19 import com.intellij.psi.JavaPsiFacade
20 import com.intellij.psi.PsiType
21 import com.intellij.psi.impl.source.PostprocessReformattingAspect
22 import com.intellij.refactoring.introduce.inplace.OccurrencesChooser.ReplaceChoice
23 import org.jetbrains.annotations.NotNull
24 import org.jetbrains.annotations.Nullable
25 import org.jetbrains.plugins.groovy.GroovyFileType
26 import org.jetbrains.plugins.groovy.LightGroovyTestCase
27 import org.jetbrains.plugins.groovy.refactoring.introduce.IntroduceConstantTest
28 import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldSettings.Init
29 import org.jetbrains.plugins.groovy.util.TestUtils
31 import static com.intellij.refactoring.introduce.inplace.OccurrencesChooser.ReplaceChoice.ALL
32 import static org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldSettings.Init.*
35 * @author Maxim.Medvedev
37 class GrIntroduceFieldTest extends LightGroovyTestCase {
39 protected String getBasePath() {
40 "${TestUtils.testDataPath}refactoring/introduceField/"
44 doTest(false, false, false, CUR_METHOD, false, null)
47 void testDeclareFinal() {
48 doTest(false, false, true, FIELD_DECLARATION, false, null)
51 void testCreateConstructor() {
52 doTest(false, false, true, CONSTRUCTOR, true, null)
55 void testManyConstructors() {
56 doTest(false, false, true, CONSTRUCTOR, true, null)
59 void testDontReplaceStaticOccurrences() {
60 doTest(false, false, true, FIELD_DECLARATION, true, null)
63 void testQualifyUsages() {
64 doTest(false, false, true, FIELD_DECLARATION, true, null)
67 void testReplaceLocalVar() {
68 doTest(false, true, false, CUR_METHOD, true, null)
71 void testIntroduceLocalVarByDeclaration() {
72 doTest(false, true, false, FIELD_DECLARATION, true, null)
75 void testReplaceExpressionWithAssignment() {
76 doTest(false, false, false, CUR_METHOD, false, null)
79 void testAnonymousClass() {
80 doTest(false, false, false, CUR_METHOD, false, null)
83 void testAnonymous2() {
84 doTest(false, false, false, CONSTRUCTOR, false, null)
87 void testAnonymous3() {
88 doTest(false, false, false, CONSTRUCTOR, false, null)
91 void testInitializeInCurrentMethod() {
92 doTest(false, true, true, CUR_METHOD, false, null)
95 void testScriptBody() {
96 addGroovyTransformField()
98 print <selection>'abc'</selection>
100 import groovy.transform.Field
104 ''', false, false, false, FIELD_DECLARATION)
107 void testScriptMethod() {
108 addGroovyTransformField()
111 print <selection>'abc'</selection>
114 import groovy.transform.Field
116 @Field final f = 'abc'
121 ''', false, false, true, FIELD_DECLARATION)
124 void testStaticScriptMethod() {
125 addGroovyTransformField()
128 print <selection>'abc'</selection>
131 import groovy.transform.Field
133 @Field static f = 'abc'
138 ''', true, false, false, FIELD_DECLARATION)
141 void testScriptMethod2() {
142 addGroovyTransformField()
145 print <selection>'abc'</selection>
148 import groovy.transform.Field
156 ''', false, false, false, CUR_METHOD)
159 void testSetUp1() throws Exception {
162 class MyTest extends GroovyTestCase {
164 print <selection>'ac'</selection>
168 class MyTest extends GroovyTestCase {
181 false, false, false, SETUP_METHOD)
184 void testSetUp2() throws Exception {
188 class MyTest extends GroovyTestCase {
195 print <selection>'ac'</selection>
199 class MyTest extends GroovyTestCase {
213 false, false, false, SETUP_METHOD)
216 void testStringPart0() {
220 print 'a<selection>b</selection>c'
227 print 'a' + f<caret> + 'c'
229 }''', false, false, false, FIELD_DECLARATION, false, null)
232 void testStringPart1() {
236 print 'a<selection>b</selection>c'
244 print 'a' + f<caret> + 'c'
246 }''', false, false, false, CUR_METHOD, false, null)
249 void testStringPart2() {
254 print 'a<selection>b</selection>c'
263 print 'a' + this.f<caret> + 'c'
265 }''', false, false, false, CUR_METHOD, false, null)
268 void testGStringInjection() {
270 class GroovyLightProjectDescriptor {
271 public void configureModule() {
272 print ("$<selection>mockGroovy2_1LibraryName</selection>!/");
275 def getMockGroovy2_1LibraryName() {''}
278 class GroovyLightProjectDescriptor {
281 public void configureModule() {
282 f = mockGroovy2_1LibraryName
286 def getMockGroovy2_1LibraryName() {''}
288 ''', false, false, false, CUR_METHOD)
291 void testGStringInjection2() {
293 class GroovyLightProjectDescriptor {
294 public void configureModule() {
295 print ("$<selection>mockGroovy2_1LibraryName</selection>.bytes!/");
298 def getMockGroovy2_1LibraryName() {''}
301 class GroovyLightProjectDescriptor {
304 public void configureModule() {
305 f = mockGroovy2_1LibraryName
306 print ("${f.bytes}!/");
309 def getMockGroovy2_1LibraryName() {''}
311 ''', false, false, false, CUR_METHOD)
314 void 'test GString closure injection and initialize in current method'() {
316 class GroovyLightProjectDescriptor {
317 public void configureModule() {
318 print ("${<selection>mockGroovy2_1LibraryName</selection>}!/");
321 def getMockGroovy2_1LibraryName() {''}
324 class GroovyLightProjectDescriptor {
327 public void configureModule() {
328 f = mockGroovy2_1LibraryName
332 def getMockGroovy2_1LibraryName() {''}
334 ''', false, false, false, CUR_METHOD
337 void testInitializeInMethodInThenBranch() {
341 if (abc) print <selection>2</selection>
355 ''', false, false, false, CUR_METHOD, false, null)
362 def <selection>a = 5</selection>
372 }''', false, true, false, FIELD_DECLARATION, true, null)
375 void 'test replace top level expression within constructor and initialize in current method'() {
396 ''', false, false, false, CUR_METHOD
399 void 'test replace top level expression within constructor and initialize field'() {
420 ''', false, false, false, FIELD_DECLARATION
423 void 'test replace top level expression within constructor and initialize in constructor'() {
445 ''', false, false, false, CONSTRUCTOR
448 void 'test replace non top level expression within constructor and initialize in current method'() {
452 <selection>new String()</selection>.empty
470 ''', false, false, false, CUR_METHOD
473 void 'test replace non top level expression within constructor and initialize field'() {
477 <selection>new String()</selection>.empty
494 ''', false, false, false, FIELD_DECLARATION
497 void 'test replace non top level expression within constructor and initialize in constructor'() {
501 <selection>new String()</selection>.empty
520 ''', false, false, false, CONSTRUCTOR
523 void 'test replace string injection and initialize in constructor'() {
527 "${<selection>new String()</selection>}"
544 ''', false, false, false, CONSTRUCTOR
547 void 'test introduce field in script with invalid class name'() {
548 myFixture.configureByText "abcd-efgh.groovy", '''\
551 println(<selection>aaa + bbb</selection>)
553 performRefactoring(null, false, false, false, CUR_METHOD, false)
554 myFixture.checkResult '''\
555 import groovy.transform.Field
565 void 'test cannot initialize in current method when introducing from field initializer'() {
566 doTestInitInTarget '''
568 def object = <selection>new Object()</selection>
570 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION)
572 doTestInitInTarget '''
574 def object = <selection>new Object()</selection>
575 def object2 = new Object()
577 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION)
579 doTestInitInTarget '''
581 def object = <selection>new Object()</selection>
582 def object2 = new Object()
584 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION), ReplaceChoice.NO
587 void 'test can not initialize in current method with some occurence outside'() {
588 doTestInitInTarget '''
590 def field = new Object()
592 def a = <selection>new Object()</selection>
595 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION)
598 void 'test can initialize in current method from within method'() {
599 doTestInitInTarget '''
602 def a = <selection>new Object()</selection>
605 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION, CUR_METHOD)
607 doTestInitInTarget '''
609 def field = new Object()
611 def a = <selection>new Object()</selection>
614 ''', EnumSet.of(CONSTRUCTOR, FIELD_DECLARATION, CUR_METHOD), ReplaceChoice.NO
617 void 'test can initialize script field in current method only'() {
618 doTestInitInTarget '''
621 println(<selection>a + b</selection>)
622 ''', EnumSet.of(CUR_METHOD)
624 doTestInitInTarget '''
627 println(<selection>a + b</selection>)
628 ''', EnumSet.of(CUR_METHOD), ReplaceChoice.NO
630 doTestInitInTarget '''
634 println(<selection>a + b</selection>)
635 ''', EnumSet.of(CUR_METHOD)
637 doTestInitInTarget '''
641 println(<selection>a + b</selection>)
642 ''', EnumSet.of(CUR_METHOD), ReplaceChoice.NO
645 void 'test introduce field from this'() {
662 ''', false, false, false, FIELD_DECLARATION
665 private void doTest(final boolean isStatic,
666 final boolean removeLocal,
667 final boolean declareFinal,
668 @NotNull final GrIntroduceFieldSettings.Init initIn,
669 final boolean replaceAll = false,
670 @Nullable final String selectedType = null) {
671 myFixture.configureByFile("${getTestName(false)}.groovy")
672 performRefactoring(selectedType, isStatic, removeLocal, declareFinal, initIn, replaceAll)
673 myFixture.checkResultByFile("${getTestName(false)}_after.groovy")
676 private void doTest(@NotNull final String textBefore,
677 @NotNull String textAfter,
678 final boolean isStatic,
679 final boolean removeLocal,
680 final boolean declareFinal,
681 @NotNull final GrIntroduceFieldSettings.Init initIn,
682 final boolean replaceAll = false,
683 @Nullable final String selectedType = null) {
684 myFixture.configureByText("_.groovy", textBefore)
685 performRefactoring(selectedType, isStatic, removeLocal, declareFinal, initIn, replaceAll)
686 myFixture.checkResult(textAfter)
689 private void performRefactoring(String selectedType, boolean isStatic, boolean removeLocal, boolean declareFinal, GrIntroduceFieldSettings.Init initIn, boolean replaceAll) {
690 final PsiType type = selectedType == null ? null : JavaPsiFacade.getElementFactory(project).createTypeFromText(selectedType, myFixture.file)
692 final IntroduceFieldTestHandler handler = new IntroduceFieldTestHandler(isStatic, removeLocal, declareFinal, initIn, replaceAll, type)
693 handler.invoke(project, myFixture.editor, myFixture.file, null)
694 PostprocessReformattingAspect.getInstance(project).doPostponedFormatting()
698 private void doTestInitInTarget(String text, EnumSet<Init> expected = EnumSet.noneOf(Init), ReplaceChoice replaceChoice = ALL) {
699 myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, text)
700 def handler = new GrIntroduceFieldHandler()
702 def expression = IntroduceConstantTest.findExpression(myFixture)
703 def variable = IntroduceConstantTest.findVariable(myFixture)
704 def stringPart = IntroduceConstantTest.findStringPart(myFixture)
705 def scopes = handler.findPossibleScopes(expression, variable, stringPart, editor)
706 assert scopes.length == 1
707 def scope = scopes[0]
709 def context = handler.getContext(getProject(), myFixture.editor, expression, variable, stringPart, scope)
710 def initPlaces = GrInplaceFieldIntroducer.getApplicableInitPlaces(context, replaceChoice == ALL)
711 assert initPlaces == expected