IDEA-170039 Honor new foldings 'collapse by default' state - implement setting changes tracking for Java and XML

This commit is contained in:
Dmitry Batrak
2017-04-10 10:25:51 +03:00
parent ae251d56bb
commit a031e42f20
7 changed files with 97 additions and 41 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -29,7 +29,6 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -50,7 +49,8 @@ public class SuppressWarningsFoldingBuilder extends FoldingBuilderEx {
@Override
public void visitAnnotation(PsiAnnotation annotation) {
if (Comparing.strEqual(annotation.getQualifiedName(), SuppressWarnings.class.getName())) {
result.add(new FoldingDescriptor(annotation, annotation.getTextRange()));
result.add(new FoldingDescriptor(annotation, annotation.getTextRange(),
JavaCodeFoldingSettings.getInstance().getCollapseSuppressWarningsProperty()));
}
super.visitAnnotation(annotation);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* 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.
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.folding.impl;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.lang.folding.NamedFoldingDescriptor;
import com.intellij.openapi.editor.Document;
@@ -24,7 +25,7 @@ import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.BooleanTrackableProperty;
import com.intellij.util.ObjectUtils;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -127,10 +128,11 @@ class ClosureFolding {
if (rangeStart >= rangeEnd) return null;
FoldingGroup group = FoldingGroup.newGroup("lambda");
BooleanTrackableProperty collapseSetting = JavaCodeFoldingSettings.getInstance().getCollapseLambdasProperty();
List<NamedFoldingDescriptor> foldElements = new ArrayList<>();
foldElements.add(new NamedFoldingDescriptor(myNewExpression, getClosureStartOffset(), rangeStart, group, header));
foldElements.add(new NamedFoldingDescriptor(myNewExpression, getClosureStartOffset(), rangeStart, group, header, collapseSetting));
if (rangeEnd + 1 < getClosureEndOffset()) {
foldElements.add(new NamedFoldingDescriptor(classRBrace, rangeEnd, getClosureEndOffset(), group, footer));
foldElements.add(new NamedFoldingDescriptor(classRBrace, rangeEnd, getClosureEndOffset(), group, footer, collapseSetting));
}
return foldElements;
}
@@ -43,6 +43,7 @@ import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.BooleanTrackableProperty;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -230,7 +231,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
for (int i = 0; i < children.length; i++) {
PsiElement child = children[i];
if (child instanceof PsiAnnotation) {
addToFold(foldElements, child, document, false);
addToFold(foldElements, child, document, false,
JavaCodeFoldingSettings.getInstance().getCollapseAnnotationsProperty());
int j;
for (j = i + 1; j < children.length; j++) {
PsiElement nextChild = children[j];
@@ -289,7 +291,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
if (end != null && !containsCustomRegionMarker) {
foldElements.add(
new FoldingDescriptor(comment, new TextRange(comment.getTextRange().getStartOffset(), end.getTextRange().getEndOffset()))
new FoldingDescriptor(comment, new TextRange(comment.getTextRange().getStartOffset(), end.getTextRange().getEndOffset()),
JavaCodeFoldingSettings.getInstance().getCollapseEndOfLineCommentsProperty())
);
}
}
@@ -396,7 +399,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
final String text = list.getText();
if (text.startsWith("<") && text.endsWith(">") && text.length() > ifLongerThan) {
final TextRange range = list.getTextRange();
addFoldRegion(foldElements, list, document, true, range);
addFoldRegion(foldElements, list, document, true, range,
JavaCodeFoldingSettings.getInstance().getCollapseConstructorGenericParametersProperty());
}
}
@@ -405,17 +409,19 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
private static boolean addToFold(@NotNull List<FoldingDescriptor> list,
@NotNull PsiElement elementToFold,
@NotNull Document document,
boolean allowOneLiners) {
boolean allowOneLiners,
@Nullable BooleanTrackableProperty dependency) {
PsiUtilCore.ensureValid(elementToFold);
TextRange range = getRangeToFold(elementToFold);
return range != null && addFoldRegion(list, elementToFold, document, allowOneLiners, range);
return range != null && addFoldRegion(list, elementToFold, document, allowOneLiners, range, dependency);
}
private static boolean addFoldRegion(@NotNull List<FoldingDescriptor> list,
@NotNull PsiElement elementToFold,
@NotNull Document document,
boolean allowOneLiners,
@NotNull TextRange range) {
@NotNull TextRange range,
@Nullable BooleanTrackableProperty dependency) {
final TextRange fileRange = elementToFold.getContainingFile().getTextRange();
if (range.equals(fileRange)) return false;
@@ -428,14 +434,14 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
int startLine = document.getLineNumber(range.getStartOffset());
int endLine = document.getLineNumber(range.getEndOffset() - 1);
if (startLine < endLine && range.getLength() > 1) {
list.add(new FoldingDescriptor(elementToFold, range));
list.add(new FoldingDescriptor(elementToFold, range, dependency));
return true;
}
return false;
}
else {
if (range.getLength() > getPlaceholderText(elementToFold).length()) {
list.add(new FoldingDescriptor(elementToFold, range));
list.add(new FoldingDescriptor(elementToFold, range, dependency));
return true;
}
return false;
@@ -451,6 +457,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
return;
}
PsiJavaFile file = (PsiJavaFile) root;
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
PsiImportList importList = file.getImportList();
if (importList != null) {
@@ -458,7 +465,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
if (statements.length > 1) {
final TextRange rangeToFold = getRangeToFold(importList);
if (rangeToFold != null && rangeToFold.getLength() > 1) {
FoldingDescriptor descriptor = new FoldingDescriptor(importList, rangeToFold);
FoldingDescriptor descriptor = new FoldingDescriptor(importList, rangeToFold, settings.getCollapseImportsProperty());
// imports are often added/removed automatically, so we enable autoupdate of folded region for foldings even if it's collapsed
descriptor.setCanBeRemovedWhenCollapsed(true);
descriptors.add(descriptor);
@@ -491,7 +498,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
anchorElementToUse = candidate;
}
}
descriptors.add(new FoldingDescriptor(anchorElementToUse, range));
descriptors.add(new FoldingDescriptor(anchorElementToUse, range, settings.getCollapseFileHeaderProperty()));
}
}
@@ -500,15 +507,21 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
@NotNull Document document,
boolean foldJavaDocs,
boolean quick) {
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
if (!(aClass.getParent() instanceof PsiJavaFile) || ((PsiJavaFile)aClass.getParent()).getClasses().length > 1) {
addToFold(list, aClass, document, true);
addToFold(list, aClass, document, true,
aClass.getParent() instanceof PsiFile ? null
: aClass instanceof PsiAnonymousClass
? settings.getCollapseAnonymousClassesProperty()
: settings.getCollapseInnerClassesProperty());
}
PsiDocComment docComment;
if (foldJavaDocs) {
docComment = aClass.getDocComment();
if (docComment != null) {
addToFold(list, docComment, document, true);
addToFold(list, docComment, document, true, settings.getCollapseJavadocsProperty());
}
}
addAnnotationsToFold(aClass.getModifierList(), list, document);
@@ -522,14 +535,16 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
PsiMethod method = (PsiMethod)child;
boolean oneLiner = addOneLineMethodFolding(list, method);
if (!oneLiner) {
addToFold(list, method, document, true);
addToFold(list, method, document, true, isSimplePropertyAccessor(method)
? settings.getCollapseAccessorsProperty()
: settings.getCollapseMethodsProperty());
}
addAnnotationsToFold(method.getModifierList(), list, document);
if (foldJavaDocs) {
docComment = method.getDocComment();
if (docComment != null) {
addToFold(list, docComment, document, true);
addToFold(list, docComment, document, true, settings.getCollapseJavadocsProperty());
}
}
@@ -543,7 +558,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
if (foldJavaDocs) {
docComment = field.getDocComment();
if (docComment != null) {
addToFold(list, docComment, document, true);
addToFold(list, docComment, document, true, settings.getCollapseJavadocsProperty());
}
}
addAnnotationsToFold(field.getModifierList(), list, document);
@@ -556,7 +571,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
else if (child instanceof PsiClassInitializer) {
PsiClassInitializer initializer = (PsiClassInitializer)child;
addToFold(list, initializer, document, true);
addToFold(list, initializer, document, true, settings.getCollapseMethodsProperty());
addCodeBlockFolds(initializer, list, processedComments, document, quick);
}
else if (child instanceof PsiClass) {
@@ -569,7 +584,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
private boolean addOneLineMethodFolding(@NotNull List<FoldingDescriptor> descriptorList, @NotNull PsiMethod method) {
if (!JavaCodeFoldingSettings.getInstance().isCollapseOneLineMethods()) {
JavaCodeFoldingSettings settings = JavaCodeFoldingSettings.getInstance();
if (!settings.isCollapseOneLineMethods()) {
return false;
}
@@ -621,8 +637,9 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
}
FoldingGroup group = FoldingGroup.newGroup("one-liner");
descriptorList.add(new NamedFoldingDescriptor(lBrace, leftStart, leftEnd, group, leftText));
descriptorList.add(new NamedFoldingDescriptor(rBrace, rightStart, rightEnd, group, rightText));
BooleanTrackableProperty collapseSetting = settings.getCollapseOneLineMethodsProperty();
descriptorList.add(new NamedFoldingDescriptor(lBrace, leftStart, leftEnd, group, leftText, collapseSetting));
descriptorList.add(new NamedFoldingDescriptor(rBrace, rightStart, rightEnd, group, rightText, collapseSetting));
return true;
}
@@ -714,7 +731,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
@Override
public void visitClass(PsiClass aClass) {
if (dumb || !addClosureFolding(aClass, document, foldElements, processedComments, quick)) {
addToFold(foldElements, aClass, document, true);
addToFold(foldElements, aClass, document, true,
JavaCodeFoldingSettings.getInstance().getCollapseAnonymousClassesProperty());
addElementsToFold(foldElements, aClass, document, false, quick);
}
}
@@ -741,7 +759,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
public void visitLambdaExpression(PsiLambdaExpression expression) {
PsiElement body = expression.getBody();
if (body instanceof PsiCodeBlock) {
addToFold(foldElements, expression, document, true);
addToFold(foldElements, expression, document, true,
JavaCodeFoldingSettings.getInstance().getCollapseAnonymousClassesProperty());
}
super.visitLambdaExpression(expression);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* 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.
@@ -55,10 +55,19 @@ public class FoldingDescriptor {
this(node, range, null);
}
public FoldingDescriptor(@NotNull ASTNode node, @NotNull TextRange range, @Nullable Object dependency) {
this(node, range, null, dependency);
}
public FoldingDescriptor(@NotNull PsiElement element, @NotNull TextRange range) {
this(ObjectUtils.assertNotNull(element.getNode()), range, null);
}
public FoldingDescriptor(@NotNull PsiElement element, @NotNull TextRange range, @Nullable Object dependency) {
this(ObjectUtils.assertNotNull(element.getNode()), range, null,
dependency == null ? Collections.<Object>emptySet() : Collections.singleton(dependency));
}
/**
* Creates a folding region related to the specified AST node and covering the specified
* text range.
@@ -72,6 +81,10 @@ public class FoldingDescriptor {
this(node, range, group, Collections.<Object>emptySet());
}
public FoldingDescriptor(@NotNull ASTNode node, @NotNull TextRange range, @Nullable FoldingGroup group, @Nullable Object dependency) {
this(node, range, group, dependency == null ? Collections.<Object>emptySet() : Collections.singleton(dependency));
}
/**
* Creates a folding region related to the specified AST node and covering the specified
* text range.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -29,6 +29,11 @@ public class NamedFoldingDescriptor extends FoldingDescriptor {
this(e.getNode(), new TextRange(start, end), group, placeholderText);
}
public NamedFoldingDescriptor(@NotNull PsiElement e, int start, int end, @Nullable FoldingGroup group, @NotNull String placeholderText,
@Nullable Object dependency) {
this(e.getNode(), new TextRange(start, end), group, placeholderText, dependency);
}
public NamedFoldingDescriptor(@NotNull ASTNode node, int start, int end, @Nullable FoldingGroup group, @NotNull String placeholderText) {
this(node, new TextRange(start, end), group, placeholderText);
}
@@ -37,7 +42,15 @@ public class NamedFoldingDescriptor extends FoldingDescriptor {
@NotNull final TextRange range,
@Nullable FoldingGroup group,
@NotNull String placeholderText) {
super(node, range, group);
this(node, range, group, placeholderText, null);
}
public NamedFoldingDescriptor(@NotNull ASTNode node,
@NotNull final TextRange range,
@Nullable FoldingGroup group,
@NotNull String placeholderText,
@Nullable Object dependency) {
super(node, range, group, dependency);
myPlaceholderText = placeholderText;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* 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.
@@ -81,6 +81,7 @@ public class PropertyFoldingBuilder extends FoldingBuilderEx {
if (isI18nProperty(expression)) {
final IProperty property = getI18nProperty(expression);
final HashSet<Object> set = new HashSet<>();
set.add(JavaCodeFoldingSettings.getInstance().getCollapseI18nMessagesProperty());
set.add(property != null ? property : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
final String msg = formatI18nProperty(expression, property);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* 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.
@@ -34,6 +34,7 @@ import com.intellij.psi.impl.source.xml.XmlTokenImpl;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.xml.*;
import com.intellij.util.BooleanTrackableProperty;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.URLUtil;
import com.intellij.xml.util.HtmlUtil;
@@ -212,7 +213,14 @@ public abstract class XmlCodeFoldingBuilder extends CustomFoldingBuilder impleme
final boolean entity = isEntity(elementToFold);
if (startLine < endLine || elementToFold instanceof XmlAttribute || entity) {
if (range.getStartOffset() + MIN_TEXT_RANGE_LENGTH < range.getEndOffset() || entity) {
foldings.add(new FoldingDescriptor(elementToFold.getNode(), range));
XmlCodeFoldingSettings settings = getFoldingSettings();
BooleanTrackableProperty dependency =
elementToFold instanceof XmlTag ? settings.getCollapseXmlTagsProperty() :
elementToFold instanceof XmlAttribute ?
(isSrcAttribute((XmlAttribute)elementToFold) ? settings.getCollapseDataUriProperty()
: isStyleAttribute((XmlAttribute)elementToFold) ? settings.getCollapseHtmlStyleAttributeProperty() : null) :
isEntity(elementToFold) ? settings.getCollapseEntitiesProperty() : null;
foldings.add(new FoldingDescriptor(elementToFold.getNode(), range, dependency));
return true;
}
}
@@ -269,16 +277,17 @@ public abstract class XmlCodeFoldingBuilder extends CustomFoldingBuilder impleme
final PsiElement psi = node.getPsi();
final XmlCodeFoldingSettings foldingSettings = getFoldingSettings();
return (psi instanceof XmlTag && foldingSettings.isCollapseXmlTags())
|| (psi instanceof XmlAttribute && (foldStyle((XmlAttribute)psi, foldingSettings) || foldSrc((XmlAttribute)psi, foldingSettings)))
|| (psi instanceof XmlAttribute && (foldingSettings.isCollapseHtmlStyleAttribute() && isStyleAttribute((XmlAttribute)psi) ||
foldingSettings.isCollapseDataUri() && isSrcAttribute((XmlAttribute)psi)))
|| isEntity(psi) && foldingSettings.isCollapseEntities() && getEntityPlaceholder(psi) != null;
}
private static boolean foldSrc(XmlAttribute psi, XmlCodeFoldingSettings settings) {
return settings.isCollapseDataUri() && "src".equals(psi.getName());
private static boolean isSrcAttribute(XmlAttribute psi) {
return "src".equals(psi.getName());
}
private static boolean foldStyle(XmlAttribute psi, XmlCodeFoldingSettings settings) {
return settings.isCollapseHtmlStyleAttribute() && HtmlUtil.STYLE_ATTRIBUTE_NAME.equalsIgnoreCase(psi.getName());
private static boolean isStyleAttribute(XmlAttribute psi) {
return HtmlUtil.STYLE_ATTRIBUTE_NAME.equalsIgnoreCase(psi.getName());
}
protected boolean isEntity(PsiElement psi) {
@@ -288,8 +297,7 @@ public abstract class XmlCodeFoldingBuilder extends CustomFoldingBuilder impleme
private static boolean isAttributeShouldBeFolded(XmlAttribute child) {
return HtmlUtil.isHtmlFile(child.getContainingFile()) &&
(HtmlUtil.STYLE_ATTRIBUTE_NAME.equalsIgnoreCase(child.getName()) ||
"src".equals(child.getName()) && child.getValue() != null && URLUtil.isDataUri(child.getValue()));
(isStyleAttribute(child) || isSrcAttribute(child) && child.getValue() != null && URLUtil.isDataUri(child.getValue()));
}
protected abstract XmlCodeFoldingSettings getFoldingSettings();