IDEA-19061 Integrate the Rearranger-plugin into core-IDEA

1. Arrangement core engine is provided;
2. Arrangement tests infrastructure is provided;
3. Added java-specific support for arrangement by type, name and modifier;
4. Corresponding tests are added;
This commit is contained in:
Denis.Zhdanov
2012-07-24 10:46:44 +04:00
parent 6f3abb799d
commit 7a9eddae63
18 changed files with 1038 additions and 23 deletions
@@ -0,0 +1,84 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement
import com.intellij.lang.java.JavaLanguage
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.util.TextRange
import com.intellij.psi.codeStyle.CodeStyleSettings
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.annotations.NotNull
/**
* @author Denis Zhdanov
* @since 7/20/12 2:54 PM
*/
abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase {
def FileType fileType
@Override
protected void setUp() {
super.setUp()
CodeStyleSettingsManager.getInstance(myFixture.project).temporarySettings = new CodeStyleSettings()
}
@Override
protected void tearDown() {
CodeStyleSettingsManager.getInstance(myFixture.project).dropTemporarySettings()
super.tearDown()
}
protected void doTest(@NotNull String initial,
@NotNull String expected,
@NotNull List<ArrangementRule> rules,
@NotNull Collection<TextRange> ranges = null)
{
def (String textToUse, List<TextRange> rangesToUse) = parseRanges(initial)
if (rangesToUse && ranges) {
fail("Duplicate ranges info detected: explicitly given: $ranges, derived from markup: $rangesToUse. Text:\n$initial")
}
if (!rangesToUse) {
rangesToUse = ranges ?: [TextRange.from(0, initial.length())]
}
myFixture.configureByText(fileType, textToUse)
def settings = CodeStyleSettingsManager.getInstance(myFixture.project).currentSettings.getCommonSettings(JavaLanguage.INSTANCE)
settings.arrangementRules = rules
ArrangementEngine engine = ServiceManager.getService(myFixture.project, ArrangementEngine)
engine.arrange(myFixture.file, rangesToUse);
assertEquals(expected, myFixture.editor.document.text);
}
@NotNull
private static def parseRanges(@NotNull String text) {
def clearText = new StringBuilder(text)
def ranges = []
int shift = 0
int shiftIncrease = '<range>'.length() * 2 + 1
def match = text =~ '(?is)<range>.*?</range>'
match.each {
ranges << TextRange.create(match.start() - shift, match.end() - shift - shiftIncrease)
clearText.delete(match.end() - '</range>'.length() - shift, match.end() - shift)
clearText.delete(match.start() - shift, match.start() + '<range>'.length() - shift)
shift += shiftIncrease
}
[clearText.toString(), ranges]
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2000-2012 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.psi.codeStyle.arrangement
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType
import com.intellij.psi.codeStyle.arrangement.match.ByTypeArrangementEntryMatcher
/**
* @author Denis Zhdanov
* @since 7/20/12 2:45 PM
*/
class JavaRearrangerByTypeTest extends AbstractRearrangerTest {
JavaRearrangerByTypeTest() {
fileType = JavaFileType.INSTANCE
}
void testFieldsBeforeMethods() {
doTest(
'''\
class Test {
public void test() {}
private int i;
}
class Test2 {
public void test() {
}
private int i;
private int j;
}''',
'''\
class Test {
private int i;
public void test() {}
}
class Test2 {
private int i;
private int j;
public void test() {
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
)
}
void testAnonymousClassAtFieldInitializer() {
doTest(
'''\
class Test {
private Object first = new Object() {
int inner1;
public String toString() { return "test"; }
int inner2;
};
public Object test(Object ... args) {
return null;
}
private Object second = test(test(new Object() {
public String toString() {
return "test";
}
private Object inner = new Object() {
public String toString() { return "innerTest"; }
};
}));
}''',
'''\
class Test {
private Object first = new Object() {
int inner1;
int inner2;
public String toString() { return "test"; }
};
private Object second = test(test(new Object() {
private Object inner = new Object() {
public String toString() { return "innerTest"; }
};
public String toString() {
return "test";
}
}));
public Object test(Object ... args) {
return null;
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
)
}
void testAnonymousClassAtMethod() {
doTest(
'''\
class Test {
void declaration() {
Object o = new Object() {
private int test() { return 1; }
String s;
}
}
double d;
void call() {
test(test(1, new Object() {
public void test() {}
int i;
});
}
}''',
'''\
class Test {
double d;
void declaration() {
Object o = new Object() {
String s;
private int test() { return 1; }
}
}
void call() {
test(test(1, new Object() {
int i;
public void test() {}
});
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
)
}
void testRanges() {
doTest(
'''\
class Test {
void outer1() {}
<range> String outer2() {}
int i;</range>
void test() {
method(new Object() {
void inner1() {}
Object field = new Object() {
<range> void inner2() {}
String s;</range>
Integer i;
}
});
}
}''',
'''\
class Test {
void outer1() {}
int i;
String outer2() {}
void test() {
method(new Object() {
void inner1() {}
Object field = new Object() {
String s;
void inner2() {}
Integer i;
}
});
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
)
}
}