literal arguments folding: fold one char instead of the whole literal; folding in case of generic method fixed; Settings|Editor|General|Code Folding|Literal arguments|Minimum arguments to fold and Minimum parameter name length settings added

This commit is contained in:
Alexey Kudravtsev
2016-08-04 15:21:39 +03:00
parent da1faa5875
commit 3b2dfb2619
11 changed files with 452 additions and 111 deletions
@@ -27,16 +27,47 @@ import com.intellij.openapi.options.BeanConfigurable;
public class JavaCodeFoldingOptionsProvider extends BeanConfigurable<JavaCodeFoldingSettings> implements CodeFoldingOptionsProvider {
public JavaCodeFoldingOptionsProvider() {
super(JavaCodeFoldingSettings.getInstance());
checkBox("INLINE_PARAMETER_NAMES_FOR_LITERAL_CALL_ARGUMENTS", ApplicationBundle.message("checkbox.collapse.boolean.parameters"));
checkBox("COLLAPSE_ONE_LINE_METHODS", ApplicationBundle.message("checkbox.collapse.one.line.methods"));
checkBox("COLLAPSE_ACCESSORS", ApplicationBundle.message("checkbox.collapse.simple.property.accessors"));
checkBox("COLLAPSE_INNER_CLASSES", ApplicationBundle.message("checkbox.collapse.inner.classes"));
checkBox("COLLAPSE_ANONYMOUS_CLASSES", ApplicationBundle.message("checkbox.collapse.anonymous.classes"));
checkBox("COLLAPSE_ANNOTATIONS", ApplicationBundle.message("checkbox.collapse.annotations"));
checkBox("COLLAPSE_CLOSURES", ApplicationBundle.message("checkbox.collapse.closures"));
checkBox("COLLAPSE_CONSTRUCTOR_GENERIC_PARAMETERS", ApplicationBundle.message("checkbox.collapse.generic.constructor.parameters"));
checkBox("COLLAPSE_I18N_MESSAGES", ApplicationBundle.message("checkbox.collapse.i18n.messages"));
checkBox("COLLAPSE_SUPPRESS_WARNINGS", ApplicationBundle.message("checkbox.collapse.suppress.warnings"));
checkBox("COLLAPSE_END_OF_LINE_COMMENTS", ApplicationBundle.message("checkbox.collapse.end.of.line.comments"));
JavaCodeFoldingSettings settings = getInstance();
checkBox(ApplicationBundle.message("checkbox.collapse.boolean.parameters"), settings::isInlineParameterNamesForLiteralCallArguments, settings::setInlineParameterNamesForLiteralCallArguments);
JavaCodeFoldingSettingsPanel panel = new JavaCodeFoldingSettingsPanel();
component(panel.getRow0(),
() -> null,
pair -> {},
() -> null,
pair -> {}
);
component(panel.getRow1(),
settings::getInlineLiteralParameterMinNameLength,
settings::setInlineLiteralParameterMinNameLength,
panel::getMinNameLengthThresholdText,
panel::setMinNameLengthThresholdText
);
component(panel.getRow2(),
settings::getInlineLiteralParameterMinArgumentsToFold,
settings::setInlineLiteralParameterMinArgumentsToFold,
panel::getMinArgumentsToFoldText,
panel::setMinArgumentsToFoldText
);
checkBox(ApplicationBundle.message("checkbox.collapse.one.line.methods"), settings::isCollapseOneLineMethods, settings::setCollapseOneLineMethods);
checkBox(ApplicationBundle.message("checkbox.collapse.simple.property.accessors"), settings::isCollapseAccessors, settings::setCollapseAccessors);
checkBox(ApplicationBundle.message("checkbox.collapse.inner.classes"), settings::isCollapseInnerClasses, settings::setCollapseInnerClasses);
checkBox(ApplicationBundle.message("checkbox.collapse.anonymous.classes"), settings::isCollapseAnonymousClasses, settings::setCollapseAnonymousClasses);
checkBox(ApplicationBundle.message("checkbox.collapse.annotations"), settings::isCollapseAnnotations, settings::setCollapseAnnotations);
checkBox(ApplicationBundle.message("checkbox.collapse.closures"), settings::isCollapseLambdas, settings::setCollapseLambdas);
checkBox(ApplicationBundle.message("checkbox.collapse.generic.constructor.parameters"), settings::isCollapseConstructorGenericParameters, settings::setCollapseConstructorGenericParameters);
checkBox(ApplicationBundle.message("checkbox.collapse.i18n.messages"), settings::isCollapseI18nMessages, settings::setCollapseI18nMessages);
checkBox(ApplicationBundle.message("checkbox.collapse.suppress.warnings"), settings::isCollapseSuppressWarnings, settings::setCollapseSuppressWarnings);
checkBox(ApplicationBundle.message("checkbox.collapse.end.of.line.comments"), settings::isCollapseEndOfLineComments, settings::setCollapseEndOfLineComments);
}
}
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.editor.JavaCodeFoldingSettingsPanel">
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="852" height="97"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="bc2a4" binding="row1" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="a067a" class="javax.swing.JTextField" binding="minNameLengthThresholdText">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="2746f" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="5" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Minimum Parameter Name Length:"/>
</properties>
</component>
</children>
</grid>
<grid id="8e464" binding="row2" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="11578" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="5" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Minimum Number of Arguments To Fold:"/>
</properties>
</component>
<component id="dc29a" class="javax.swing.JTextField" binding="minArgumentsToFoldText">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="72ed7" binding="row0" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="c0ee0" class="com.intellij.ui.TitledSeparator">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="4" anchor="0" fill="1" indent="3" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Literal Arguments Options"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -0,0 +1,64 @@
/*
* Copyright 2000-2016 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.application.options.editor;
import javax.swing.*;
public class JavaCodeFoldingSettingsPanel {
private JTextField minNameLengthThresholdText;
private JTextField minArgumentsToFoldText;
private JPanel row0;
private JPanel row1;
private JPanel row2;
int getMinNameLengthThresholdText() {
try {
return Integer.parseInt(minNameLengthThresholdText.getText());
}
catch (NumberFormatException e) {
return 3;
}
}
void setMinNameLengthThresholdText(int value) {
minNameLengthThresholdText.setText(String.valueOf(value));
}
int getMinArgumentsToFoldText() {
try {
return Integer.parseInt(minArgumentsToFoldText.getText());
}
catch (NumberFormatException e) {
return 2;
}
}
void setMinArgumentsToFoldText(int value) {
minArgumentsToFoldText.setText(String.valueOf(value));
}
JComponent getRow0() {
return row0;
}
JPanel getRow1() {
return row1;
}
JPanel getRow2() {
return row2;
}
}
@@ -40,6 +40,7 @@ public abstract class JavaCodeFoldingSettings {
public abstract void setCollapseAccessors(boolean value);
public abstract boolean isCollapseOneLineMethods();
public abstract void setCollapseOneLineMethods(boolean value);
public abstract boolean isCollapseInnerClasses();
public abstract void setCollapseInnerClasses(boolean value);
@@ -67,4 +68,10 @@ public abstract class JavaCodeFoldingSettings {
public abstract boolean isInlineParameterNamesForLiteralCallArguments();
public abstract void setInlineParameterNamesForLiteralCallArguments(boolean value);
public abstract int getInlineLiteralParameterMinNameLength();
public abstract void setInlineLiteralParameterMinNameLength(int value);
public abstract int getInlineLiteralParameterMinArgumentsToFold();
public abstract void setInlineLiteralParameterMinArgumentsToFold(int value);
}
@@ -19,17 +19,19 @@ import com.intellij.codeInsight.folding.CodeFoldingSettings;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
public class JavaCodeFoldingSettingsBase extends JavaCodeFoldingSettings {
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_ACCESSORS;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_ONE_LINE_METHODS = true;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_INNER_CLASSES;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_ANONYMOUS_CLASSES;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_ANNOTATIONS;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_CLOSURES = true;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_CONSTRUCTOR_GENERIC_PARAMETERS = true;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_I18N_MESSAGES = true;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_SUPPRESS_WARNINGS = true;
@SuppressWarnings("WeakerAccess") public boolean COLLAPSE_END_OF_LINE_COMMENTS;
@SuppressWarnings("WeakerAccess") public boolean INLINE_PARAMETER_NAMES_FOR_LITERAL_CALL_ARGUMENTS;
private boolean COLLAPSE_ACCESSORS;
private boolean COLLAPSE_ONE_LINE_METHODS = true;
private boolean COLLAPSE_INNER_CLASSES;
private boolean COLLAPSE_ANONYMOUS_CLASSES;
private boolean COLLAPSE_ANNOTATIONS;
private boolean COLLAPSE_CLOSURES = true;
private boolean COLLAPSE_CONSTRUCTOR_GENERIC_PARAMETERS = true;
private boolean COLLAPSE_I18N_MESSAGES = true;
private boolean COLLAPSE_SUPPRESS_WARNINGS = true;
private boolean COLLAPSE_END_OF_LINE_COMMENTS;
private boolean INLINE_PARAMETER_NAMES_FOR_LITERAL_CALL_ARGUMENTS;
private int INLINE_LITERAL_PARAMETER_MIN_NAME_LENGTH = 3;
private int INLINE_LITERAL_PARAMETER_MIN_ARGS_TO_FOLD = 2;
@Override
public boolean isCollapseImports() {
@@ -85,6 +87,11 @@ public class JavaCodeFoldingSettingsBase extends JavaCodeFoldingSettings {
return COLLAPSE_ONE_LINE_METHODS;
}
@Override
public void setCollapseOneLineMethods(boolean value) {
COLLAPSE_ONE_LINE_METHODS = value;
}
@Override
public boolean isCollapseInnerClasses() {
return COLLAPSE_INNER_CLASSES;
@@ -174,4 +181,24 @@ public class JavaCodeFoldingSettingsBase extends JavaCodeFoldingSettings {
public void setInlineParameterNamesForLiteralCallArguments(boolean value) {
INLINE_PARAMETER_NAMES_FOR_LITERAL_CALL_ARGUMENTS = value;
}
@Override
public int getInlineLiteralParameterMinNameLength() {
return INLINE_LITERAL_PARAMETER_MIN_NAME_LENGTH;
}
@Override
public void setInlineLiteralParameterMinNameLength(int value) {
INLINE_LITERAL_PARAMETER_MIN_NAME_LENGTH = value;
}
@Override
public int getInlineLiteralParameterMinArgumentsToFold() {
return INLINE_LITERAL_PARAMETER_MIN_ARGS_TO_FOLD;
}
@Override
public void setInlineLiteralParameterMinArgumentsToFold(int value) {
INLINE_LITERAL_PARAMETER_MIN_ARGS_TO_FOLD = value;
}
}
@@ -807,13 +807,12 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
private static void inlineLiteralArgumentsNames(@NotNull PsiCallExpression expression,
@NotNull List<FoldingDescriptor> foldElements,
boolean quick)
{
boolean quick) {
if (quick || !JavaCodeFoldingSettings.getInstance().isInlineParameterNamesForLiteralCallArguments()) {
return;
}
ParameterNameFoldingManager manager = new ParameterNameFoldingManager(expression);
foldElements.addAll(manager.buildDescriptors());
foldElements.addAll(manager.getDescriptors());
}
private boolean addClosureFolding(@NotNull PsiClass aClass,
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.folding.impl;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.lang.folding.NamedFoldingDescriptor;
import com.intellij.openapi.util.Couple;
@@ -27,12 +28,11 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ParameterNameFoldingManager {
private static final int MIN_NAME_LENGTH_THRESHOLD = 3;
private static final int MIN_ARGS_TO_FOLD = 2;
class ParameterNameFoldingManager {
private static final List<Couple<String>> COMMONLY_USED_PARAMETER_PAIR = ContainerUtil.newArrayList(
Couple.of("begin", "end"),
Couple.of("start", "end"),
@@ -43,16 +43,27 @@ public class ParameterNameFoldingManager {
Couple.of("min", "max")
);
private final PsiCallExpression myCallExpression;
@NotNull
private final List<FoldingDescriptor> myDescriptors;
private PsiExpression[] myCallArguments;
private PsiParameter[] myParameters;
ParameterNameFoldingManager(@NotNull PsiCallExpression callExpression) {
PsiExpression[] callArguments = getArguments(callExpression);
JavaResolveResult resolveResult = callExpression.resolveMethodGenerics();
public ParameterNameFoldingManager(@NotNull PsiCallExpression callExpression) {
myCallExpression = callExpression;
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
List<FoldingDescriptor> descriptors = Collections.emptyList();
if (callArguments.length >= settings.getInlineLiteralParameterMinArgumentsToFold() &&
hasLiteralExpression(callArguments) &&
resolveResult.getElement() instanceof PsiMethod) {
PsiMethod method = (PsiMethod)resolveResult.getElement();
PsiParameter[] parameters = method.getParameterList().getParameters();
descriptors = buildDescriptorsForLiteralArguments(callArguments, parameters, resolveResult);
}
myDescriptors = descriptors;
}
public static boolean isLiteralExpression(@Nullable PsiElement callArgument) {
static boolean isLiteralExpression(@Nullable PsiElement callArgument) {
if (callArgument instanceof PsiLiteralExpression)
return true;
@@ -66,43 +77,32 @@ public class ParameterNameFoldingManager {
return false;
}
@Nullable
public PsiExpression[] getArguments(@NotNull PsiCallExpression call) {
@NotNull
private static PsiExpression[] getArguments(@NotNull PsiCallExpression call) {
PsiExpressionList callArgumentsList = call.getArgumentList();
return callArgumentsList != null ? callArgumentsList.getExpressions() : null;
return callArgumentsList == null ? PsiExpression.EMPTY_ARRAY : callArgumentsList.getExpressions();
}
@NotNull
public List<FoldingDescriptor> buildDescriptors() {
myCallArguments = getArguments(myCallExpression);
if (myCallArguments != null && myCallArguments.length >= MIN_ARGS_TO_FOLD && hasLiteralExpression(myCallArguments)) {
PsiMethod method = myCallExpression.resolveMethod();
if (method != null) {
myParameters = method.getParameterList().getParameters();
if (myParameters.length == myCallArguments.length) {
return buildDescriptorsForLiteralArguments();
}
}
}
return ContainerUtil.emptyList();
List<FoldingDescriptor> getDescriptors() {
return myDescriptors;
}
@NotNull
private List<FoldingDescriptor> buildDescriptorsForLiteralArguments() {
List<FoldingDescriptor> descriptors = ContainerUtil.newArrayList();
private static List<FoldingDescriptor> buildDescriptorsForLiteralArguments(@NotNull PsiExpression[] callArguments,
@NotNull PsiParameter[] parameters,
@NotNull JavaResolveResult resolveResult) {
List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();
int i = 0;
while (i < myCallArguments.length) {
if (i + 1 < myCallArguments.length && isCommonlyNamedParameterPair(i, i + 1)) {
while (i < callArguments.length && i < parameters.length) {
if (i + 1 < callArguments.length && isCommonlyNamedParameterPair(i, i + 1, parameters)) {
i += 2;
continue;
}
if (shouldInlineParameterName(i)) {
descriptors.add(createFoldingDescriptor(myCallArguments[i], myParameters[i]));
if (!(parameters[i].getType() instanceof PsiEllipsisType) && shouldInlineParameterName(i, callArguments, parameters, resolveResult)) {
descriptors.add(createFoldingDescriptor(callArguments[i], parameters[i]));
}
i++;
}
@@ -112,16 +112,17 @@ public class ParameterNameFoldingManager {
@NotNull
private static NamedFoldingDescriptor createFoldingDescriptor(@NotNull PsiExpression callArgument, @NotNull PsiParameter methodParam) {
TextRange range = callArgument.getTextRange();
String placeholderText = methodParam.getName() + ": " + callArgument.getText();
return new NamedFoldingDescriptor(callArgument, range.getStartOffset(), range.getEndOffset(), null, placeholderText);
PsiElement lParenOrCommaOrWhitespaceOrComment = callArgument.getPrevSibling();
TextRange range = lParenOrCommaOrWhitespaceOrComment.getTextRange();
String placeholderText = StringUtil.last(lParenOrCommaOrWhitespaceOrComment.getText(), 1, false) + methodParam.getName() + ": ";
return new NamedFoldingDescriptor(callArgument, range.getEndOffset()-1, range.getEndOffset(), null, placeholderText);
}
private boolean isCommonlyNamedParameterPair(int first, int second) {
assert first < myParameters.length && second < myParameters.length;
private static boolean isCommonlyNamedParameterPair(int first, int second, PsiParameter[] parameters) {
if (!(first < parameters.length && second < parameters.length)) return false;
String firstParamName = myParameters[first].getName();
String secondParamName = myParameters[second].getName();
String firstParamName = parameters[first].getName();
String secondParamName = parameters[second].getName();
if (firstParamName == null || secondParamName == null) return false;
for (Couple<String> knownPair : COMMONLY_USED_PARAMETER_PAIR) {
@@ -134,13 +135,18 @@ public class ParameterNameFoldingManager {
return false;
}
private boolean shouldInlineParameterName(int paramIndex) {
PsiExpression argument = myCallArguments[paramIndex];
private static boolean shouldInlineParameterName(int paramIndex,
@NotNull PsiExpression[] callArguments,
@NotNull PsiParameter[] parameters,
@NotNull JavaResolveResult resolveResult) {
PsiExpression argument = callArguments[paramIndex];
if (isLiteralExpression(argument) && argument.getType() != null) {
PsiParameter parameter = myParameters[paramIndex];
PsiParameter parameter = parameters[paramIndex];
String paramName = parameter.getName();
if (paramName != null && paramName.length() >= MIN_NAME_LENGTH_THRESHOLD) {
return TypeConversionUtil.isAssignable(parameter.getType(), argument.getType());
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
if (paramName != null && paramName.length() >= settings.getInlineLiteralParameterMinNameLength()) {
PsiType parameterType = resolveResult.getSubstitutor().substitute(parameter.getType());
return TypeConversionUtil.isAssignable(parameterType, argument.getType());
}
}
return false;
@@ -31,7 +31,6 @@ 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.PsiLiteralExpression
import com.intellij.psi.PsiMethod
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.EditorTestUtil
@@ -687,15 +686,13 @@ class Test {
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 9
def literals = fooClass.methods[0].body.statements[6].children[0].children[1].children.findAll { it instanceof PsiLiteralExpression }
def parameters = fooClass.methods[1].parameterList.parameters
for (int i = 0; i < literals.size(); i++) {
def currentElement = literals[i]
def correspondingFolding = regions[i + 1]
assert correspondingFolding.startOffset == currentElement.textRange.startOffset && correspondingFolding.endOffset == currentElement.textRange.endOffset
assert correspondingFolding.placeholderText == parameters[i].name + ": " + currentElement.text
}
checkTheFoldingStartsRightBefore(regions[1], text, "(testNow: ", "true")
checkTheFoldingStartsRightBefore(regions[2], text, " shouldIgnoreRoots: ", "false")
checkTheFoldingStartsRightBefore(regions[3], text, " times: ", "555")
checkTheFoldingStartsRightBefore(regions[4], text, " pii: ", "3.141f")
checkTheFoldingStartsRightBefore(regions[5], text, " title: ", '"Huge Title"')
checkTheFoldingStartsRightBefore(regions[6], text, " terminate: ", "'c'")
checkTheFoldingStartsRightBefore(regions[7], text, " file: ", "null")
}
public void "test do not inline name if setter"() {
@@ -738,8 +735,7 @@ public class VarArgTest {
configure text
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 3
checkRangeOffsetByPositionInText(regions[1], text, "13")
assert regions[1].placeholderText == "test: 13"
checkTheFoldingStartsRightBefore(regions[1], text, "(test: ", "13")
}
public void "test do not inline if parameter length is one or two"() {
@@ -857,14 +853,11 @@ public class CharSymbol {
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 5
checkRangeOffsetByPositionInText(regions[1], text, "100")
assert regions[1].placeholderText == "test: 100"
checkTheFoldingStartsRightBefore(regions[1], text, "(test: ", "100")
checkRangeOffsetByPositionInText(regions[2], text, "false")
assert regions[2].placeholderText == "boo: false"
checkTheFoldingStartsRightBefore(regions[2], text, " boo: ", "false")
checkRangeOffsetByPositionInText(regions[3], text, '"Hi!"')
assert regions[3].placeholderText == 'seq: "Hi!"'
checkTheFoldingStartsRightBefore(regions[3], text, " seq: ", '"Hi!"')
}
public void "test inline negative and positive numbers"() {
@@ -890,11 +883,53 @@ public class CharSymbol {
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.size() == 4
checkRangeOffsetByPositionInText(regions[1], text, "-1")
assert regions[1].placeholderText == "test: -1"
checkTheFoldingStartsRightBefore(regions[1], text, "(test: ", "-1")
checkTheFoldingStartsRightBefore(regions[2], text, "(test: ", "+1")
}
checkRangeOffsetByPositionInText(regions[2], text, "+1")
assert regions[2].placeholderText == "test: +1"
public void "test inline literal arguments with crazy settings"() {
myFoldingSettings.setInlineParameterNamesForLiteralCallArguments(true);
myFoldingSettings.setInlineLiteralParameterMinArgumentsToFold(1);
myFoldingSettings.setInlineLiteralParameterMinNameLength(1);
@Language("JAVA")
def text = """
public class Test {
public void main(boolean isActive, boolean requestFocus, int xoo) {
System.out.println("AAA");
main(true,false, /*comment*/2);
}
}
"""
configure text
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
checkTheFoldingStartsRightBefore(regions[1], text, "(x: ", '"AAA"')
checkTheFoldingStartsRightBefore(regions[2], text, "(isActive: ", "true")
checkTheFoldingStartsRightBefore(regions[3], text, ",requestFocus: ", "false")
checkTheFoldingStartsRightBefore(regions[4], text, "/xoo: ", "2")
}
public void "test inline literal arguments with generics"() {
myFoldingSettings.setInlineParameterNamesForLiteralCallArguments(true);
myFoldingSettings.setInlineLiteralParameterMinArgumentsToFold(1);
myFoldingSettings.setInlineLiteralParameterMinNameLength(1);
@Language("JAVA")
def text = """
import java.util.*;
public class Test {
public void main(Comparator<Integer> c, List<String> l) {
c.compare(0, /** ddd */3);
l.add(1, "uuu");
}
}
"""
configure text
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
checkTheFoldingStartsRightBefore(regions[1], text, "(o1: ", '0')
checkTheFoldingStartsRightBefore(regions[2], text, "/o2: ", "3")
checkTheFoldingStartsRightBefore(regions[3], text, "(index: ", "1")
checkTheFoldingStartsRightBefore(regions[4], text, " element: ", '"uuu"')
}
public void "test inline constructor literal arguments names"() {
@@ -922,11 +957,14 @@ public class Test {
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.length == 6
assert regions[1].placeholderText == "isActive: true"
assert regions[2].placeholderText == "requestFocus: false"
checkTheFoldingStartsRightBefore(regions[1], text, "(isActive: ", "true")
checkTheFoldingStartsRightBefore(regions[2], text, " requestFocus: ", "false")
}
checkRangeOffsetByPositionInText(regions[1], text, "true")
checkRangeOffsetByPositionInText(regions[2], text, "false")
private static def checkTheFoldingStartsRightBefore(FoldRegion region, String fileText, String placeHolder, String fileTextAfterFold) {
assert region.endOffset == fileText.indexOf(fileTextAfterFold)
assert region.startOffset == region.endOffset - 1
assert region.placeholderText == placeHolder : "expected placeholder text: "+placeHolder+"; but got: "+region.placeholderText
}
public void "test inline anonymous class constructor literal arguments names"() {
@@ -951,18 +989,10 @@ public class Test {
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
assert regions.length == 4
assert regions[2].placeholderText == "counter: 10"
assert regions[3].placeholderText == "shouldTest: false"
checkRangeOffsetByPositionInText(regions[2], text, "10")
checkRangeOffsetByPositionInText(regions[3], text, "false")
checkTheFoldingStartsRightBefore(regions[2], text, "(counter: ", "10")
checkTheFoldingStartsRightBefore(regions[3], text, " shouldTest: ", "false")
}
private static def checkRangeOffsetByPositionInText(FoldRegion region, String text, String foldElement) {
assert region.startOffset == text.indexOf(foldElement) && region.endOffset == text.indexOf(foldElement) + foldElement.length()
}
private def changeFoldRegions(Closure op) {
myFixture.editor.foldingModel.runBatchFoldingOperationDoNotCollapseCaret(op)
}
@@ -16,6 +16,8 @@
package com.intellij.openapi.options;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Setter;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -48,26 +50,27 @@ public abstract class BeanConfigurable<T> implements UnnamedConfigurable {
return myComponent;
}
@NotNull
abstract T createComponent();
boolean isModified(Object instance) {
boolean isModified(@NotNull Object instance) {
final Object componentValue = getComponentValue();
final Object beanValue = getBeanValue(instance);
return !Comparing.equal(componentValue, beanValue);
}
void apply(Object instance) {
void apply(@NotNull Object instance) {
setBeanValue(instance, getComponentValue());
}
void reset(Object instance) {
void reset(@NotNull Object instance) {
setComponentValue(getBeanValue(instance));
}
abstract Object getComponentValue();
abstract void setComponentValue(Object value);
Object getBeanValue(Object instance) {
Object getBeanValue(@NotNull Object instance) {
try {
Field field = instance.getClass().getField(myFieldName);
return field.get(instance);
@@ -121,6 +124,7 @@ public abstract class BeanConfigurable<T> implements UnnamedConfigurable {
myTitle = title;
}
@NotNull
@Override
JCheckBox createComponent() {
return new JCheckBox(myTitle);
@@ -153,14 +157,81 @@ public abstract class BeanConfigurable<T> implements UnnamedConfigurable {
myInstance = beanInstance;
}
@NotNull
protected T getInstance() {
return myInstance;
}
/**
* @deprecated use {@link #checkBox(String, Getter, Setter)} instead
*/
protected void checkBox(@NonNls String fieldName, String title) {
myFields.add(new CheckboxField(fieldName, title));
}
/**
* Adds check box with given {@code title}.
* Initial checkbox value is obtained from {@code getter}.
* After the apply, the value from the check box is written back to model via {@code setter}.
*/
protected void checkBox(@NotNull String title, @NotNull Getter<Boolean> getter, @NotNull Setter<Boolean> setter) {
CheckboxField field = new CheckboxField("", title) {
@Override
Object getBeanValue(@NotNull Object instance) {
return getter.get();
}
@Override
void setBeanValue(Object instance, Object value) {
setter.set((Boolean)value);
}
};
myFields.add(field);
}
/**
* Adds custom component (e.g. edit box).
* Initial value is obtained from {@code beanGetter} and applied to the component via {@code componentSetter}.
* E.g. text is read from the model and set to the edit box.
* After the apply, the value from the component is queried via {@code componentGetter} and written back to model via {@code beanSetter}.
* E.g. text from the edit box is queried and saved back to model bean.
*/
protected <V> void component(@NotNull JComponent component, @NotNull Getter<V> beanGetter, @NotNull Setter<V> beanSetter, @NotNull Getter<V> componentGetter, @NotNull Setter<V> componentSetter) {
BeanField<JComponent> field = new BeanField<JComponent>("") {
@NotNull
@Override
JComponent createComponent() {
return component;
}
@Override
Object getComponentValue() {
return componentGetter.get();
}
@Override
void setComponentValue(Object value) {
componentSetter.set((V)value);
}
@Override
protected Class getValueClass() {
return null;
}
@Override
Object getBeanValue(@NotNull Object instance) {
return beanGetter.get();
}
@Override
void setBeanValue(Object instance, Object value) {
beanSetter.set((V)value);
}
};
myFields.add(field);
}
@Override
public JComponent createComponent() {
final JPanel panel = new JPanel(new GridLayout(myFields.size(), 1));
@@ -6,5 +6,8 @@
<item name="com.intellij.openapi.util.Getter">
<annotation name="java.lang.FunctionalInterface" />
</item>
<item name="com.intellij.openapi.util.Setter">
<annotation name="java.lang.FunctionalInterface" />
</item>
</root>
@@ -0,0 +1,20 @@
/*
* Copyright 2000-2016 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.openapi.util;
public interface Setter<T> {
void set(T value);
}