blob: b16e23e83e376ce8bc98783caf328d280774a614 [file] [log] [blame]
/*
* Copyright 2000-2014 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.formatter.java;
import com.intellij.idea.Bombed;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import java.util.Calendar;
/**
* Is intended to hold specific java formatting tests for 'wrapping' settings.
*
* @author Denis Zhdanov
* @since Apr 29, 2010 4:06:15 PM
*/
public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
@SuppressWarnings("SpellCheckingInspection")
public void testWrappingAnnotationArrayParameters() {
getSettings().RIGHT_MARGIN = 80;
getSettings().ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doTextTest(
"@AttributeOverrides( { @AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\"))," +
"@AttributeOverride(name = \"transactionReference\", column = @Column(name = \"deal_reference\"))," +
"@AttributeOverride(name = \"eventDate\", column = @Column(name = \"recovery_date\"))," +
"@AttributeOverride(name = \"amount\", column = @Column(name = \"recovery_amount\"))," +
"@AttributeOverride(name = \"currency\", column = @Column(name = \"local_currency\"))," +
"@AttributeOverride(name = \"exchangeRate\", column = @Column(name = \"exchange_rate\"))," +
"@AttributeOverride(name = \"exchangeRateDate\", column = @Column(name = \"recovery_date\", insertable = false, updatable = false))," +
"@AttributeOverride(name = \"exchangeRateAlterationJustification\", column = @Column(name = \"exchange_rate_justification\"))," +
"@AttributeOverride(name = \"systemExchangeRate\", column = @Column(name = \"system_exchange_rate\")) })\n" +
"class Foo {\n" +
"}",
"@AttributeOverrides({\n" +
" @AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\")),\n" +
" @AttributeOverride(name = \"transactionReference\", column = @Column(name = \"deal_reference\")),\n" +
" @AttributeOverride(name = \"eventDate\", column = @Column(name = \"recovery_date\")),\n" +
" @AttributeOverride(name = \"amount\", column = @Column(name = \"recovery_amount\")),\n" +
" @AttributeOverride(name = \"currency\", column = @Column(name = \"local_currency\")),\n" +
" @AttributeOverride(name = \"exchangeRate\", column = @Column(name = \"exchange_rate\")),\n" +
" @AttributeOverride(name = \"exchangeRateDate\", column = @Column(name = \"recovery_date\", insertable = false, updatable = false)),\n" +
" @AttributeOverride(name = \"exchangeRateAlterationJustification\", column = @Column(name = \"exchange_rate_justification\")),\n" +
" @AttributeOverride(name = \"systemExchangeRate\", column = @Column(name = \"system_exchange_rate\"))})\n" +
"class Foo {\n" +
"}"
);
}
public void testAnnotationParamValueExceedingRightMargin() {
// Inspired by IDEA-18051
getSettings().RIGHT_MARGIN = 80;
doTextTest(
"package formatting;\n" +
"\n" +
"public class EnumInAnnotationFormatting {\n" +
"\n" +
" public enum TheEnum {\n" +
"\n" +
" FIRST,\n" +
" SECOND,\n" +
" THIRD,\n" +
"\n" +
" }\n" +
"\n" +
" public @interface TheAnnotation {\n" +
"\n" +
" TheEnum[] value();\n" +
"\n" +
" String comment();\n" +
"\n" +
" }\n" +
"\n" +
"\n" +
" @TheAnnotation(value = {TheEnum.FIRST, TheEnum.SECOND}, comment =" +
" \"some long comment that goes longer that right margin 012345678901234567890\")\n" +
" public class Test {\n" +
"\n" +
" }\n" +
"\n" +
"}",
"package formatting;\n" +
"\n" +
"public class EnumInAnnotationFormatting {\n" +
"\n" +
" public enum TheEnum {\n" +
"\n" +
" FIRST,\n" +
" SECOND,\n" +
" THIRD,\n" +
"\n" +
" }\n" +
"\n" +
" public @interface TheAnnotation {\n" +
"\n" +
" TheEnum[] value();\n" +
"\n" +
" String comment();\n" +
"\n" +
" }\n" +
"\n" +
"\n" +
" @TheAnnotation(value = {TheEnum.FIRST, TheEnum.SECOND}, comment =" +
" \"some long comment that goes longer that right margin 012345678901234567890\")\n" +
" public class Test {\n" +
"\n" +
" }\n" +
"\n" +
"}");
}
@SuppressWarnings("SpellCheckingInspection")
public void testEnumConstantsWrapping() {
// Inspired by IDEA-54667
getSettings().ENUM_CONSTANTS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().RIGHT_MARGIN = 80;
// Don't expect the constants to be placed on new line.
doTextTest(
"enum Test {FIRST, SECOND}",
"enum Test {FIRST, SECOND}"
);
// Expect not only enum constants to be wrapped but line break inside enum-level curly braces as well.
doTextTest(
"enum Test {FIRST, SECOND, THIIIIIIIIIIIIIIIIIRRDDDDDDDDDDDDDD, FOURTHHHHHHHHHHHHHHHH}",
"enum Test {\n" +
" FIRST, SECOND, THIIIIIIIIIIIIIIIIIRRDDDDDDDDDDDDDD, FOURTHHHHHHHHHHHHHHHH\n" +
"}"
);
}
public void testIDEA123074() {
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS;
String before = "final GeoZone geoZone1 = new GeoZone(APPROACHING, new Polygon(point(\"0.0\", \"0.0\"), point(\"10.0\", \"0.0\")," +
"point(\"10.0\", \"10.0\"), point(\"0.0\", \"10.0\")));";
String after = "final GeoZone geoZone1 = new GeoZone(APPROACHING,\n" +
" new Polygon(point(\"0.0\",\n" +
" \"0.0\"),\n" +
" point(\"10.0\",\n" +
" \"0.0\"),\n" +
" point(\"10.0\",\n" +
" \"10.0\"),\n" +
" point(\"0.0\",\n" +
" \"10.0\")));";
doMethodTest(before, after);
}
public void testMethodAnnotationFollowedBySingleLineComment() {
// Inspired by IDEA-22808
getSettings().METHOD_ANNOTATION_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS;
String text =
"@Test//my_comment\n" +
"public void foo() {\n" +
"}";
// Expecting the code to be left as-is
doClassTest(text, text);
}
public void testWrapCompoundStringLiteralThatEndsAtRightMargin() {
// Inspired by IDEA-82398
getSettings().RIGHT_MARGIN = 30;
getSettings().WRAP_LONG_LINES = true;
final String text = "class Test {\n" +
" String s = \"first line \" +\n" +
" +\"second line\";\n" +
"}";
doTextTest(text, text);
}
public void testWrapLongLine() {
// Inspired by IDEA-55782
getSettings().RIGHT_MARGIN = 50;
getSettings().WRAP_LONG_LINES = true;
doTextTest(
"class TestClass {\n" +
" // Single line comment that is long enough to exceed right margin\n" +
" /* Multi line comment that is long enough to exceed right margin*/\n" +
" /**\n" +
" Javadoc comment that is long enough to exceed right margin" +
" */\n" +
" public String s = \"this is a string that is long enough to be wrapped\"\n" +
"}",
"class TestClass {\n" +
" // Single line comment that is long enough \n" +
" // to exceed right margin\n" +
" /* Multi line comment that is long enough \n" +
" to exceed right margin*/\n" +
" /**\n" +
" * Javadoc comment that is long enough to \n" +
" * exceed right margin\n" +
" */\n" +
" public String s = \"this is a string that is\" +\n" +
" \" long enough to be wrapped\"\n" +
"}"
);
}
public void testWrapLongLineWithTabs() {
// Inspired by IDEA-55782
getSettings().RIGHT_MARGIN = 20;
getSettings().WRAP_LONG_LINES = true;
getIndentOptions().USE_TAB_CHARACTER = true;
getIndentOptions().TAB_SIZE = 4;
doTextTest(
"class TestClass {\n" +
"\t \t //This is a comment\n" +
"}",
"class TestClass {\n" +
"\t//This is a \n" +
"\t// comment\n" +
"}"
);
}
public void testWrapLongLineWithSelection() {
// Inspired by IDEA-55782
getSettings().RIGHT_MARGIN = 20;
getSettings().WRAP_LONG_LINES = true;
String initial =
"class TestClass {\n" +
" //This is a comment\n" +
" //This is another comment\n" +
"}";
int start = initial.indexOf("//");
int end = initial.indexOf("comment");
myTextRange = new TextRange(start, end);
doTextTest(initial, initial);
myLineRange = new TextRange(1, 1);
doTextTest(
initial,
"class TestClass {\n" +
" //This is a \n" +
" // comment\n" +
" //This is another comment\n" +
"}"
);
}
@Bombed(user = "Roman Shevchenko", year = 2014, month = Calendar.MARCH, day = 14)
public void testWrapMethodAnnotationBeforeParams() {
// Inspired by IDEA-59536
getSettings().RIGHT_MARGIN = 90;
getSettings().METHOD_ANNOTATION_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doClassTest(
"@SuppressWarnings({\"SomeInspectionIWantToIgnore\"}) public void doSomething(int x, int y) {}",
"@SuppressWarnings({\"SomeInspectionIWantToIgnore\"})\n" +
"public void doSomething(int x, int y) {\n}"
);
}
public void testMultipleExpressionInSameLine() {
// Inspired by IDEA-64975.
getSettings().KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = true;
doMethodTest(
"int i = 1; int j = 2;",
"int i = 1; int j = 2;"
);
getSettings().KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = false;
doMethodTest(
"int i = 1; int j = 2;",
"int i = 1;\n" +
"int j = 2;"
);
}
public void testIncompleteFieldAndAnnotationWrap() {
// Inspired by IDEA-64725
getSettings().FIELD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
doClassTest(
"@NotNull Comparable<String>",
"@NotNull Comparable<String>"
);
}
public void testResourceListWrap() {
getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true;
getSettings().RIGHT_MARGIN = 40;
getSettings().RESOURCE_LIST_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doMethodTest("try (MyResource r1 = null; MyResource r2 = null) { }",
"try (MyResource r1 = null;\n" +
" MyResource r2 = null) { }");
getSettings().RESOURCE_LIST_LPAREN_ON_NEXT_LINE = true;
getSettings().RESOURCE_LIST_RPAREN_ON_NEXT_LINE = true;
doMethodTest("try (MyResource r1 = null; MyResource r2 = null) { }",
"try (\n" +
" MyResource r1 = null;\n" +
" MyResource r2 = null\n" +
") { }");
}
@SuppressWarnings("SpellCheckingInspection")
public void testLineLongEnoughToExceedAfterFirstWrapping() {
// Inspired by IDEA-103624
getSettings().WRAP_LONG_LINES = true;
getSettings().RIGHT_MARGIN = 40;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doMethodTest(
"test(1,\n" +
" 2,\n" +
" MyTestClass.loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongMethod());\n" +
"int i = 1;\n" +
"int j = 2;",
"test(1,\n" +
" 2,\n" +
" MyTestClass\n" +
" .loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongMethod());\n" +
"int i = 1;\n" +
"int j = 2;"
);
}
@SuppressWarnings("SpellCheckingInspection")
public void testNoUnnecessaryWrappingIsPerformedForLongLine() {
// Inspired by IDEA-103624
getSettings().WRAP_LONG_LINES = true;
getSettings().RIGHT_MARGIN = 40;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
String text =
"test(1,\n" +
" 2,\n" +
" Test.\n" +
" loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongMethod()\n" +
");\n" +
"int i = 1;\n" +
"int j = 2;";
doMethodTest(text, text);
}
public void testEnforceIndentMethodCallParamWrap() {
getSettings().WRAP_LONG_LINES = true;
getSettings().RIGHT_MARGIN = 140;
getSettings().PREFER_PARAMETERS_WRAP = true;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
String before = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, " +
"String.format(\"Could not process annotations: %s%n%s\", e.toString(), writer.toString()));";
String afterFirstReformat = "processingEnv.getMessenger().printMessage(\n" +
" Diagnostic.Kind.ERROR, String.format(\n" +
" \"Could not process annotations: %s%n%s\",\n" +
" e.toString(),\n" +
" writer.toString()\n" +
")\n" +
");";
String after = "processingEnv.getMessenger().printMessage(\n" +
" Diagnostic.Kind.ERROR, String.format(\n" +
" \"Could not process annotations: %s%n%s\",\n" +
" e.toString(),\n" +
" writer.toString()\n" +
" )\n" +
");";
doMethodTest(afterFirstReformat, after);
getSettings().CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = true;
getSettings().CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true;
doMethodTest(before, after);
String literal = "\"" + StringUtil.repeatSymbol('A', 128) + "\"";
before = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, call(" + literal + "));\n";
after = "processingEnv.getMessenger().printMessage(\n" +
" Diagnostic.Kind.ERROR, call(\n" +
" " + literal + "\n" +
" )\n" +
");\n";
doMethodTest(before, after);
}
@SuppressWarnings("SpellCheckingInspection")
public void testDoNotWrapMethodsWithMethodCallAsParameters() {
getSettings().WRAP_LONG_LINES = true;
getSettings().RIGHT_MARGIN = 140;
getSettings().PREFER_PARAMETERS_WRAP = true;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
getSettings().CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = true;
getSettings().CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true;
String before = " processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage());";
String after = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage());";
doMethodTest(before, after);
before = " processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage(loooooooooooooooooongParamName));";
after = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage(loooooooooooooooooongParamName));";
doMethodTest(before, after);
}
public void testFieldAnnotationWithoutModifier() {
doClassTest("@NotNull String myFoo = null;", "@NotNull\nString myFoo = null;");
}
public void testTypeAnnotationsInModifierList() {
getSettings().getRootSettings().FORMATTER_TAGS_ENABLED = true;
String prefix =
"import java.lang.annotation.*;\n\n" +
"//@formatter:off\n" +
"@interface A { }\n" +
"@Target({ElementType.TYPE_USE}) @interface TA { int value() default 0; }\n" +
"//@formatter:on\n\n";
doTextTest(
prefix + "interface C {\n" +
" @TA(0)String m();\n" +
" @A @TA(1) @TA(2)String m();\n" +
" @A public @TA String m();\n" +
"}",
prefix + "interface C {\n" +
" @TA(0) String m();\n\n" +
" @A\n" +
" @TA(1) @TA(2) String m();\n\n" +
" @A\n" +
" public @TA String m();\n" +
"}");
}
public void testKeepSingleFieldAnnotationOnSameLine() {
getJavaSettings().DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = true;
doClassTest(
"@NotNull public String result = \"OK\"\n" +
"@NotNull String newResult = \"OK\"\n" +
"@NotNull\n" +
"@Deprecated public String bad = \"bad\"",
"@NotNull public String result = \"OK\"\n" +
"@NotNull String newResult = \"OK\"\n" +
"@NotNull\n" +
"@Deprecated\n" +
"public String bad = \"bad\""
);
}
public void testMoveSingleAnnotationOnSameLine() {
getJavaSettings().DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = true;
getSettings().KEEP_LINE_BREAKS = false;
doClassTest(
"@NotNull\n" +
"public String test = \"tst\";\n" +
"String ok = \"ok\";\n",
"@NotNull public String test = \"tst\";\n" +
"String ok = \"ok\";\n"
);
}
}