mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-19061 Integrate the Rearranger-plugin into core-IDEA
'Grouping rules' are now part of the arrangement settings
This commit is contained in:
@@ -17,6 +17,7 @@ package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -140,10 +141,20 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaElementArrangementEntry wrap(@NotNull PsiElement element) {
|
||||
List<JavaElementArrangementEntry> result = new ArrayList<JavaElementArrangementEntry>();
|
||||
element.accept(new JavaArrangementVisitor(result, null, Collections.singleton(element.getTextRange())));
|
||||
return result.size() == 1 ? result.get(0) : null;
|
||||
public Pair<JavaElementArrangementEntry, List<JavaElementArrangementEntry>> parseWithNew(@NotNull PsiElement root,
|
||||
@Nullable Document document,
|
||||
@NotNull Collection<TextRange> ranges,
|
||||
@NotNull PsiElement element)
|
||||
{
|
||||
List<JavaElementArrangementEntry> existingEntries = new ArrayList<JavaElementArrangementEntry>();
|
||||
root.accept(new JavaArrangementVisitor(existingEntries, document, ranges));
|
||||
|
||||
List<JavaElementArrangementEntry> newEntry = new ArrayList<JavaElementArrangementEntry>();
|
||||
element.accept(new JavaArrangementVisitor(newEntry, document, Collections.singleton(element.getTextRange())));
|
||||
if (newEntry.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return Pair.create(newEntry.get(0), existingEntries);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
@@ -31,8 +31,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -42,15 +40,15 @@ import java.util.Set;
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public class CommonCodeStyleSettings {
|
||||
|
||||
@NonNls private static final String ARRANGEMENT_ELEMENT_NAME = "arrangementRules";
|
||||
|
||||
private final List<ArrangementRule> myArrangementRules
|
||||
= new ArrayList<ArrangementRule>();
|
||||
private final Language myLanguage;
|
||||
private CodeStyleSettings myRootSettings;
|
||||
private IndentOptions myIndentOptions;
|
||||
private FileType myFileType;
|
||||
|
||||
@NonNls private static final String ARRANGEMENT_ELEMENT_NAME = "arrangement";
|
||||
|
||||
private final Language myLanguage;
|
||||
|
||||
private ArrangementSettings myArrangementSettings;
|
||||
private CodeStyleSettings myRootSettings;
|
||||
private IndentOptions myIndentOptions;
|
||||
private FileType myFileType;
|
||||
|
||||
@NonNls private static final String INDENT_OPTIONS_TAG = "indentOptions";
|
||||
|
||||
@@ -122,14 +120,13 @@ public class CommonCodeStyleSettings {
|
||||
return myIndentOptions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ArrangementRule> getArrangementRules() {
|
||||
return myArrangementRules;
|
||||
@Nullable
|
||||
public ArrangementSettings getArrangementSettings() {
|
||||
return myArrangementSettings;
|
||||
}
|
||||
|
||||
public void setArrangementRules(@NotNull List<? extends ArrangementRule> rules) {
|
||||
myArrangementRules.clear();
|
||||
myArrangementRules.addAll(rules);
|
||||
public void setArrangementSettings(@NotNull ArrangementSettings settings) {
|
||||
myArrangementSettings = settings;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -141,8 +138,8 @@ public class CommonCodeStyleSettings {
|
||||
IndentOptions targetIndentOptions = commonSettings.initIndentOptions();
|
||||
targetIndentOptions.copyFrom(myIndentOptions);
|
||||
}
|
||||
if (!myArrangementRules.isEmpty()) {
|
||||
rootSettings.setArrangementRules(getArrangementRules());
|
||||
if (myArrangementSettings != null) {
|
||||
rootSettings.setArrangementSettings(myArrangementSettings);
|
||||
}
|
||||
return commonSettings;
|
||||
}
|
||||
@@ -214,7 +211,7 @@ public class CommonCodeStyleSettings {
|
||||
}
|
||||
Element arrangementRulesContainer = element.getChild(ARRANGEMENT_ELEMENT_NAME);
|
||||
if (arrangementRulesContainer != null) {
|
||||
myArrangementRules.addAll(ArrangementUtil.readExternal(arrangementRulesContainer, myLanguage));
|
||||
myArrangementSettings = ArrangementUtil.readExternal(arrangementRulesContainer, myLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,9 +231,9 @@ public class CommonCodeStyleSettings {
|
||||
}
|
||||
}
|
||||
|
||||
if (!myArrangementRules.isEmpty()) {
|
||||
if (myArrangementSettings != null) {
|
||||
Element container = new Element(ARRANGEMENT_ELEMENT_NAME);
|
||||
ArrangementUtil.writeExternal(container, myArrangementRules, myLanguage);
|
||||
ArrangementUtil.writeExternal(container, myArrangementSettings, myLanguage);
|
||||
if (!container.getChildren().isEmpty()) {
|
||||
element.addContent(container);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Holds arrangement rules.
|
||||
* <p/>
|
||||
* Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/17/12 11:51 AM
|
||||
*/
|
||||
public interface ArrangementSettings {
|
||||
|
||||
@NotNull
|
||||
List<? extends ArrangementRule> getRules();
|
||||
}
|
||||
+13
-17
@@ -20,40 +20,36 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Identifies a strategy that can tweak default {@link ArrangementRule arrangement rules} (de)serialization mechanism.
|
||||
* Identifies a strategy that can tweak default {@link ArrangementSettings arrangement settings} (de)serialization mechanism.
|
||||
* <p/>
|
||||
* Implementations of this interface are expected to be thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 7/18/12 10:30 AM
|
||||
*/
|
||||
public interface ArrangementRuleSerializer {
|
||||
public interface ArrangementSettingsSerializer {
|
||||
|
||||
/**
|
||||
* Allows to provide custom rule deserialization logic. This method is expected to be consistent with {@link #serialize(ArrangementRule)}.
|
||||
* Allows to provide custom settings deserialization logic. This method is expected to be consistent
|
||||
* with {@link #serialize(ArrangementSettings, Element)}.
|
||||
* <p/>
|
||||
* <b>Note:</b> it's save to return <code>null</code> if current rearranger doesn't use custom rules (rules over those
|
||||
* <b>Note:</b> it's save to return <code>null</code> if current rearranger doesn't use custom settings (settings over those
|
||||
* located at the <code>'lang-api'</code>/<code>'lang-impl'</code> modules).
|
||||
*
|
||||
* @param element serialized rule
|
||||
* @return rule de-serialized from the given element;
|
||||
* <code>null</code> as an indication that current rearranger doesn't provide custom serialization logic
|
||||
* for the target rule serialized at the given element, i.e. default deserialization algorithm should be used for it
|
||||
* @param element serialized settings holder
|
||||
* @return settings de-serialized from the given element
|
||||
*/
|
||||
@Nullable
|
||||
ArrangementRule deserialize(@NotNull Element element);
|
||||
ArrangementSettings deserialize(@NotNull Element element);
|
||||
|
||||
/**
|
||||
* Allows to provide custom rule serialization logic. This method is expected to be consistent with {@link #deserialize(Element)}.
|
||||
* Allows to provide custom settings serialization logic. This method is expected to be consistent with {@link #deserialize(Element)}.
|
||||
* <p/>
|
||||
* <b>Note:</b> it's save to return <code>null</code> if current rearranger doesn't use custom rules (rules over those
|
||||
* <b>Note:</b> it's save to return <code>null</code> if current rearranger doesn't use custom settings (settings over those
|
||||
* located at the <code>'lang-api'</code>/<code>'lang-impl'</code> modules).
|
||||
*
|
||||
* @param rule rule to serialize
|
||||
* @return serialized rule;
|
||||
* <code>null</code> as an indication that no custom serialization logic for the given rule
|
||||
* is provided by the current rearranger
|
||||
* @param settings settings to serialize
|
||||
* @param holder element to hold serialized settings
|
||||
*/
|
||||
@Nullable
|
||||
Element serialize(ArrangementRule rule);
|
||||
void serialize(ArrangementSettings settings, @NotNull Element holder);
|
||||
}
|
||||
@@ -39,73 +39,25 @@ public class ArrangementUtil {
|
||||
|
||||
//region Serialization
|
||||
|
||||
@NotNull
|
||||
public static List<ArrangementRule> readExternal(@NotNull Element element, @NotNull Language language) {
|
||||
final List<ArrangementRule> result = new ArrayList<ArrangementRule>();
|
||||
ArrangementRuleSerializer serializer = getSerializer(language);
|
||||
for (Object child : element.getChildren()) {
|
||||
ArrangementRule rule = serializer.deserialize((Element)child);
|
||||
if (rule != null) {
|
||||
result.add(rule);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@Nullable
|
||||
public static ArrangementSettings readExternal(@NotNull Element element, @NotNull Language language) {
|
||||
ArrangementSettingsSerializer serializer = getSerializer(language);
|
||||
return serializer.deserialize(element);
|
||||
}
|
||||
|
||||
public static void writeExternal(@NotNull Element element, @NotNull List<ArrangementRule> rules, @NotNull Language language) {
|
||||
if (rules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrangementRuleSerializer serializer = getSerializer(language);
|
||||
for (ArrangementRule rule : rules) {
|
||||
Element e = serializer.serialize(rule);
|
||||
if (e != null) {
|
||||
element.addContent(e);
|
||||
}
|
||||
}
|
||||
public static void writeExternal(@NotNull Element element, @NotNull ArrangementSettings settings, @NotNull Language language) {
|
||||
ArrangementSettingsSerializer serializer = getSerializer(language);
|
||||
serializer.serialize(settings, element);
|
||||
}
|
||||
|
||||
private static ArrangementRuleSerializer getSerializer(@NotNull Language language) {
|
||||
private static ArrangementSettingsSerializer getSerializer(@NotNull Language language) {
|
||||
Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(language);
|
||||
if (rearranger instanceof ArrangementRuleSerializer) {
|
||||
return new CompositeArrangementRuleSerializer((ArrangementRuleSerializer)rearranger, DefaultArrangementRuleSerializer.INSTANCE);
|
||||
if (rearranger instanceof ArrangementSettingsSerializer) {
|
||||
return (ArrangementSettingsSerializer)rearranger;
|
||||
}
|
||||
return DefaultArrangementRuleSerializer.INSTANCE;
|
||||
}
|
||||
|
||||
private static class CompositeArrangementRuleSerializer implements ArrangementRuleSerializer {
|
||||
|
||||
@NotNull private final List<ArrangementRuleSerializer> mySerializers = new ArrayList<ArrangementRuleSerializer>();
|
||||
|
||||
CompositeArrangementRuleSerializer(@NotNull ArrangementRuleSerializer ... serializers) {
|
||||
mySerializers.addAll(Arrays.asList(serializers));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ArrangementRule deserialize(@NotNull Element element) {
|
||||
for (ArrangementRuleSerializer serializer : mySerializers) {
|
||||
ArrangementRule rule = serializer.deserialize(element);
|
||||
if (rule != null) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Element serialize(ArrangementRule rule) {
|
||||
for (ArrangementRuleSerializer serializer : mySerializers) {
|
||||
Element element = serializer.serialize(rule);
|
||||
if (element != null) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
@NotNull
|
||||
|
||||
+72
-23
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingType;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.DefaultArrangementEntryMatcherSerializer;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
|
||||
@@ -22,51 +23,99 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 7/18/12 10:37 AM
|
||||
*/
|
||||
public class DefaultArrangementRuleSerializer implements ArrangementRuleSerializer {
|
||||
public class DefaultArrangementRuleSerializer implements ArrangementSettingsSerializer {
|
||||
|
||||
public static final ArrangementRuleSerializer INSTANCE = new DefaultArrangementRuleSerializer();
|
||||
public static final ArrangementSettingsSerializer INSTANCE = new DefaultArrangementRuleSerializer();
|
||||
|
||||
@NotNull @NonNls private static final String GROUPS_ELEMENT_NAME = "groups";
|
||||
@NotNull @NonNls private static final String GROUP_ELEMENT_NAME = "group";
|
||||
@NotNull @NonNls private static final String RULES_ELEMENT_NAME = "rules";
|
||||
@NotNull @NonNls private static final String RULE_ELEMENT_NAME = "rule";
|
||||
@NotNull @NonNls private static final String MATCHER_ELEMENT_NAME = "match";
|
||||
@NotNull @NonNls private static final String ORDER_TYPE_ELEMENT_NAME = "order";
|
||||
|
||||
@NotNull private final DefaultArrangementEntryMatcherSerializer myMatcherSerializer = new DefaultArrangementEntryMatcherSerializer();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StdArrangementRule deserialize(@NotNull Element element) {
|
||||
Element matcherElement = element.getChild(MATCHER_ELEMENT_NAME);
|
||||
if (matcherElement == null) {
|
||||
return null;
|
||||
public void serialize(ArrangementSettings s, @NotNull Element holder) {
|
||||
if (!(s instanceof StdArrangementSettings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StdArrangementEntryMatcher matcher = null;
|
||||
for (Object o : matcherElement.getChildren()) {
|
||||
matcher = myMatcherSerializer.deserialize((Element)o);
|
||||
if (matcher != null) {
|
||||
break;
|
||||
|
||||
StdArrangementSettings settings = (StdArrangementSettings)s;
|
||||
|
||||
List<ArrangementGroupingType> groupings = settings.getGroupings();
|
||||
if (!groupings.isEmpty()) {
|
||||
Element groupingsElement = new Element(GROUPS_ELEMENT_NAME);
|
||||
holder.addContent(groupingsElement);
|
||||
for (ArrangementGroupingType group : groupings) {
|
||||
groupingsElement.addContent(new Element(GROUP_ELEMENT_NAME).setText(group.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (matcher == null) {
|
||||
return null;
|
||||
List<StdArrangementRule> rules = settings.getRules();
|
||||
if (!rules.isEmpty()) {
|
||||
Element rulesElement = new Element(RULES_ELEMENT_NAME);
|
||||
holder.addContent(rulesElement);
|
||||
for (StdArrangementRule rule : rules) {
|
||||
rulesElement.addContent(serialize(rule));
|
||||
}
|
||||
}
|
||||
|
||||
Element orderTypeElement = element.getChild(ORDER_TYPE_ELEMENT_NAME);
|
||||
ArrangementEntryOrderType orderType = ArrangementRule.DEFAULT_ORDER_TYPE;
|
||||
if (orderTypeElement != null) {
|
||||
orderType = ArrangementEntryOrderType.valueOf(orderTypeElement.getText());
|
||||
}
|
||||
|
||||
return new StdArrangementRule(matcher, orderType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ArrangementSettings deserialize(@NotNull Element element) {
|
||||
StdArrangementSettings result = new StdArrangementSettings();
|
||||
Element groups = element.getChild(GROUPS_ELEMENT_NAME);
|
||||
if (groups != null) {
|
||||
for (Object group : groups.getChildren(GROUP_ELEMENT_NAME)) {
|
||||
Element groupElement = (Element)group;
|
||||
result.addGrouping(ArrangementGroupingType.valueOf(groupElement.getText()));
|
||||
}
|
||||
}
|
||||
|
||||
Element rulesElement = element.getChild(RULES_ELEMENT_NAME);
|
||||
if (rulesElement != null) {
|
||||
for (Object o : rulesElement.getChildren(RULE_ELEMENT_NAME)) {
|
||||
Element ruleElement = (Element)o;
|
||||
Element matcherElement = ruleElement.getChild(MATCHER_ELEMENT_NAME);
|
||||
if (matcherElement == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StdArrangementEntryMatcher matcher = null;
|
||||
for (Object c : matcherElement.getChildren()) {
|
||||
matcher = myMatcherSerializer.deserialize((Element)c);
|
||||
if (matcher != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matcher == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Element orderTypeElement = element.getChild(ORDER_TYPE_ELEMENT_NAME);
|
||||
ArrangementEntryOrderType orderType = ArrangementRule.DEFAULT_ORDER_TYPE;
|
||||
if (orderTypeElement != null) {
|
||||
orderType = ArrangementEntryOrderType.valueOf(orderTypeElement.getText());
|
||||
}
|
||||
result.addRule(new StdArrangementRule(matcher, orderType));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Element serialize(@NotNull ArrangementRule rule) {
|
||||
Element matcherElement = myMatcherSerializer.serialize(rule.getMatcher());
|
||||
if (matcherElement == null) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -40,17 +41,21 @@ public interface Rearranger<E extends ArrangementEntry> {
|
||||
LanguageExtension<Rearranger<?>> EXTENSION = new LanguageExtension<Rearranger<?>>("com.intellij.lang.rearranger");
|
||||
|
||||
/**
|
||||
* Tries to wrap given element to the corresponding arrangement entry.
|
||||
* Tries to wrap given element into arrangement entry at the target context.
|
||||
* <p/>
|
||||
* This is useful in a situation when new element is generated and we're deciding where to insert it (e.g. new field is
|
||||
* generated and we want to insert it according to the arrangement rules like 'fields before methods').
|
||||
*
|
||||
* @param element element to wrap into format eligible for further processing by arrangement engine
|
||||
* @return arrangement entry for the given element if it's possible to perform the mapping;
|
||||
* @return arrangement entry for the given element if it's possible to perform the mapping and list of arrangement entries
|
||||
* available at the given context plus newly created entry for the given element;
|
||||
* <code>null</code> otherwise
|
||||
*/
|
||||
@Nullable
|
||||
E wrap(@NotNull PsiElement element);
|
||||
Pair<E, List<E>> parseWithNew(@NotNull PsiElement root,
|
||||
@Nullable Document document,
|
||||
@NotNull Collection<TextRange> ranges,
|
||||
@NotNull PsiElement element);
|
||||
|
||||
/**
|
||||
* Allows to build rearranger-interested data for the given element.
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.psi.codeStyle.arrangement.group.ArrangementGroupingType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/17/12 11:53 AM
|
||||
*/
|
||||
public class StdArrangementSettings implements ArrangementSettings {
|
||||
|
||||
@NotNull private final List<StdArrangementRule> myRules = new ArrayList<StdArrangementRule>();
|
||||
@NotNull private final List<ArrangementGroupingType> myGroupings = new ArrayList<ArrangementGroupingType>();
|
||||
|
||||
public StdArrangementSettings() {
|
||||
}
|
||||
|
||||
public StdArrangementSettings(@NotNull Collection<StdArrangementRule> rules) {
|
||||
myRules.addAll(rules);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<StdArrangementRule> getRules() {
|
||||
return myRules;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ArrangementGroupingType> getGroupings() {
|
||||
return myGroupings;
|
||||
}
|
||||
|
||||
public void addRule(@NotNull StdArrangementRule rule) {
|
||||
myRules.add(rule);
|
||||
}
|
||||
|
||||
public void addGrouping(@NotNull ArrangementGroupingType grouping) {
|
||||
myGroupings.add(grouping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myRules.hashCode();
|
||||
result = 31 * result + myGroupings.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
StdArrangementSettings settings = (StdArrangementSettings)o;
|
||||
|
||||
if (!myGroupings.equals(settings.myGroupings)) return false;
|
||||
if (!myRules.equals(settings.myRules)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.group;
|
||||
|
||||
/**
|
||||
* Enumerates available grouping types.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 9/17/12 11:47 AM
|
||||
*/
|
||||
public enum ArrangementGroupingType {
|
||||
|
||||
GETTERS_AND_SETTERS,
|
||||
|
||||
OVERRIDDEN_METHODS,
|
||||
|
||||
UTILITY_METHODS
|
||||
}
|
||||
+16
-9
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.codeStyle.arrangement.StdArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.StdArrangementSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
@@ -78,7 +79,7 @@ public class ArrangementRuleTree {
|
||||
private boolean myExplicitSelectionChange;
|
||||
private boolean mySkipSelectionChange;
|
||||
|
||||
public ArrangementRuleTree(@NotNull List<StdArrangementRule> rules,
|
||||
public ArrangementRuleTree(@Nullable StdArrangementSettings settings,
|
||||
@NotNull List<Set<ArrangementMatchCondition>> groupingRules,
|
||||
@NotNull ArrangementNodeDisplayManager displayManager)
|
||||
{
|
||||
@@ -185,7 +186,7 @@ public class ArrangementRuleTree {
|
||||
}
|
||||
});
|
||||
|
||||
setRules(rules);
|
||||
setSettings(settings);
|
||||
|
||||
myTree.setShowsRootHandles(false);
|
||||
myTree.setCellRenderer(new MyCellRenderer());
|
||||
@@ -403,10 +404,10 @@ public class ArrangementRuleTree {
|
||||
* @return rules configured at the current tree at the moment
|
||||
*/
|
||||
@NotNull
|
||||
public List<StdArrangementRule> getRules() {
|
||||
public StdArrangementSettings getSettings() {
|
||||
int[] rows = myModels.keys();
|
||||
Arrays.sort(rows);
|
||||
List<StdArrangementRule> result = new ArrayList<StdArrangementRule>();
|
||||
List<StdArrangementRule> rules = new ArrayList<StdArrangementRule>();
|
||||
ArrangementMatchCondition prevGroup = null;
|
||||
Set<ArrangementMatchCondition> implicitGroupConditions = new HashSet<ArrangementMatchCondition>();
|
||||
for (int row : rows) {
|
||||
@@ -414,27 +415,32 @@ public class ArrangementRuleTree {
|
||||
ArrangementTreeNode topMost = model.getTopMost();
|
||||
ArrangementMatchCondition currentGroup = topMost.getBackingCondition();
|
||||
if (prevGroup != null && !prevGroup.equals(currentGroup)) {
|
||||
result.add(new StdArrangementRule(new StdArrangementEntryMatcher(prevGroup)));
|
||||
rules.add(new StdArrangementRule(new StdArrangementEntryMatcher(prevGroup)));
|
||||
implicitGroupConditions.add(prevGroup);
|
||||
prevGroup = null;
|
||||
}
|
||||
if (!myRoot.equals(topMost) && !topMost.equals(model.getBottomMost()) && !implicitGroupConditions.contains(currentGroup)) {
|
||||
prevGroup = currentGroup;
|
||||
}
|
||||
result.add(model.getRule());
|
||||
rules.add(model.getRule());
|
||||
}
|
||||
|
||||
if (prevGroup != null) {
|
||||
result.add(new StdArrangementRule(new StdArrangementEntryMatcher(prevGroup)));
|
||||
rules.add(new StdArrangementRule(new StdArrangementEntryMatcher(prevGroup)));
|
||||
}
|
||||
return result;
|
||||
return new StdArrangementSettings(rules);
|
||||
}
|
||||
|
||||
public void setRules(@NotNull List<StdArrangementRule> rules) {
|
||||
public void setSettings(@Nullable StdArrangementSettings settings) {
|
||||
myRenderers.clear();
|
||||
myModels.clear();
|
||||
while (myRoot.getChildCount() > 0)
|
||||
myTreeModel.removeNodeFromParent(myRoot.getFirstChild());
|
||||
if (settings == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<StdArrangementRule> rules = settings.getRules();
|
||||
map(rules);
|
||||
expandAll(myTree, new TreePath(myRoot));
|
||||
|
||||
@@ -631,6 +637,7 @@ public class ArrangementRuleTree {
|
||||
&& ((ArrangementCompositeMatchCondition)condition).getOperands().isEmpty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
public void disposeUI() {
|
||||
Container parent = EMPTY_RENDERER.getParent();
|
||||
if (parent != null) parent.remove(EMPTY_RENDERER);
|
||||
|
||||
+12
-23
@@ -25,11 +25,10 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.Rearranger;
|
||||
import com.intellij.psi.codeStyle.arrangement.StdArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.*;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
@@ -96,7 +95,7 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
toolbarControl.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.TOP | SideBorder.RIGHT));
|
||||
myContent.add(toolbarControl, new GridBag().weightx(1).fillCellHorizontally().coverLine());
|
||||
|
||||
myRuleTree = new ArrangementRuleTree(getRules(settings), groupingRules, displayManager);
|
||||
myRuleTree = new ArrangementRuleTree(getSettings(settings), groupingRules, displayManager);
|
||||
final Tree treeComponent = myRuleTree.getTreeComponent();
|
||||
actionToolbar.setTargetComponent(treeComponent);
|
||||
JBScrollPane scrollPane = new JBScrollPane(treeComponent);
|
||||
@@ -283,26 +282,16 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
private List<StdArrangementRule> getRules(@NotNull CodeStyleSettings settings) {
|
||||
List<ArrangementRule> storedRules = settings.getCommonSettings(myLanguage).getArrangementRules();
|
||||
if (storedRules.isEmpty()) {
|
||||
@Nullable
|
||||
private StdArrangementSettings getSettings(@NotNull CodeStyleSettings settings) {
|
||||
StdArrangementSettings result = (StdArrangementSettings)settings.getCommonSettings(myLanguage).getArrangementSettings();
|
||||
if (result == null) {
|
||||
List<StdArrangementRule> defaultRules = mySettingsAware.getDefaultRules();
|
||||
if (defaultRules != null) {
|
||||
return defaultRules;
|
||||
result = new StdArrangementSettings(defaultRules);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We use unchecked cast here in assumption that current rearranger is based on standard settings if it uses standard
|
||||
// settings-based rule editor.
|
||||
// Note: unchecked cast for the whole collection doesn't work here (compiler error).
|
||||
List<StdArrangementRule> result = new ArrayList<StdArrangementRule>();
|
||||
for (ArrangementRule rule : storedRules) {
|
||||
result.add((StdArrangementRule)rule);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void setupKeyboardActions(@NotNull ActionManager actionManager, @NotNull Tree treeComponent) {
|
||||
@@ -329,17 +318,17 @@ public abstract class ArrangementSettingsPanel extends CodeStyleAbstractPanel {
|
||||
|
||||
@Override
|
||||
public boolean isModified(@NotNull CodeStyleSettings settings) {
|
||||
return !getRules(settings).equals(myRuleTree.getRules());
|
||||
return !Comparing.equal(getSettings(settings), myRuleTree.getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(@NotNull CodeStyleSettings settings) {
|
||||
settings.getCommonSettings(myLanguage).setArrangementRules(myRuleTree.getRules());
|
||||
settings.getCommonSettings(myLanguage).setArrangementSettings(myRuleTree.getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl(@NotNull CodeStyleSettings settings) {
|
||||
myRuleTree.setRules(getRules(settings));
|
||||
myRuleTree.setSettings(getSettings(settings));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-16
@@ -16,6 +16,7 @@
|
||||
package com.intellij.psi.codeStyle.arrangement;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
|
||||
@@ -44,7 +45,7 @@ public class MemberOrderService {
|
||||
|
||||
/**
|
||||
* Tries to find an element at the given context which should be the previous sibling for the given 'member'element according to the
|
||||
* {@link CommonCodeStyleSettings#getArrangementRules() user-defined arrangement rules}.
|
||||
* {@link CommonCodeStyleSettings#getArrangementSettings() user-defined arrangement rules}.
|
||||
* <p/>
|
||||
* E.g. the IDE might generate given 'member' element and wants to know element after which it should be inserted
|
||||
*
|
||||
@@ -64,30 +65,31 @@ public class MemberOrderService {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<? extends ArrangementRule> rules = settings.getArrangementRules();
|
||||
if (rules.isEmpty() && rearranger instanceof ArrangementStandardSettingsAware) {
|
||||
rules = ((ArrangementStandardSettingsAware)rearranger).getDefaultRules();
|
||||
}
|
||||
|
||||
if (rules == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrangementEntry memberEntry = rearranger.wrap(member);
|
||||
if (memberEntry == null) {
|
||||
return null;
|
||||
ArrangementSettings arrangementSettings = settings.getArrangementSettings();
|
||||
if (arrangementSettings == null && rearranger instanceof ArrangementStandardSettingsAware) {
|
||||
List<StdArrangementRule> rules = ((ArrangementStandardSettingsAware)rearranger).getDefaultRules();
|
||||
if (rules != null && !rules.isEmpty()) {
|
||||
arrangementSettings = new StdArrangementSettings(rules);
|
||||
}
|
||||
}
|
||||
|
||||
List<? extends ArrangementEntry> entries = rearranger.parse(context, null, Collections.singleton(context.getTextRange()));
|
||||
if (entries.isEmpty()) {
|
||||
if (arrangementSettings == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Pair<? extends ArrangementEntry,? extends List<? extends ArrangementEntry>> pair =
|
||||
rearranger.parseWithNew(context, null, Collections.singleton(context.getTextRange()), member);
|
||||
if (pair == null || pair.second.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrangementEntry memberEntry = pair.first;
|
||||
List<? extends ArrangementEntry> entries = pair.second;
|
||||
ArrangementEntry parentEntry = entries.get(0);
|
||||
List<? extends ArrangementEntry> nonArranged = parentEntry.getChildren();
|
||||
List<ArrangementEntry> entriesWithNew = new ArrayList<ArrangementEntry>(nonArranged);
|
||||
entriesWithNew.add(memberEntry);
|
||||
List<ArrangementEntry> arranged = ArrangementEngine.arrange(entriesWithNew, rules);
|
||||
List<ArrangementEntry> arranged = ArrangementEngine.arrange(entriesWithNew, arrangementSettings.getRules());
|
||||
int i = arranged.indexOf(memberEntry);
|
||||
|
||||
if (i <= 0) {
|
||||
|
||||
+10
-10
@@ -26,10 +26,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
|
||||
import com.intellij.psi.codeStyle.arrangement.ArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.Rearranger;
|
||||
import com.intellij.psi.codeStyle.arrangement.StdArrangementRule;
|
||||
import com.intellij.psi.codeStyle.arrangement.*;
|
||||
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.containers.Stack;
|
||||
@@ -70,14 +67,15 @@ public class ArrangementEngine {
|
||||
}
|
||||
|
||||
final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(file.getProject()).getCurrentSettings();
|
||||
List<? extends ArrangementRule> arrangementRules = settings.getCommonSettings(file.getLanguage()).getArrangementRules();
|
||||
if (arrangementRules.isEmpty() && rearranger instanceof ArrangementStandardSettingsAware) {
|
||||
ArrangementSettings arrangementSettings = settings.getCommonSettings(file.getLanguage()).getArrangementSettings();
|
||||
if (arrangementSettings == null && rearranger instanceof ArrangementStandardSettingsAware) {
|
||||
List<StdArrangementRule> defaultRules = ((ArrangementStandardSettingsAware)rearranger).getDefaultRules();
|
||||
if (defaultRules != null) {
|
||||
arrangementRules = defaultRules;
|
||||
if (defaultRules != null && !defaultRules.isEmpty()) {
|
||||
arrangementSettings = new StdArrangementSettings(defaultRules);
|
||||
}
|
||||
}
|
||||
if (arrangementRules.isEmpty()) {
|
||||
|
||||
if (arrangementSettings == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,7 +87,9 @@ public class ArrangementEngine {
|
||||
documentEx = null;
|
||||
}
|
||||
|
||||
final Context<? extends ArrangementEntry> context = Context.from(rearranger, document, file, ranges, arrangementRules, settings);
|
||||
final Context<? extends ArrangementEntry> context = Context.from(
|
||||
rearranger, document, file, ranges, arrangementSettings.getRules(), settings
|
||||
);
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@ abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFixtureTes
|
||||
|
||||
protected void doTest(@NotNull String initial,
|
||||
@NotNull String expected,
|
||||
@NotNull List<ArrangementRule> rules,
|
||||
@NotNull List<StdArrangementRule> rules,
|
||||
Collection<TextRange> ranges = null)
|
||||
{
|
||||
def (String textToUse, List<TextRange> rangesToUse) = parseRanges(initial)
|
||||
@@ -89,7 +89,7 @@ abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFixtureTes
|
||||
|
||||
myFixture.configureByText(fileType, textToUse)
|
||||
def settings = CodeStyleSettingsManager.getInstance(myFixture.project).currentSettings.getCommonSettings(language)
|
||||
settings.arrangementRules = rules
|
||||
settings.arrangementSettings = new StdArrangementSettings(rules)
|
||||
ArrangementEngine engine = ServiceManager.getService(myFixture.project, ArrangementEngine)
|
||||
engine.arrange(myFixture.file, rangesToUse);
|
||||
junit.framework.Assert.assertEquals(expected, myFixture.editor.document.text);
|
||||
|
||||
Reference in New Issue
Block a user