mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-08-18 16:17:00 +07:00
1108 lines
33 KiB
Groovy
1108 lines
33 KiB
Groovy
/*
|
|
* Copyright 2000-2017 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 com.intellij.codeInsight.folding
|
|
|
|
import com.intellij.codeInsight.CodeInsightSettings
|
|
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
|
|
import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder
|
|
import com.intellij.find.FindManager
|
|
import com.intellij.openapi.actionSystem.IdeActions
|
|
import com.intellij.openapi.application.ex.PathManagerEx
|
|
import com.intellij.openapi.command.WriteCommandAction
|
|
import com.intellij.openapi.editor.FoldRegion
|
|
import com.intellij.openapi.editor.ex.DocumentEx
|
|
import com.intellij.openapi.editor.ex.EditorEx
|
|
import com.intellij.openapi.editor.ex.FoldingModelEx
|
|
import com.intellij.openapi.editor.impl.FoldingModelImpl
|
|
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
|
import com.intellij.openapi.util.registry.Registry
|
|
import com.intellij.psi.JavaPsiFacade
|
|
import com.intellij.psi.PsiClass
|
|
import com.intellij.psi.PsiMethod
|
|
import com.intellij.psi.search.GlobalSearchScope
|
|
import com.intellij.testFramework.EditorTestUtil
|
|
import com.intellij.testFramework.LightProjectDescriptor
|
|
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
|
import com.intellij.util.DocumentUtil
|
|
import org.intellij.lang.annotations.Language
|
|
import org.jetbrains.annotations.NotNull
|
|
|
|
/**
|
|
* @author Denis Zhdanov
|
|
* @since 17.01.2011
|
|
*/
|
|
@SuppressWarnings("ALL") // too many warnings in injections
|
|
class JavaFoldingTest extends JavaFoldingTestCase {
|
|
@NotNull
|
|
@Override
|
|
protected LightProjectDescriptor getProjectDescriptor() {
|
|
return JAVA_1_7
|
|
}
|
|
|
|
public void testEndOfLineComments() { doTest() }
|
|
|
|
public void testEditingImports() {
|
|
configure """\
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
<caret>
|
|
|
|
class Foo { List a; Map b; }
|
|
"""
|
|
|
|
assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10)
|
|
|
|
myFixture.type 'import '
|
|
myFixture.doHighlighting()
|
|
assert !myFixture.editor.foldingModel.getCollapsedRegionAtOffset(46)
|
|
}
|
|
|
|
public void testJavadocLikeClassHeader() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
/**
|
|
* This is a header to collapse
|
|
*/
|
|
import java.util.*;
|
|
class Foo { List a; Map b; }
|
|
"""
|
|
configure text
|
|
def foldRegion = myFixture.editor.foldingModel.getCollapsedRegionAtOffset(0)
|
|
assert foldRegion
|
|
assertEquals 0, foldRegion.startOffset
|
|
assertEquals text.indexOf("import") - 1, foldRegion.endOffset
|
|
}
|
|
|
|
public void testSubsequentCollapseBlock() {
|
|
def text = """\
|
|
class Test {
|
|
void test(int i) {
|
|
if (i > 1) {
|
|
<caret>i++;
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
myFixture.performEditorAction 'CollapseBlock'
|
|
myFixture.performEditorAction 'CollapseBlock'
|
|
assertEquals(text.indexOf('}', text.indexOf('i++')), myFixture.editor.caretModel.offset)
|
|
}
|
|
|
|
public void testFoldGroup() {
|
|
// Implied by IDEA-79420
|
|
myFoldingSettings.setCollapseLambdas(true)
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
void test() {
|
|
new Runnable() {
|
|
public void run() {
|
|
int i = 1;
|
|
}
|
|
}.run();
|
|
}
|
|
}
|
|
"""
|
|
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
|
assertNotNull closureStartFold
|
|
assertFalse closureStartFold.expanded
|
|
|
|
assertNotNull closureStartFold.group
|
|
def closureFolds = foldingModel.getGroupedRegions(closureStartFold.group)
|
|
assertNotNull closureFolds
|
|
assertEquals(2, closureFolds.size())
|
|
|
|
def closureEndFold = closureFolds.get(1)
|
|
assertFalse closureEndFold.expanded
|
|
|
|
myFixture.editor.caretModel.moveToOffset(closureEndFold.startOffset + 1)
|
|
assertTrue closureStartFold.expanded
|
|
assertTrue closureEndFold.expanded
|
|
|
|
changeFoldRegions { closureStartFold.expanded = false }
|
|
assertTrue closureStartFold.expanded
|
|
assertTrue closureEndFold.expanded
|
|
}
|
|
|
|
public void "test closure folding when an abstract method is not in the direct superclass"() {
|
|
myFoldingSettings.setCollapseLambdas(true)
|
|
@Language("JAVA")
|
|
def text = """\
|
|
public abstract class AroundTemplateMethod<T> {
|
|
public abstract T execute();
|
|
}
|
|
private static abstract class SetupTimer<T> extends AroundTemplateMethod<T> {
|
|
}
|
|
class Test {
|
|
void test() {
|
|
new SetupTimer<Integer>() {
|
|
public Integer execute() {
|
|
return 0;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
"""
|
|
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("<Integer>"))
|
|
assertNotNull closureStartFold
|
|
assertFalse closureStartFold.expanded
|
|
|
|
assertNotNull closureStartFold.group
|
|
def closureFolds = foldingModel.getGroupedRegions(closureStartFold.group)
|
|
assertNotNull closureFolds
|
|
assertEquals(2, closureFolds.size())
|
|
}
|
|
|
|
public void "test builder style setter"() {
|
|
myFoldingSettings.setCollapseAccessors(true)
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Foo {
|
|
private String bar;
|
|
|
|
public Foo setBar(String bar) {
|
|
this.bar = bar;
|
|
return this;
|
|
}
|
|
}
|
|
"""
|
|
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
int indexOfBar = text.indexOf("this.bar")
|
|
def accessorStartFold = foldingModel.getCollapsedRegionAtOffset(indexOfBar)
|
|
assertNotNull accessorStartFold
|
|
assertFalse accessorStartFold.expanded
|
|
}
|
|
|
|
public void "test closure folding doesn't expand when editing inside"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
void test() {
|
|
new Runnable() {
|
|
static final long serialVersionUID = 42L;
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
"""
|
|
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
|
assertNotNull closureStartFold
|
|
assertFalse closureStartFold.expanded
|
|
assert text.substring(closureStartFold.endOffset).startsWith('System') //one line closure
|
|
|
|
myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.text.indexOf("();") + 1)
|
|
myFixture.type('2')
|
|
myFixture.doHighlighting()
|
|
closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
|
assert closureStartFold
|
|
}
|
|
|
|
public void "test closure folding placeholder texts"() {
|
|
myFixture.addClass('interface Runnable2 { void run(); }')
|
|
myFixture.addClass('interface Runnable3 { void run(); }')
|
|
myFixture.addClass('interface Runnable4 { void run(); }')
|
|
myFixture.addClass('abstract class MyAction { public abstract void run(); public void registerVeryCustomShortcutSet() {} }')
|
|
myFixture.addClass('abstract class MyAction2 { public abstract void run(); public void registerVeryCustomShortcutSet() {} }')
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
MyAction2 action2;
|
|
|
|
void test() {
|
|
Runnable r = new Runnable() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
new Runnable2() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
}.run();
|
|
foo(new Runnable3() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
});
|
|
bar(new Runnable4() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
});
|
|
new MyAction() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
}.registerVeryCustomShortcutSet();
|
|
action2 = new MyAction2() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
}
|
|
|
|
void foo(Object o) {}
|
|
void bar(Runnable4 o) {}
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable(")).placeholderText == '() ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable2(")).placeholderText == '(Runnable2) () ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable3(")).placeholderText == '(Runnable3) () ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable4(")).placeholderText == '() ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("MyAction(")).placeholderText == '(MyAction) () ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("MyAction2(")).placeholderText == '(MyAction2) () ' + rightArrow() + ' { '
|
|
}
|
|
|
|
private static String rightArrow() {
|
|
return JavaFoldingBuilder.rightArrow
|
|
}
|
|
|
|
public void "test closure folding after paste"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
<caret>// comment
|
|
void test() {
|
|
Runnable r = new Runnable() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
myFixture.performEditorAction("EditorCut")
|
|
myFixture.performEditorAction("EditorPaste")
|
|
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable(")).placeholderText == '() ' + rightArrow() + ' { '
|
|
}
|
|
|
|
public void "test closure folding when overriding one method of many"() {
|
|
myFixture.addClass('abstract class Runnable { void run() {}; void run2() {} }')
|
|
myFixture.addClass('abstract class Runnable2 { void run() {}; void run2() {} }')
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
void test() {
|
|
Runnable r = new Runnable() {
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
foo(new Runnable2() {
|
|
public void run2() {
|
|
System.out.println();
|
|
}
|
|
});
|
|
}
|
|
|
|
void foo(Object o) {}
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable("))?.placeholderText == 'run() ' + rightArrow() + ' { '
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable2("))?.placeholderText == '(Runnable2) run2() ' + rightArrow() + ' { '
|
|
}
|
|
|
|
public void "test no closure folding when the method throws an unresolved exception"() {
|
|
def text = """\
|
|
class Test {
|
|
void test() { new Runnable() {
|
|
public void run() throws Asadfsdafdfasd {
|
|
System.out.println(<caret>);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
"""
|
|
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
assert !foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
|
}
|
|
|
|
public void "test no closure folding for synchronized methods"() {
|
|
def text = """\
|
|
class Test {
|
|
void test() { new Runnable() {
|
|
public synchronized void run() {
|
|
System.out.println(<caret>);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
assert !foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
|
|
}
|
|
|
|
public void testFindInFolding() {
|
|
def text = """\
|
|
class Test {
|
|
void test1() {
|
|
}
|
|
void test2() {
|
|
<caret>test1();
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
myFixture.performEditorAction 'CollapseBlock'
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf('test1'))
|
|
myFixture.performEditorAction 'HighlightUsagesInFile'
|
|
FindManager.getInstance(project).findNextUsageInEditor(TextEditorProvider.getInstance().getTextEditor(myFixture.editor))
|
|
assertEquals('test1', myFixture.editor.selectionModel.selectedText)
|
|
}
|
|
|
|
public void testCustomFolding() { doTest() }
|
|
public void testEmptyMethod() { doTest() }
|
|
|
|
private doTest() {
|
|
myFixture.testFolding("$PathManagerEx.testDataPath/codeInsight/folding/${getTestName(false)}.java")
|
|
}
|
|
|
|
public void "test custom folding IDEA-122715 and IDEA-87312"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
public class Test {
|
|
|
|
//region Foo
|
|
interface Foo {void bar();}
|
|
//endregion
|
|
|
|
//region Bar
|
|
void test() {
|
|
|
|
}
|
|
//endregion
|
|
enum Bar {
|
|
BAR1,
|
|
BAR2
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
int count = 0;
|
|
for (FoldRegion region : foldingModel.allFoldRegions) {
|
|
if (region.startOffset == text.indexOf("//region Foo")) {
|
|
assert region.placeholderText == "Foo";
|
|
count ++;
|
|
}
|
|
else if (region.startOffset == text.indexOf("//region Bar")) {
|
|
assert region.placeholderText == "Bar"
|
|
count ++;
|
|
}
|
|
}
|
|
assert count == 2 : "Not all custom regions are found";
|
|
}
|
|
|
|
public void "test custom foldings intersecting with language ones"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Foo {
|
|
//*********************************************
|
|
// region Some
|
|
//*********************************************
|
|
|
|
int t = 1;
|
|
|
|
//*********************************************
|
|
// endregion
|
|
//*********************************************
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
assertEquals 1, foldRegionsCount
|
|
assertEquals "Some", foldingModel.allFoldRegions[0].placeholderText
|
|
}
|
|
|
|
public void "test custom foldings intersecting with comment foldings"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
// 0
|
|
// 1
|
|
// region Some
|
|
// 2
|
|
// 3 next empty line is significant
|
|
|
|
// non-dangling
|
|
int t = 1;
|
|
// 4
|
|
// 5
|
|
// endregion
|
|
// 6
|
|
// 7
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
|
|
assertFolding "// region"
|
|
assertFolding "// 0"
|
|
assertFolding "// 2" // Note: spans only two lines, see next test for details
|
|
assertFolding "// 4"
|
|
assertFolding "// 6"
|
|
|
|
assertEquals 5, foldRegionsCount
|
|
}
|
|
|
|
public void "test single line comments foldings"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
// 0
|
|
// 1
|
|
// 2 next empty line is significant
|
|
|
|
// 3 non-folded
|
|
// 4 non-folded
|
|
int t = 1;
|
|
// 5
|
|
// 6
|
|
// 7
|
|
}
|
|
"""
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
|
|
assertFolding "// 0"
|
|
assertNoFoldingStartsAt "// 3"
|
|
assertNoFoldingCovers "// 3"
|
|
assertNoFoldingCovers "// 4"
|
|
assertFolding "// 5"
|
|
|
|
assertEquals 2, foldRegionsCount
|
|
}
|
|
|
|
public void "test custom folding collapsed by default"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Test {
|
|
void test() {
|
|
//<editor-fold desc="Custom region">
|
|
System.out.println(1);
|
|
System.out.println(2);
|
|
//</editor-fold>
|
|
System.out.println(3);
|
|
};
|
|
}
|
|
"""
|
|
boolean oldValue = CodeFoldingSettings.instance.COLLAPSE_CUSTOM_FOLDING_REGIONS;
|
|
try {
|
|
CodeFoldingSettings.instance.COLLAPSE_CUSTOM_FOLDING_REGIONS = true;
|
|
configure text
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("//<editor-fold"))
|
|
}
|
|
finally {
|
|
CodeFoldingSettings.instance.COLLAPSE_CUSTOM_FOLDING_REGIONS = oldValue;
|
|
}
|
|
}
|
|
|
|
public void "test move methods"() {
|
|
@Language("JAVA")
|
|
def initialText = '''\
|
|
class Test {
|
|
void test1() {
|
|
}
|
|
|
|
void test2() {
|
|
}
|
|
}
|
|
'''
|
|
|
|
Closure<FoldRegion> fold = { String methodName ->
|
|
def text = myFixture.editor.document.text
|
|
def nameIndex = text.indexOf(methodName)
|
|
def start = text.indexOf('{', nameIndex)
|
|
def end = text.indexOf('}', start) + 1
|
|
def regions = myFixture.editor.foldingModel.allFoldRegions
|
|
for (region in regions) {
|
|
if (region.startOffset == start && region.endOffset == end) {
|
|
return region
|
|
}
|
|
}
|
|
fail("Can't find target fold region for method with name '$methodName'. Registered regions: $regions")
|
|
null
|
|
}
|
|
|
|
configure initialText
|
|
def foldingModel = myFixture.editor.foldingModel as FoldingModelEx
|
|
foldingModel.runBatchFoldingOperation {
|
|
fold('test1').expanded = true
|
|
fold('test2').expanded = false
|
|
}
|
|
|
|
myFixture.editor.caretModel.moveToOffset(initialText.indexOf('void'))
|
|
myFixture.performEditorAction 'MoveStatementDown'
|
|
CodeFoldingManager.getInstance(project).updateFoldRegions(myFixture.editor)
|
|
assertTrue(fold('test1').expanded)
|
|
assertFalse(fold('test2').expanded)
|
|
|
|
myFixture.performEditorAction 'MoveStatementUp'
|
|
CodeFoldingManager.getInstance(project).updateFoldRegions(myFixture.editor)
|
|
assertTrue(fold('test1').expanded)
|
|
assertFalse(fold('test2').expanded)
|
|
}
|
|
|
|
public void testUnorderedFoldRegionsRegistration() {
|
|
def text = '01234567'
|
|
configure text
|
|
def foldModel = myFixture.editor.foldingModel as FoldingModelImpl
|
|
foldModel.runBatchFoldingOperation {
|
|
def innerFold = foldModel.addFoldRegion(3, 5, '...')
|
|
def outerFold = foldModel.addFoldRegion(2, 6, '...')
|
|
innerFold.expanded = false
|
|
outerFold.expanded = false
|
|
}
|
|
def folds = foldModel.fetchVisible()
|
|
assertEquals(1, folds.length)
|
|
assertEquals(2, folds[0].startOffset)
|
|
assertEquals(6, folds[0].endOffset)
|
|
}
|
|
|
|
public void "test simple property accessors in one line"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
int field;
|
|
int field2;
|
|
int field3;
|
|
|
|
int getField()
|
|
{
|
|
return field;
|
|
}
|
|
|
|
void setField(int f) {
|
|
field = f;
|
|
}
|
|
|
|
void setField2(int f){field2=f;} // normal method folding here
|
|
|
|
// normal method folding here
|
|
void setField3(int f){
|
|
|
|
field2=f;
|
|
}
|
|
|
|
}"""
|
|
configure text
|
|
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
|
|
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
|
|
assert regions.size() == 6
|
|
|
|
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
|
|
checkAccessorFolding(regions[2], regions[3], fooClass.methods[1])
|
|
|
|
assert regions[4].placeholderText == '{...}'
|
|
assert regions[5].placeholderText == '{...}'
|
|
}
|
|
|
|
static checkAccessorFolding(FoldRegion region1, FoldRegion region2, PsiMethod method) {
|
|
assert region1.startOffset == method.parameterList.textRange.endOffset
|
|
assert region1.endOffset == method.body.statements[0].textRange.startOffset
|
|
assert region1.placeholderText == ' { '
|
|
|
|
assert region2.startOffset == method.body.statements[0].textRange.endOffset
|
|
assert region2.endOffset == method.textRange.endOffset
|
|
assert region2.placeholderText == ' }'
|
|
assert region1.group == region2.group
|
|
}
|
|
|
|
public void "test fold one-line methods"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
@Override
|
|
int someMethod() {
|
|
return 0;
|
|
}
|
|
|
|
int someOtherMethod(
|
|
int param) {
|
|
return 0;
|
|
}
|
|
|
|
}"""
|
|
configure text
|
|
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
|
|
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
|
|
assert regions.size() == 3
|
|
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
|
|
}
|
|
|
|
public void "test don't inline array methods"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
int arrayMethod(int param)[] {
|
|
return new int[0];
|
|
}
|
|
|
|
}"""
|
|
configure text
|
|
assert myFixture.editor.foldingModel.allFoldRegions.size() == 1
|
|
}
|
|
|
|
public void "test don't inline very long one-line methods"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
int someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
|
|
|
|
// don't create folding that would exceed the right margin
|
|
int getSomeVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable() {
|
|
return someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
|
|
}
|
|
}"""
|
|
configure text
|
|
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
|
|
assert regions.size() == 1
|
|
assert regions[0].placeholderText == '{...}'
|
|
}
|
|
|
|
|
|
private def changeFoldRegions(Closure op) {
|
|
myFixture.editor.foldingModel.runBatchFoldingOperationDoNotCollapseCaret(op)
|
|
}
|
|
|
|
public void "test unselect word should go inside folding group"() {
|
|
@Language("JAVA")
|
|
def text = """class Foo {
|
|
int field;
|
|
|
|
int getField() {
|
|
return field;
|
|
}
|
|
|
|
}"""
|
|
configure text
|
|
assertSize 2, myFixture.editor.foldingModel.allFoldRegions
|
|
myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.text.indexOf("return"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET)
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET)
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET)
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET)
|
|
assert """int getField() {
|
|
return field;
|
|
}""" == myFixture.editor.selectionModel.selectedText
|
|
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_UNSELECT_WORD_AT_CARET)
|
|
assert ' {\n return field;\n }' == myFixture.editor.selectionModel.selectedText
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_UNSELECT_WORD_AT_CARET)
|
|
assert 'return field;' == myFixture.editor.selectionModel.selectedText
|
|
}
|
|
|
|
public void "test expand and collapse regions in selection"() {
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
public static void main() {
|
|
new Runnable(){
|
|
public void run() {
|
|
}
|
|
}.run();
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertEquals 3, foldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_ALL_REGIONS)
|
|
assertEquals 3, expandedFoldRegionsCount
|
|
|
|
|
|
myFixture.editor.selectionModel.setSelection(text.indexOf("new"), text.indexOf("run();"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_ALL_REGIONS)
|
|
assertEquals 1, expandedFoldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_ALL_REGIONS)
|
|
assertEquals 3, expandedFoldRegionsCount
|
|
}
|
|
|
|
public void "test expand and collapse recursively"() {
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
public static void main() {
|
|
new Runnable(){
|
|
public void run() {
|
|
}
|
|
}.run();
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertEquals 3, foldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_ALL_REGIONS)
|
|
assertEquals 3, expandedFoldRegionsCount
|
|
|
|
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("new"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_REGION_RECURSIVELY)
|
|
assertEquals 1, expandedFoldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_REGION_RECURSIVELY)
|
|
assertEquals 3, expandedFoldRegionsCount
|
|
}
|
|
|
|
public void "test expand to level"() {
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
public static void main() {
|
|
new Runnable(){
|
|
public void run() {
|
|
}
|
|
}.run();
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertEquals 3, foldRegionsCount
|
|
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("new"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_TO_LEVEL_1)
|
|
assertEquals 2, expandedFoldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_ALL_TO_LEVEL_1)
|
|
assertEquals 1, expandedFoldRegionsCount
|
|
}
|
|
|
|
public void "test expand recursively on expanded region containing collapsed regions"() {
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
public static void main() {
|
|
new Runnable(){
|
|
public void run() {
|
|
}
|
|
}.run();
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertEquals 3, foldRegionsCount
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("run"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_REGION)
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("new"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_REGION)
|
|
assertEquals 1, expandedFoldRegionsCount
|
|
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("main"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_EXPAND_REGION_RECURSIVELY)
|
|
assertEquals 3, expandedFoldRegionsCount
|
|
}
|
|
|
|
public void "test single line closure unfolds when converted to multiline"() {
|
|
boolean oldValue = Registry.is("editor.durable.folding.state")
|
|
try {
|
|
Registry.get("editor.durable.folding.state").setValue(false)
|
|
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
void m() {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(text.indexOf("new Runnable"))
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("System"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ENTER)
|
|
myFixture.doHighlighting()
|
|
assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(text.indexOf("new Runnable")) == null
|
|
}
|
|
finally {
|
|
Registry.get("editor.durable.folding.state").setValue(oldValue)
|
|
}
|
|
}
|
|
|
|
public void "test folding state is preserved for unchanged text in bulk mode"() {
|
|
@Language("JAVA")
|
|
def text = """
|
|
class Foo {
|
|
void m1() {
|
|
|
|
}
|
|
void m2() {
|
|
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertEquals 2, foldRegionsCount
|
|
assertEquals 2, expandedFoldRegionsCount
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_ALL_REGIONS)
|
|
assertEquals 0, expandedFoldRegionsCount
|
|
|
|
def document = (DocumentEx)myFixture.editor.document
|
|
WriteCommandAction.runWriteCommandAction myFixture.project, {
|
|
DocumentUtil.executeInBulk(document, true, {
|
|
document.insertString(document.getText().indexOf("}") + 1, "\n");
|
|
} as Closure)
|
|
}
|
|
assertEquals 2, foldRegionsCount
|
|
assertEquals 0, expandedFoldRegionsCount
|
|
}
|
|
|
|
public void "test processing of tabs inside fold regions"() {
|
|
@Language("JAVA")
|
|
String text = """public class Foo {
|
|
\tpublic static void main(String[] args) {
|
|
\t\tjavax.swing.SwingUtilities.invokeLater(new Runnable() {
|
|
\t\t\t@Override
|
|
\t\t\tpublic void run() {
|
|
\t\t\t\tSystem.out.println();
|
|
\t\t\t}
|
|
\t\t});
|
|
\t}
|
|
}""";
|
|
configure text
|
|
assert myFixture.editor.getFoldingModel().getCollapsedRegionAtOffset(text.indexOf("new"))
|
|
myFixture.editor.settings.useTabCharacter = true
|
|
EditorTestUtil.configureSoftWraps(myFixture.editor, 1000)
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("System"))
|
|
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_TAB)
|
|
myFixture.checkResult("""public class Foo {
|
|
\tpublic static void main(String[] args) {
|
|
\t\tjavax.swing.SwingUtilities.invokeLater(new Runnable() {
|
|
\t\t\t@Override
|
|
\t\t\tpublic void run() {
|
|
\t\t\t\t\t<caret>System.out.println();
|
|
\t\t\t}
|
|
\t\t});
|
|
\t}
|
|
}""");
|
|
}
|
|
|
|
public void testCollapseExistingButExpandedBlock() {
|
|
@Language("JAVA")
|
|
String text = '''class Foo {
|
|
void m() {
|
|
if (true) {
|
|
System.out.println();
|
|
}
|
|
}
|
|
}
|
|
'''
|
|
configure text
|
|
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("System"))
|
|
myFixture.performEditorAction("CollapseBlock")
|
|
|
|
myFixture.performEditorAction("ExpandAllRegions")
|
|
|
|
myFixture.editor.caretModel.moveToOffset(text.indexOf("System"))
|
|
myFixture.performEditorAction("CollapseBlock")
|
|
|
|
def topLevelRegions = ((FoldingModelEx)myFixture.editor.foldingModel).fetchTopLevel()
|
|
assert topLevelRegions.length == 1
|
|
assert topLevelRegions[0].startOffset == text.indexOf('{', text.indexOf("if"))
|
|
assert topLevelRegions[0].endOffset == text.indexOf('}', text.indexOf("if")) + 1
|
|
}
|
|
|
|
public void "test editing near closure folding"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Foo {
|
|
void m() {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
System.out.println();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(56:143), placeholder='(Runnable) () → { ', FoldRegion +(164:188), placeholder=' }']"
|
|
myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.text.indexOf("SwingUtilities"))
|
|
myFixture.type(' ')
|
|
myFixture.doHighlighting()
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(57:144), placeholder='(Runnable) () → { ', FoldRegion +(165:189), placeholder=' }']"
|
|
}
|
|
|
|
public void "test folding update after external change"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Foo {
|
|
void m1() {
|
|
System.out.println(1);
|
|
System.out.println(2);
|
|
}
|
|
|
|
void m2() {
|
|
System.out.println(3);
|
|
System.out.println(4);
|
|
}
|
|
}
|
|
"""
|
|
configure text
|
|
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_ALL_REGIONS)
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(24:83), placeholder='{...}', FoldRegion +(97:156), placeholder='{...}']"
|
|
|
|
def virtualFile = ((EditorEx)myFixture.getEditor()).virtualFile
|
|
myFixture.saveText(virtualFile, """\
|
|
class Foo {
|
|
void m1() {
|
|
System.out.println(1);
|
|
System.out.println(4);
|
|
}
|
|
}
|
|
""")
|
|
virtualFile.refresh(false, false)
|
|
|
|
myFixture.doHighlighting()
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(24:83), placeholder='{...}']"
|
|
}
|
|
|
|
public void "test placeholder update on refactoring"() {
|
|
@Language("JAVA")
|
|
def text = """\
|
|
class Foo {
|
|
void method() {}
|
|
|
|
Foo foo = new Foo() {
|
|
void method() {
|
|
System.out.println();
|
|
}
|
|
};
|
|
}
|
|
"""
|
|
configure text
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(44:82), placeholder='method() → { ', FoldRegion +(103:113), placeholder=' }']"
|
|
|
|
// emulate rename refactoring ('method' to 'otherMethod')
|
|
def document = myFixture.editor.document
|
|
WriteCommandAction.runWriteCommandAction myFixture.project, {
|
|
int pos;
|
|
while ((pos = document.getText().indexOf("method")) >= 0) {
|
|
document.replaceString(pos, pos + "method".length(), "otherMethod")
|
|
}
|
|
}
|
|
|
|
myFixture.doHighlighting()
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(49:92), placeholder='otherMethod() → { ', FoldRegion +(113:123), placeholder=' }']"
|
|
}
|
|
|
|
public void "test imports remain collapsed when new item is added at the end"() {
|
|
boolean oldValue = CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY
|
|
CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = true
|
|
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(true); // tests disable this by default
|
|
((CodeInsightTestFixtureImpl)myFixture).canChangeDocumentDuringHighlighting(true)
|
|
try {
|
|
configure """\
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
class Foo {
|
|
public static void main(String[] args) {
|
|
Class a = ArrayList.class;
|
|
Class l = List.class;
|
|
<caret>
|
|
}
|
|
}
|
|
"""
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(7:50), placeholder='...']"
|
|
|
|
myFixture.type("Class t = TreeMap.class;")
|
|
myFixture.doHighlighting() // let auto-import complete
|
|
myFixture.checkResult"""\
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.TreeMap;
|
|
|
|
class Foo {
|
|
public static void main(String[] args) {
|
|
Class a = ArrayList.class;
|
|
Class l = List.class;
|
|
Class t = TreeMap.class;<caret>
|
|
}
|
|
}
|
|
"""
|
|
myFixture.doHighlighting() // update folding for the new text
|
|
assertTopLevelFoldRegionsState "[FoldRegion +(7:76), placeholder='...']"
|
|
}
|
|
finally {
|
|
CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = oldValue
|
|
}
|
|
}
|
|
|
|
private void assertTopLevelFoldRegionsState(String expectedState) {
|
|
assertEquals(expectedState, myFixture.editor.foldingModel.toString())
|
|
}
|
|
|
|
private int getFoldRegionsCount() {
|
|
return myFixture.editor.foldingModel.allFoldRegions.length
|
|
}
|
|
|
|
private int getExpandedFoldRegionsCount() {
|
|
return myFixture.editor.foldingModel.allFoldRegions.count { it.isExpanded() ? 1 : 0}
|
|
}
|
|
|
|
// Based on methods from GroovyFoldingTest
|
|
private boolean assertFolding(int offset) {
|
|
assert offset >= 0
|
|
myFixture.editor.foldingModel.allFoldRegions.any { it.startOffset == offset }
|
|
}
|
|
|
|
private void assertFolding(String marker) {
|
|
assert assertFolding(myFixture.file.text.indexOf(marker)), marker
|
|
}
|
|
|
|
private boolean assertNoFoldingCovers(int offset) {
|
|
assert offset >= 0
|
|
myFixture.editor.foldingModel.allFoldRegions.every { offset < it.startOffset || it.endOffset <= offset }
|
|
}
|
|
|
|
private void assertNoFoldingCovers(String marker) {
|
|
assert assertNoFoldingCovers(myFixture.file.text.indexOf(marker)), marker
|
|
}
|
|
|
|
private boolean assertNoFoldingStartsAt(int offset) {
|
|
assert offset >= 0
|
|
myFixture.editor.foldingModel.allFoldRegions.every { offset != it.startOffset }
|
|
}
|
|
|
|
private void assertNoFoldingStartsAt(String marker) {
|
|
assert assertNoFoldingStartsAt(myFixture.file.text.indexOf(marker)), marker
|
|
}
|
|
} |