mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-87639 Add a possibility to specify a dependent LF spacing if a checked range does NOT have line feeds.
1. API changes - DependentSpacingRule allows to define properties to use on dependent change trigger; 2. Corresponding changes have been made to the formatter core;
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.formatting;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds settings that should be used if
|
||||
* {@link Spacing#createDependentLFSpacing(int, int, TextRange, boolean, int, DependentSpacingRule) dependent spacing}
|
||||
* target region changes its 'contains line feeds' status.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 6/28/12 1:08 PM
|
||||
*/
|
||||
public class DependentSpacingRule {
|
||||
|
||||
enum Anchor {
|
||||
MIN_LINE_FEEDS, MAX_LINE_FEEDS
|
||||
}
|
||||
|
||||
enum Trigger {
|
||||
HAS_LINE_FEEDS, DOES_NOT_HAVE_LINE_FEEDS
|
||||
}
|
||||
|
||||
public static final DependentSpacingRule DEFAULT = new DependentSpacingRule(Trigger.HAS_LINE_FEEDS).registerData(Anchor.MIN_LINE_FEEDS, 1);
|
||||
|
||||
private final Map<Anchor, Object> myData = new HashMap<Anchor, Object>();
|
||||
|
||||
@NotNull private final Trigger myTrigger;
|
||||
|
||||
public DependentSpacingRule(@NotNull Trigger trigger) {
|
||||
myTrigger = trigger;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Trigger getTrigger() {
|
||||
return myTrigger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to register given data for the given anchor within the current rule.
|
||||
*
|
||||
* @param anchor target anchor
|
||||
* @param data data to register for the given anchor
|
||||
* @param <T> data's type
|
||||
* @see #getData(Anchor)
|
||||
*/
|
||||
public <T> DependentSpacingRule registerData(@NotNull Anchor anchor, @NotNull T data) {
|
||||
myData.put(anchor, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anchor target data anchor
|
||||
* @return <code>true</code> if there is a data registered for the given anchor within the current rule;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean hasData(@NotNull Anchor anchor) {
|
||||
return myData.containsKey(anchor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to retrieve data associated with the given anchor.
|
||||
*
|
||||
* @param anchor target anchor
|
||||
* @param <T> data's type
|
||||
* @return data associated for the given anchor
|
||||
* @throws IllegalArgumentException if no data is registered for the given anchor
|
||||
* (use {@link #hasData(Anchor)} for the preliminary examination)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getData(@NotNull Anchor anchor) throws IllegalArgumentException {
|
||||
if (!myData.containsKey(anchor)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"No data is registered for the dependent spacing rule %s. Registered: %s", anchor, myData
|
||||
));
|
||||
}
|
||||
return (T)myData.get(anchor);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The spacing setting for a formatting model block. Indicates the number of spaces and/or
|
||||
@@ -100,19 +101,50 @@ public abstract class Spacing {
|
||||
* to which the spacing setting instance is related, or <code>Integer.MAX_VALUE</code>
|
||||
* if the number of spaces is not limited. Spaces are deleted if there are
|
||||
* more than this amount of spaces in the document.
|
||||
* @param dependance The text range checked for the presense of line breaks.
|
||||
* @param dependency The text range checked for the presence of line breaks.
|
||||
* @param keepLineBreaks Whether the existing line breaks between the blocks should be preserved.
|
||||
* @param keepBlankLines Whether the existing blank lines between the blocks should be preserved.
|
||||
* @return the spacing setting instance.
|
||||
*/
|
||||
public static Spacing createDependentLFSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
TextRange dependance,
|
||||
TextRange dependency,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines) {
|
||||
return myFactory.createDependentLFSpacing(minSpaces, maxSpaces, dependance, keepLineBreaks, keepBlankLines);
|
||||
int keepBlankLines)
|
||||
{
|
||||
return createDependentLFSpacing(minSpaces, maxSpaces, dependency, keepLineBreaks, keepBlankLines, DependentSpacingRule.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spacing setting instance which uses settings from the given dependent spacing rule if the specified text range changes
|
||||
* its 'has line feed' status during formatting (new line feed is added and the range hasn't contained them before
|
||||
* or it contained line feed(s) and it was removed during formatting).
|
||||
* <p/>
|
||||
* Used for formatting rules like the "next line if wrapped" brace placement.
|
||||
*
|
||||
* @param minSpaces The minimum number of spaces that should be present between the blocks
|
||||
* to which the spacing setting instance is related. Spaces are inserted
|
||||
* if there are less than this amount of spaces in the document.
|
||||
* @param maxSpaces The maximum number of spaces that should be present between the blocks
|
||||
* to which the spacing setting instance is related, or <code>Integer.MAX_VALUE</code>
|
||||
* if the number of spaces is not limited. Spaces are deleted if there are
|
||||
* more than this amount of spaces in the document.
|
||||
* @param dependencyRange The text range checked for the presence of line breaks.
|
||||
* @param keepLineBreaks Whether the existing line breaks between the blocks should be preserved.
|
||||
* @param keepBlankLines Whether the existing blank lines between the blocks should be preserved.
|
||||
* @param rule settings to use if dependent region changes its 'contains line feed' status during formatting
|
||||
* @return the spacing setting instance for the given parameters
|
||||
*/
|
||||
public static Spacing createDependentLFSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
@NotNull TextRange dependencyRange,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines,
|
||||
@NotNull DependentSpacingRule rule)
|
||||
{
|
||||
return myFactory.createDependentLFSpacing(minSpaces, maxSpaces, dependencyRange, keepLineBreaks, keepBlankLines, rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spacing setting instance which preserves the presence of spaces between the blocks but,
|
||||
* if spaces are present, may insert or delete the spaces. Used, for example, for HTML formatting
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,34 +16,43 @@
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Internal interface for creating spacing instances.
|
||||
*/
|
||||
|
||||
interface SpacingFactory {
|
||||
public Spacing createSpacing(int minSpaces,
|
||||
|
||||
@NotNull
|
||||
Spacing createSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
int minLineFeeds,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines);
|
||||
|
||||
public Spacing getReadOnlySpacing();
|
||||
@NotNull
|
||||
Spacing getReadOnlySpacing();
|
||||
|
||||
@NotNull
|
||||
Spacing createDependentLFSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
@NotNull TextRange dependencyRange,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines,
|
||||
@NotNull DependentSpacingRule rule);
|
||||
|
||||
public Spacing createDependentLFSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
TextRange dependance,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines);
|
||||
@NotNull
|
||||
Spacing createSafeSpacing(boolean keepLineBreaks,
|
||||
int keepBlankLines);
|
||||
|
||||
public Spacing createSafeSpacing(boolean keepLineBreaks,
|
||||
int keepBlankLines);
|
||||
|
||||
public Spacing createKeepingFirstColumnSpacing(final int minSpaces,
|
||||
final int maxSpaces,
|
||||
final boolean keepLineBreaks,
|
||||
final int keepBlankLines);
|
||||
@NotNull
|
||||
Spacing createKeepingFirstColumnSpacing(final int minSpaces,
|
||||
final int maxSpaces,
|
||||
final boolean keepLineBreaks,
|
||||
final int keepBlankLines);
|
||||
|
||||
@NotNull
|
||||
Spacing createSpacing(final int minSpaces, final int maxSpaces, final int minLineFeeds, final boolean keepLineBreaks,
|
||||
final int keepBlankLines, final int prefLineFeeds);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.intellij.formatting;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Extends {@link SpacingImpl} in order to add notion of dependency range.
|
||||
@@ -24,29 +25,50 @@ import com.intellij.openapi.util.TextRange;
|
||||
* <code>'Dependency'</code> here affect {@link #getMinLineFeeds() minLineFieeds} property value. See property contract for more details.
|
||||
*/
|
||||
public class DependantSpacingImpl extends SpacingImpl {
|
||||
private final TextRange myDependency;
|
||||
private static final int DEPENDENCE_CONTAINS_LF_MASK = 0x10;
|
||||
private static final int DEPENDENCE_CONTAINS_LF_MASK = 0x10;
|
||||
private static final int DEPENDENT_REGION_LF_CHANGED_MASK = 0x20;
|
||||
|
||||
@NotNull private final TextRange myDependency;
|
||||
@NotNull private final DependentSpacingRule myRule;
|
||||
|
||||
|
||||
public DependantSpacingImpl(final int minSpaces,
|
||||
final int maxSpaces,
|
||||
TextRange dependency,
|
||||
@NotNull TextRange dependency,
|
||||
final boolean keepLineBreaks,
|
||||
final int keepBlankLines) {
|
||||
final int keepBlankLines,
|
||||
@NotNull DependentSpacingRule rule)
|
||||
{
|
||||
super(minSpaces, maxSpaces, 0, false, false, keepLineBreaks, keepBlankLines, false, 0);
|
||||
myDependency = dependency;
|
||||
myRule = rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>1</code> if dependency has line feeds; <code>0</code> otherwise
|
||||
*/
|
||||
public int getMinLineFeeds() {
|
||||
if ((myFlags & DEPENDENCE_CONTAINS_LF_MASK) != 0) {
|
||||
return 1;
|
||||
if (!isTriggered()) {
|
||||
return super.getMinLineFeeds();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
|
||||
if (myRule.hasData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS)) {
|
||||
return myRule.getData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS);
|
||||
}
|
||||
|
||||
if (myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) {
|
||||
return myRule.getData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS);
|
||||
}
|
||||
return super.getMinLineFeeds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKeepBlankLines() {
|
||||
if (!isTriggered() || !myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) {
|
||||
return super.getKeepBlankLines();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void refresh(FormatProcessor formatter) {
|
||||
@@ -58,14 +80,16 @@ public class DependantSpacingImpl extends SpacingImpl {
|
||||
else myFlags &= ~DEPENDENCE_CONTAINS_LF_MASK;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextRange getDependency() {
|
||||
return myDependency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer whether the target dependent regions has been changed during formatting.
|
||||
* Allows to answer whether 'contains line feed' status has been changed for the target dependent region during formatting.
|
||||
*
|
||||
* @return <code>true</code> if target dependent region has been changed during formatting; <code>false</code> otherwise
|
||||
* @return <code>true</code> if target 'contains line feed' status has been changed for the target dependent region during formatting;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final boolean isDependentRegionChanged() {
|
||||
return (myFlags & DEPENDENT_REGION_LF_CHANGED_MASK) != 0;
|
||||
@@ -85,4 +109,9 @@ public class DependantSpacingImpl extends SpacingImpl {
|
||||
return "<DependantSpacing: minSpaces=" + getMinSpaces() + " maxSpaces=" + getMaxSpaces() + " minLineFeeds=" + getMinLineFeeds() + " dep=" +
|
||||
myDependency + ">";
|
||||
}
|
||||
|
||||
private boolean isTriggered() {
|
||||
return myRule.getTrigger() == DependentSpacingRule.Trigger.HAS_LINE_FEEDS
|
||||
^ (myFlags & DEPENDENCE_CONTAINS_LF_MASK) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class FormatProcessor {
|
||||
* <pre>
|
||||
* int[] data = {1, 2, 3};
|
||||
* </pre>
|
||||
* We want to keep that in one line with possible but place curly braces on separate lines if the width is not enough:
|
||||
* We want to keep that in one line if possible but place curly braces on separate lines if the width is not enough:
|
||||
* <pre>
|
||||
* int[] data = { | < right margin
|
||||
* 1, 2, 3 |
|
||||
|
||||
@@ -133,6 +133,7 @@ public class FormatterImpl extends FormatterEx
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Spacing createSpacing(int minOffset,
|
||||
int maxOffset,
|
||||
int minLineFeeds,
|
||||
@@ -141,13 +142,21 @@ public class FormatterImpl extends FormatterEx
|
||||
return getSpacingImpl(minOffset, maxOffset, minLineFeeds, false, false, keepLineBreaks, keepBlankLines,false, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Spacing getReadOnlySpacing() {
|
||||
return myReadOnlySpacing;
|
||||
}
|
||||
|
||||
public Spacing createDependentLFSpacing(int minOffset, int maxOffset, TextRange dependence, boolean keepLineBreaks,
|
||||
int keepBlankLines) {
|
||||
return new DependantSpacingImpl(minOffset, maxOffset, dependence, keepLineBreaks, keepBlankLines);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Spacing createDependentLFSpacing(int minSpaces,
|
||||
int maxSpaces,
|
||||
@NotNull TextRange dependencyRange,
|
||||
boolean keepLineBreaks,
|
||||
int keepBlankLines,
|
||||
@NotNull DependentSpacingRule rule)
|
||||
{
|
||||
return new DependantSpacingImpl(minSpaces, maxSpaces, dependencyRange, keepLineBreaks, keepBlankLines, rule);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -669,10 +678,12 @@ public class FormatterImpl extends FormatterEx
|
||||
return myAbsoluteLabelIndent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Spacing createSafeSpacing(final boolean shouldKeepLineBreaks, final int keepBlankLines) {
|
||||
return getSpacingImpl(0, 0, 0, false, true, shouldKeepLineBreaks, keepBlankLines, false, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Spacing createKeepingFirstColumnSpacing(final int minSpace,
|
||||
final int maxSpace,
|
||||
final boolean keepLineBreaks,
|
||||
@@ -680,6 +691,7 @@ public class FormatterImpl extends FormatterEx
|
||||
return getSpacingImpl(minSpace, maxSpace, -1, false, false, keepLineBreaks, keepBlankLines, true, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Spacing createSpacing(final int minSpaces, final int maxSpaces, final int minLineFeeds, final boolean keepLineBreaks, final int keepBlankLines,
|
||||
final int prefLineFeeds) {
|
||||
return getSpacingImpl(minSpaces, maxSpaces, -1, false, false, keepLineBreaks, keepBlankLines, false, prefLineFeeds);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -132,7 +132,7 @@ public final class InjectedLanguageBlockWrapper implements Block {
|
||||
DependantSpacingImpl hostSpacing = (DependantSpacingImpl)spacing;
|
||||
return new DependantSpacingImpl(
|
||||
hostSpacing.getMinSpaces(), hostSpacing.getMaxSpaces(), hostSpacing.getDependency().shiftRight(shift),
|
||||
hostSpacing.shouldKeepLineFeeds(), hostSpacing.getKeepBlankLines()
|
||||
hostSpacing.shouldKeepLineFeeds(), hostSpacing.getKeepBlankLines(), DependentSpacingRule.DEFAULT
|
||||
);
|
||||
}
|
||||
return spacing;
|
||||
|
||||
Reference in New Issue
Block a user