From c0aa0945c2d7c3f3fa662fabd83791145c6291ed Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Thu, 19 Jul 2012 18:47:59 +0400 Subject: [PATCH] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA Basic 'code arrangement' infrastructure is defined --- platform/lang-api/lang-api.iml | 3 + .../codeStyle/CommonCodeStyleSettings.java | 29 +++- .../ArrangementEntry.java} | 25 ++- .../arrangement/ArrangementRule.java | 76 +++++++++ .../ArrangementRuleSerializer.java | 59 +++++++ .../arrangement/ArrangementRuleUtil.java | 144 +++++++++++++++++ .../DefaultArrangementRuleSerializer.java | 82 ++++++++++ .../NameAwareArrangementEntry.java | 28 ++++ .../psi/codeStyle/arrangement/Rearranger.java | 47 ++++++ .../TypeAwareArrangementEntry.java} | 12 +- .../match/ArrangementEntryMatcher.java} | 17 +- .../match/ArrangementEntryType.java} | 8 +- .../match/ArrangementModifier.java} | 4 +- .../match/ByNameArrangementEntryMatcher.java | 68 ++++++++ .../match/ByTypeArrangementEntryMatcher.java | 80 +++++++++ .../CompositeArrangementEntryMatcher.java | 91 +++++++++++ .../match/ModifierAwareArrangementEntry.java | 29 ++++ ...angementEntryMatcherSerializationTag.java} | 9 +- .../ArrangementEntryMatcherSerializer.java | 61 +++++++ ...NameArrangementEntryMatcherSerializer.java | 54 +++++++ ...TypeArrangementEntryMatcherSerializer.java | 81 ++++++++++ ...aultArrangementEntryMatcherSerializer.java | 153 ++++++++++++++++++ .../sort/ArrangementEntrySortType.java | 25 +++ .../sort/ArrangementEntrySorter.java | 44 +++++ .../sort/ByNameArrangementEntrySorter.java | 63 ++++++++ .../rearranger/RearrangerFacade.java | 42 ----- .../rule/RearrangerCompositeRule.java | 64 -------- .../rearranger/rule/RearrangerRuleUtil.java | 61 ------- .../rearranger/rule/RearrangerTypeRule.java | 53 ------ .../DefaultArrangementRuleSerializerTest.java | 73 +++++++++ 30 files changed, 1332 insertions(+), 253 deletions(-) rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/RearrangerEntry.java => arrangement/ArrangementEntry.java} (67%) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRule.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementRuleSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/NameAwareArrangementEntry.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/TypeAwareRearrangerEntry.java => arrangement/TypeAwareArrangementEntry.java} (68%) rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/RearrangerRule.java => arrangement/match/ArrangementEntryMatcher.java} (65%) rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/RearrangerEntryType.java => arrangement/match/ArrangementEntryType.java} (78%) rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/RearrangerModifier.java => arrangement/match/ArrangementModifier.java} (89%) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/CompositeArrangementEntryMatcher.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java rename platform/lang-api/src/com/intellij/psi/codeStyle/{rearranger/ModifierAwareRearrangerEntry.java => arrangement/match/serialization/ArrangementEntryMatcherSerializationTag.java} (78%) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByNameArrangementEntryMatcherSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByTypeArrangementEntryMatcherSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/DefaultArrangementEntryMatcherSerializer.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySortType.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySorter.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ByNameArrangementEntrySorter.java delete mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerFacade.java delete mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerCompositeRule.java delete mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerRuleUtil.java delete mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerTypeRule.java create mode 100644 platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java diff --git a/platform/lang-api/lang-api.iml b/platform/lang-api/lang-api.iml index 0c89574778c7..c11c72642e4c 100644 --- a/platform/lang-api/lang-api.iml +++ b/platform/lang-api/lang-api.iml @@ -4,6 +4,7 @@ + @@ -12,6 +13,8 @@ + + diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index d5f3e7143669..15bf90ccec1f 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -19,6 +19,8 @@ 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.ArrangementRuleUtil; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializer; import org.intellij.lang.annotations.MagicConstant; @@ -28,6 +30,8 @@ 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; /** @@ -37,11 +41,14 @@ import java.util.Set; * @author Rustam Vishnyakov */ public class CommonCodeStyleSettings { - - private Language myLanguage; + + @NotNull private static final String ARRANGEMENT_ELEMENT_NAME = "arrangementRules"; + + @NotNull private final List myArrangementRules = new ArrayList(); + private Language myLanguage; private CodeStyleSettings myRootSettings; - private IndentOptions myIndentOptions; - private FileType myFileType; + private IndentOptions myIndentOptions; + private FileType myFileType; private final static String INDENT_OPTIONS_TAG = "indentOptions"; @@ -193,6 +200,10 @@ public class CommonCodeStyleSettings { myIndentOptions.deserialize(indentOptionsElement); } } + Element arrangementRulesContainer = element.getChild(ARRANGEMENT_ELEMENT_NAME); + if (arrangementRulesContainer != null) { + myArrangementRules.addAll(ArrangementRuleUtil.readExternal(arrangementRulesContainer, myLanguage)); + } } public void writeExternal(Element element) throws WriteExternalException { @@ -210,6 +221,14 @@ public class CommonCodeStyleSettings { element.addContent(indentOptionsElement); } } + + if (!myArrangementRules.isEmpty()) { + Element container = new Element(ARRANGEMENT_ELEMENT_NAME); + ArrangementRuleUtil.writeExternal(container, myArrangementRules, myLanguage); + if (!container.getChildren().isEmpty()) { + element.addContent(container); + } + } } @Nullable diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java similarity index 67% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntry.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java index ddfff7b0d3e4..f29ed7d103a2 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntry.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementEntry.java @@ -1,4 +1,19 @@ -package com.intellij.psi.codeStyle.rearranger; +/* + * 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 org.jetbrains.annotations.Nullable; @@ -9,7 +24,7 @@ import java.util.Collection; * Represents a processing unit during 'rearrangement' operation. I.e. entry's position can be changed during the processing. *

* Example: we can provide a grouping rule for class methods (e.g. getters and setters). Every such method will be represented by - * a {@link RearrangerEntry} then. + * a {@link ArrangementEntry} then. *

* The entries can be organised into hierarchies where every sub-hierarchy is independent * (see {@link #getParent()}, {@link #getChildren()}). @@ -19,14 +34,14 @@ import java.util.Collection; * @author Denis Zhdanov * @since 7/16/12 3:31 PM */ -public interface RearrangerEntry { +public interface ArrangementEntry { /** * @return parent entry, e.g. it would be a class entry for a method entry * @see #getChildren() */ @Nullable - RearrangerEntry getParent(); + ArrangementEntry getParent(); /** * Entries can be organised into hierarchies, that means that only siblings position can be changed during the rearrangement. @@ -38,7 +53,7 @@ public interface RearrangerEntry { * @see #getParent() */ @NotNull - Collection getChildren(); + Collection getChildren(); /** * @return start offset of the current entry (inclusive) within the target document. Rearranger engine uses this information diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRule.java new file mode 100644 index 000000000000..8145784a27c1 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRule.java @@ -0,0 +1,76 @@ +/* + * 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.match.ArrangementEntryMatcher; +import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType; +import org.jetbrains.annotations.NotNull; + +/** + * Container for the strategies to be used during file entries arrangement. + *

+ * Example: we can define a rule like 'private final non-static fields' or 'public static methods' etc. + *

+ * Not thread-safe. + * + * @author Denis Zhdanov + * @since 7/17/12 11:07 AM + */ +public class ArrangementRule { + + @NotNull private final ArrangementEntryMatcher myMatcher; + @NotNull private final ArrangementEntrySortType mySortType; + + public ArrangementRule(@NotNull ArrangementEntryMatcher matcher) { + this(matcher, ArrangementEntrySortType.NO_SORT); + } + + public ArrangementRule(@NotNull ArrangementEntryMatcher matcher, @NotNull ArrangementEntrySortType type) { + myMatcher = matcher; + mySortType = type; + } + + @NotNull + public ArrangementEntryMatcher getMatcher() { + return myMatcher; + } + + @NotNull + public ArrangementEntrySortType getSorter() { + return mySortType; + } + + @Override + public int hashCode() { + int result = myMatcher.hashCode(); + result = 31 * result + mySortType.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ArrangementRule that = (ArrangementRule)o; + return mySortType == that.mySortType && myMatcher.equals(that.myMatcher); + } + + @Override + public String toString() { + return String.format("matcher: %s, sort type: %s", myMatcher, mySortType); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleSerializer.java new file mode 100644 index 000000000000..c568dde2f4f1 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleSerializer.java @@ -0,0 +1,59 @@ +/* + * 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.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Identifies a strategy that can tweak default {@link ArrangementRule arrangement rules} (de)serialization mechanism. + *

+ * Implementations of this interface are expected to be thread-safe. + * + * @author Denis Zhdanov + * @since 7/18/12 10:30 AM + */ +public interface ArrangementRuleSerializer { + + /** + * Allows to provide custom rule deserialization logic. This method is expected to be consistent with {@link #serialize(ArrangementRule)}. + *

+ * Note: it's save to return null if current rearranger doesn't use custom rules (rules over those + * located at the 'lang-api'/'lang-impl' modules). + * + * @param element serialized rule + * @return rule de-serialized from the given element; + * null 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 + */ + @Nullable + ArrangementRule deserialize(@NotNull Element element); + + /** + * Allows to provide custom rule serialization logic. This method is expected to be consistent with {@link #deserialize(Element)}. + *

+ * Note: it's save to return null if current rearranger doesn't use custom rules (rules over those + * located at the 'lang-api'/'lang-impl' modules). + * + * @param rule rule to serialize + * @return serialized rule; + * null as an indication that no custom serialization logic for the given rule + * is provided by the current rearranger + */ + @Nullable + Element serialize(ArrangementRule rule); +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java new file mode 100644 index 000000000000..9d9c21da3533 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementRuleUtil.java @@ -0,0 +1,144 @@ +/* + * 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.lang.Language; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; +import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author Denis Zhdanov + * @since 7/17/12 11:24 AM + */ +public class ArrangementRuleUtil { + + private ArrangementRuleUtil() { + } + + //region Serialization + + @NotNull + public static List readExternal(@NotNull Element element, @NotNull Language language) { + final List result = new ArrayList(); + ArrangementRuleSerializer serializer = getSerializer(language); + for (Object child : element.getChildren()) { + ArrangementRule rule = serializer.deserialize((Element)child); + if (rule != null) { + result.add(rule); + } + } + return result; + } + + public static void writeExternal(@NotNull Element element, @NotNull List 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); + } + } + } + + private static ArrangementRuleSerializer getSerializer(@NotNull Language language) { + Rearranger rearranger = Rearranger.EXTENSION.forLanguage(language); + if (rearranger instanceof ArrangementRuleSerializer) { + return new CompositeArrangementRuleSerializer((ArrangementRuleSerializer)rearranger, DefaultArrangementRuleSerializer.INSTANCE); + } + return DefaultArrangementRuleSerializer.INSTANCE; + } + + private static class CompositeArrangementRuleSerializer implements ArrangementRuleSerializer { + + @NotNull private final List mySerializers = new ArrayList(); + + 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 + + //region Matchers composition + @NotNull + public static ArrangementEntryMatcher or(@NotNull ArrangementEntryMatcher... matchers) { + return combine(CompositeArrangementEntryMatcher.Operator.OR, matchers); + } + + @NotNull + public static ArrangementEntryMatcher and(@NotNull ArrangementEntryMatcher... matchers) { + return combine(CompositeArrangementEntryMatcher.Operator.AND, matchers); + } + + @NotNull + private static ArrangementEntryMatcher combine(@NotNull CompositeArrangementEntryMatcher.Operator operator, + @NotNull ArrangementEntryMatcher... matchers) + { + CompositeArrangementEntryMatcher composite = null; + for (ArrangementEntryMatcher matcher : matchers) { + if (matcher instanceof CompositeArrangementEntryMatcher && ((CompositeArrangementEntryMatcher)(matcher)).getOperator() == operator) { + composite = (CompositeArrangementEntryMatcher)matcher; + break; + } + } + + if (composite == null) { + return new CompositeArrangementEntryMatcher(operator, matchers); + } + + for (ArrangementEntryMatcher matcher : matchers) { + if (matcher != composite) { + composite.addMatcher(matcher); + } + } + return composite; + } + //endregion +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementRuleSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementRuleSerializer.java new file mode 100644 index 000000000000..c7702fff35e4 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementRuleSerializer.java @@ -0,0 +1,82 @@ +/* + * 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.match.ArrangementEntryMatcher; +import com.intellij.psi.codeStyle.arrangement.match.serialization.DefaultArrangementEntryMatcherSerializer; +import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +/** + * @author Denis Zhdanov + * @since 7/18/12 10:37 AM + */ +public class DefaultArrangementRuleSerializer implements ArrangementRuleSerializer { + + public static final ArrangementRuleSerializer INSTANCE = new DefaultArrangementRuleSerializer(); + + @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 SORT_TYPE_ELEMENT_NAME = "sort"; + + @NotNull private final DefaultArrangementEntryMatcherSerializer myMatcherSerializer = new DefaultArrangementEntryMatcherSerializer(); + + + @Nullable + @Override + public ArrangementRule deserialize(@NotNull Element element) { + Element matcherElement = element.getChild(MATCHER_ELEMENT_NAME); + if (matcherElement == null) { + return null; + } + + ArrangementEntryMatcher matcher = null; + for (Object o : matcherElement.getChildren()) { + matcher = myMatcherSerializer.deserialize((Element)o); + if (matcher != null) { + break; + } + } + + if (matcher == null) { + return null; + } + + Element sortElement = element.getChild(SORT_TYPE_ELEMENT_NAME); + ArrangementEntrySortType sortType = ArrangementEntrySortType.NO_SORT; + if (sortElement != null) { + sortType = ArrangementEntrySortType.valueOf(sortElement.getText()); + } + + return new ArrangementRule(matcher, sortType); + } + + @Nullable + @Override + public Element serialize(@NotNull ArrangementRule rule) { + Element matcherElement = myMatcherSerializer.serialize(rule.getMatcher()); + if (matcherElement == null) { + return null; + } + + Element result = new Element(RULE_ELEMENT_NAME); + result.addContent(new Element(MATCHER_ELEMENT_NAME).addContent(matcherElement)); + result.addContent(new Element(SORT_TYPE_ELEMENT_NAME).setText(rule.getSorter().toString())); + return result; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/NameAwareArrangementEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/NameAwareArrangementEntry.java new file mode 100644 index 000000000000..91ac3c203360 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/NameAwareArrangementEntry.java @@ -0,0 +1,28 @@ +/* + * 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.Nullable; + +/** + * @author Denis Zhdanov + * @since 7/19/12 6:13 PM + */ +public interface NameAwareArrangementEntry extends ArrangementEntry { + + @Nullable + String getName(); +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java new file mode 100644 index 000000000000..b8eb681b3704 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java @@ -0,0 +1,47 @@ +/* + * 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.lang.LanguageExtension; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Encapsulates language-specific rearrangement logic. + *

+ * Implementations of this interface are expected to be thread-safe. + * + * @author Denis Zhdanov + * @since 7/16/12 3:23 PM + * @param entry type + */ +public interface Rearranger { + + LanguageExtension> EXTENSION = new LanguageExtension>("com.intellij.rearranger.facade"); + + /** + * Allows to build rearranger-interested data for the given element. + * + * @param root root element which children should be parsed for the rearrangement + * @param range target offsets range to use for filtering given root's children + * @return given root's children that are subject for further rearrangement + */ + @NotNull + Collection parse(@NotNull PsiElement root, @NotNull TextRange range); +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/TypeAwareRearrangerEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/TypeAwareArrangementEntry.java similarity index 68% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/TypeAwareRearrangerEntry.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/TypeAwareArrangementEntry.java index 9a77f37053f5..14ddd6d3f682 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/TypeAwareRearrangerEntry.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/TypeAwareArrangementEntry.java @@ -13,20 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.codeStyle.rearranger; +package com.intellij.psi.codeStyle.arrangement; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** - * Stands for the {@link RearrangerEntry} which provides information about its type. + * Stands for the {@link ArrangementEntry} which provides information about its type. *

* Implementations of this interface are not obliged to be thread-safe. * * @author Denis Zhdanov * @since 7/17/12 11:17 AM */ -public interface TypeAwareRearrangerEntry extends RearrangerEntry { +public interface TypeAwareArrangementEntry extends ArrangementEntry { - @NotNull - RearrangerEntryType getType(); + @Nullable + ArrangementEntryType getType(); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryMatcher.java similarity index 65% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerRule.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryMatcher.java index a81360fd10c0..93a92b321561 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerRule.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryMatcher.java @@ -13,29 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.codeStyle.rearranger; +package com.intellij.psi.codeStyle.arrangement.match; +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.ArrangementRule; import org.jetbrains.annotations.NotNull; /** - * Identifies a strategy which can be used for grouping {@link RearrangerEntry entries}. + * Defines a contract for strategy that determines if an {@link ArrangementRule arrangement rule} matches particular + * {@link ArrangementEntry arrangement entry}. *

- * Example: we can define a rule like 'private final non-static fields' or 'public static methods' etc. + * Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations. *

* Implementations of this interface are expected to be thread-safe. * * @author Denis Zhdanov - * @since 7/17/12 11:07 AM + * @since 7/18/12 12:02 PM */ -public interface RearrangerRule { +public interface ArrangementEntryMatcher { /** * Allows to check if given entry is matched by the current rule. *

* Example: entry like 'public final field' should be matched by a 'final fields' rule but not matched by a 'private fields' rule. - * + * * @param entry entry to check * @return true if given entry is matched by the current rule; false otherwise */ - boolean isMatched(@NotNull RearrangerEntry entry); + boolean isMatched(@NotNull ArrangementEntry entry); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntryType.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryType.java similarity index 78% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntryType.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryType.java index 61236b2a4dd7..0ba54c75a6be 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerEntryType.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementEntryType.java @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.codeStyle.rearranger; +package com.intellij.psi.codeStyle.arrangement.match; -import com.intellij.psi.codeStyle.rearranger.RearrangerEntry; +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; /** - * Enumerates all possible {@link RearrangerEntry entry} types. + * Enumerates all possible {@link ArrangementEntry entry} types. *

* This enum is expected to be populated every time new entry type is introduced. * * @author Denis Zhdanov * @since 7/17/12 11:14 AM */ -public enum RearrangerEntryType { +public enum ArrangementEntryType { CLASS, FIELD, METHOD } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerModifier.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementModifier.java similarity index 89% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerModifier.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementModifier.java index 5bd519c8c0ef..3876c43806c3 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerModifier.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ArrangementModifier.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.codeStyle.rearranger; +package com.intellij.psi.codeStyle.arrangement.match; /** * @author Denis Zhdanov * @since 7/17/12 8:54 PM */ -public enum RearrangerModifier { +public enum ArrangementModifier { //region Visibility PUBLIC, PROTECTED, PRIVATE, PACKAGE_PRIVATE, diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java new file mode 100644 index 000000000000..251c3c91f8dc --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByNameArrangementEntryMatcher.java @@ -0,0 +1,68 @@ +/* + * 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.match; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry; +import org.jetbrains.annotations.NotNull; + +/** + * @author Denis Zhdanov + * @since 7/19/12 6:36 PM + */ +public class ByNameArrangementEntryMatcher implements ArrangementEntryMatcher { + + @NotNull private final String myPattern; + + public ByNameArrangementEntryMatcher(@NotNull String pattern) { + myPattern = pattern; + } + + @Override + public boolean isMatched(@NotNull ArrangementEntry entry) { + if (entry instanceof NameAwareArrangementEntry) { + String name = ((NameAwareArrangementEntry)entry).getName(); + if (name != null) { + return name.matches(myPattern); + } + } + return false; + } + + @NotNull + public String getPattern() { + return myPattern; + } + + @Override + public int hashCode() { + return myPattern.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ByNameArrangementEntryMatcher that = (ByNameArrangementEntryMatcher)o; + return myPattern.equals(that.myPattern); + } + + @Override + public String toString() { + return String.format("with name like '%s'", myPattern); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java new file mode 100644 index 000000000000..f28bfdb107e2 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java @@ -0,0 +1,80 @@ +/* + * 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.match; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; + +/** + * Filters {@link ArrangementEntry entries} by {@link TypeAwareArrangementEntry#getType() their types}. + *

+ * Note: type-unaware entry will not be matched by the current rule. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since 7/17/12 11:19 AM + */ +public class ByTypeArrangementEntryMatcher implements ArrangementEntryMatcher { + + @NotNull private final Set myTypes = EnumSet.noneOf(ArrangementEntryType.class); + + public ByTypeArrangementEntryMatcher(@NotNull ArrangementEntryType... interestedTypes) { + this(Arrays.asList(interestedTypes)); + } + + public ByTypeArrangementEntryMatcher(@NotNull Collection interestedTypes) { + myTypes.addAll(interestedTypes); + } + + @Override + public boolean isMatched(@NotNull ArrangementEntry entry) { + if (entry instanceof TypeAwareArrangementEntry) { + return myTypes.contains(((TypeAwareArrangementEntry)(entry)).getType()); + } + return false; + } + + @NotNull + public Set getTypes() { + return myTypes; + } + + @Override + public int hashCode() { + return myTypes.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ByTypeArrangementEntryMatcher that = (ByTypeArrangementEntryMatcher)o; + return myTypes.equals(that.myTypes); + } + + @Override + public String toString() { + return String.format("of type '%s'", myTypes); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/CompositeArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/CompositeArrangementEntryMatcher.java new file mode 100644 index 000000000000..528941a25817 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/CompositeArrangementEntryMatcher.java @@ -0,0 +1,91 @@ +/* + * 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.match; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author Denis Zhdanov + * @since 7/17/12 11:26 AM + */ +public class CompositeArrangementEntryMatcher implements ArrangementEntryMatcher { + + @NotNull private final Set myMatchers = new HashSet(); + @NotNull private final Operator myOperator; + + public CompositeArrangementEntryMatcher(@NotNull Operator operator, @NotNull ArrangementEntryMatcher... matchers) { + myOperator = operator; + myMatchers.addAll(Arrays.asList(matchers)); + } + + @Override + public boolean isMatched(@NotNull ArrangementEntry entry) { + for (ArrangementEntryMatcher matcher : myMatchers) { + boolean matched = matcher.isMatched(entry); + if (matched && myOperator == Operator.OR) { + return true; + } + else if (!matched && myOperator == Operator.AND) { + return false; + } + } + return myOperator == Operator.AND; + } + + @NotNull + public Operator getOperator() { + return myOperator; + } + + @NotNull + public Collection getMatchers() { + return myMatchers; + } + + public void addMatcher(@NotNull ArrangementEntryMatcher rule) { + myMatchers.add(rule); + } + + @Override + public int hashCode() { + int result = myMatchers.hashCode(); + result = 31 * result + myOperator.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CompositeArrangementEntryMatcher matcher = (CompositeArrangementEntryMatcher)o; + + if (!myMatchers.equals(matcher.myMatchers)) return false; + if (myOperator != matcher.myOperator) return false; + + return true; + } + + @Override + public String toString() { + return String.format("%s of those: %s", myOperator == Operator.AND ? "all" : "any", myMatchers); + } + + public enum Operator {AND, OR} +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java new file mode 100644 index 000000000000..10acb1bbd263 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ModifierAwareArrangementEntry.java @@ -0,0 +1,29 @@ +/* + * 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.match; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import org.jetbrains.annotations.NotNull; + +/** + * @author Denis Zhdanov + * @since 7/17/12 8:57 PM + */ +public interface ModifierAwareArrangementEntry extends ArrangementEntry { + + @NotNull + ArrangementModifier getModifier(); +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/ModifierAwareRearrangerEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializationTag.java similarity index 78% rename from platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/ModifierAwareRearrangerEntry.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializationTag.java index 3519a5c481a3..94e99d524764 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/ModifierAwareRearrangerEntry.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializationTag.java @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.codeStyle.rearranger; +package com.intellij.psi.codeStyle.arrangement.match.serialization; import org.jetbrains.annotations.NotNull; /** * @author Denis Zhdanov - * @since 7/17/12 8:57 PM + * @since 7/19/12 12:45 PM */ -public interface ModifierAwareRearrangerEntry extends RearrangerEntry { +public enum ArrangementEntryMatcherSerializationTag { - @NotNull - RearrangerModifier getModifier(); + TYPE, MODIFIER, OR, AND, NAME } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializer.java new file mode 100644 index 000000000000..428b31da45b8 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ArrangementEntryMatcherSerializer.java @@ -0,0 +1,61 @@ +/* + * 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.match.serialization; + +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * Strategy that knows how to serialize {@link ArrangementEntryMatcher} objects of particular class. + *

+ * Implementations of this interface are expected to be thread-safe. + * + * @author Denis Zhdanov + * @since 7/19/12 12:31 PM + */ +public interface ArrangementEntryMatcherSerializer { + + /** + * @return class of the target matcher that can be processed by the current serializer + */ + @NotNull + Class getMatcherClass(); + + /** + * @return allowed element names of the serialized matcher. Are expected to be unique between + * {@link ArrangementEntryMatcherSerializer} implementations + */ + @NotNull + Set getTags(); + + @NotNull + Element serialize(@NotNull T matcher); + + /** + * Allows to deserialize target matcher object serialized previously via {@link #serialize(ArrangementEntryMatcher)} + * + * @param element serialized representation of the target matcher + * @return de-serialized matcher instance + * @throws IllegalArgumentException if current strategy doesn't know how to deserialize target matcher from the given + * element (the exception must not be thrown if given element's name is in + * {@link #getTags() target element names}) + */ + @NotNull + T deserialize(@NotNull Element element) throws IllegalArgumentException; +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByNameArrangementEntryMatcherSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByNameArrangementEntryMatcherSerializer.java new file mode 100644 index 000000000000..66bf247fef16 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByNameArrangementEntryMatcherSerializer.java @@ -0,0 +1,54 @@ +/* + * 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.match.serialization; + +import com.intellij.psi.codeStyle.arrangement.match.ByNameArrangementEntryMatcher; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; +import java.util.Set; + +/** + * @author Denis Zhdanov + * @since 7/19/12 6:40 PM + */ +public class ByNameArrangementEntryMatcherSerializer implements ArrangementEntryMatcherSerializer { + + @NotNull + @Override + public Class getMatcherClass() { + return ByNameArrangementEntryMatcher.class; + } + + @NotNull + @Override + public Set getTags() { + return EnumSet.of(ArrangementEntryMatcherSerializationTag.NAME); + } + + @NotNull + @Override + public Element serialize(@NotNull ByNameArrangementEntryMatcher matcher) { + return new Element(ArrangementEntryMatcherSerializationTag.NAME.toString()).setText(matcher.getPattern()); + } + + @NotNull + @Override + public ByNameArrangementEntryMatcher deserialize(@NotNull Element element) throws IllegalArgumentException { + return new ByNameArrangementEntryMatcher(element.getText()); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByTypeArrangementEntryMatcherSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByTypeArrangementEntryMatcherSerializer.java new file mode 100644 index 000000000000..948f97c13fa9 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/ByTypeArrangementEntryMatcherSerializer.java @@ -0,0 +1,81 @@ +/* + * 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.match.serialization; + +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType; +import com.intellij.psi.codeStyle.arrangement.match.ByTypeArrangementEntryMatcher; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; +import java.util.Set; + +/** + * @author Denis Zhdanov + * @since 7/19/12 12:44 PM + */ +public class ByTypeArrangementEntryMatcherSerializer implements ArrangementEntryMatcherSerializer { + + private static final String SEPARATOR = "|"; + + @NotNull + @Override + public Class getMatcherClass() { + return ByTypeArrangementEntryMatcher.class; + } + + @NotNull + @Override + public Set getTags() { + return EnumSet.of(ArrangementEntryMatcherSerializationTag.TYPE); + } + + @NotNull + @Override + public Element serialize(@NotNull ByTypeArrangementEntryMatcher matcher) { + StringBuilder buffer = new StringBuilder(); + for (ArrangementEntryType type : matcher.getTypes()) { + buffer.append(type).append(SEPARATOR); + } + if (buffer.length() > 0) { + buffer.setLength(buffer.length() - 1); + } + return new Element(ArrangementEntryMatcherSerializationTag.TYPE.toString()).setText(buffer.toString()); + } + + @NotNull + @Override + public ByTypeArrangementEntryMatcher deserialize(@NotNull Element element) throws IllegalArgumentException { + if (!ArrangementEntryMatcherSerializationTag.TYPE.toString().equals(element.getName())) { + throw new IllegalArgumentException(String.format( + "Can't deserialize matcher of class %s from an element with name '%s'. Expected name: '%s'", + getMatcherClass(), element.getName(), ArrangementEntryMatcherSerializationTag.TYPE.toString())); + } + + String text = element.getText(); + if (text == null) { + throw new IllegalArgumentException(String.format( + "Can't deserialize matcher of class %s. Reason: no information about target type(s) is found", getMatcherClass() + )); + } + + Set types = EnumSet.noneOf(ArrangementEntryType.class); + for (String s : text.split("\\" + SEPARATOR)) { + types.add(ArrangementEntryType.valueOf(s)); + } + return new ByTypeArrangementEntryMatcher(types); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/DefaultArrangementEntryMatcherSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/DefaultArrangementEntryMatcherSerializer.java new file mode 100644 index 000000000000..2d340d0efe0f --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/serialization/DefaultArrangementEntryMatcherSerializer.java @@ -0,0 +1,153 @@ +/* + * 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.match.serialization; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; +import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher; +import com.intellij.util.containers.ClassMap; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * @author Denis Zhdanov + * @since 7/19/12 1:00 PM + */ +public class DefaultArrangementEntryMatcherSerializer { + + private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName()); + + @NotNull private final ClassMap> mySerializers + = new ClassMap>(); + + @NotNull private final Map> myDeserializers = + new HashMap>(); + + public DefaultArrangementEntryMatcherSerializer() { + register(new ByTypeArrangementEntryMatcherSerializer()); + register(new ByNameArrangementEntryMatcherSerializer()); + register(new CompositeSerializer()); + } + + private void register(@NotNull ArrangementEntryMatcherSerializer serializer) { + mySerializers.put(serializer.getMatcherClass(), serializer); + for (ArrangementEntryMatcherSerializationTag tag : serializer.getTags()) { + ArrangementEntryMatcherSerializer old = myDeserializers.put(tag.toString(), serializer); + assert old == null : String.format("Multiple serializers are registered for the tag %s: %s and %s", tag.toString(), old, serializer); + } + } + + @SuppressWarnings("unchecked") + @Nullable + public Element serialize(@NotNull T matcher) { + ArrangementEntryMatcherSerializer serializer = (ArrangementEntryMatcherSerializer)mySerializers.get(matcher.getClass()); + if (serializer != null) { + return serializer.serialize(matcher); + } + StringBuilder buffer = new StringBuilder(); + for (ArrangementEntryMatcherSerializer s : mySerializers.values()) { + buffer.append(s.getMatcherClass()).append(", "); + } + if (buffer.length() > 0) { + buffer.setLength(buffer.length() - 2); + } + LOG.warn(String.format( + "Can't serialize arrangement entry matcher of class '%s'. Reason: no corresponding serializer is registered." + + "Available serializers can handle the following matchers: '%s'", matcher.getClass(), buffer.toString() + )); + return null; + } + + @SuppressWarnings("unchecked") + @Nullable + public T deserialize(@NotNull Element matcherElement) { + ArrangementEntryMatcherSerializer serializer = (ArrangementEntryMatcherSerializer)myDeserializers.get(matcherElement.getName()); + if (serializer != null) { + return serializer.deserialize(matcherElement); + } + StringBuilder buffer = new StringBuilder(); + for (String s : myDeserializers.keySet()) { + buffer.append(s).append(", "); + } + if (buffer.length() > 0) { + buffer.setLength(buffer.length() - 2); + } + LOG.warn(String.format( + "Can't deserialize an arrangement entry matcher from matchElement with name '%s'. Reason: only the following elements are supported: %s", + matcherElement.getName(), buffer + )); + return null; + } + + private class CompositeSerializer implements ArrangementEntryMatcherSerializer { + @NotNull + @Override + public Class getMatcherClass() { + return CompositeArrangementEntryMatcher.class; + } + + @NotNull + @Override + public Set getTags() { + return EnumSet.of(ArrangementEntryMatcherSerializationTag.AND, ArrangementEntryMatcherSerializationTag.OR); + } + + @NotNull + @Override + public Element serialize(@NotNull CompositeArrangementEntryMatcher matcher) { + ArrangementEntryMatcherSerializationTag tag = matcher.getOperator() == CompositeArrangementEntryMatcher.Operator.AND + ? ArrangementEntryMatcherSerializationTag.AND + : ArrangementEntryMatcherSerializationTag.OR; + Element result = new Element(tag.toString()); + for (ArrangementEntryMatcher childMatcher : matcher.getMatchers()) { + Element element = DefaultArrangementEntryMatcherSerializer.this.serialize(childMatcher); + if (element != null) { + result.addContent(element); + } + } + return result; + } + + @NotNull + @Override + public CompositeArrangementEntryMatcher deserialize(@NotNull Element element) throws IllegalArgumentException { + CompositeArrangementEntryMatcher.Operator operator = ArrangementEntryMatcherSerializationTag.OR.toString().equals(element.getName()) + ? CompositeArrangementEntryMatcher.Operator.OR + : CompositeArrangementEntryMatcher.Operator.AND; + + CompositeArrangementEntryMatcher result = null; + for (Object o : element.getChildren()) { + ArrangementEntryMatcher matcher = DefaultArrangementEntryMatcherSerializer.this.deserialize((Element)o); + if (matcher == null) { + continue; + } + if (result == null) { + result = new CompositeArrangementEntryMatcher(operator, matcher); + } + else { + result.addMatcher(matcher); + } + } + if (result == null) { + throw new IllegalArgumentException(String.format("Can't deserialize a matcher from element '%s'", element)); + } + return result; + } + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySortType.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySortType.java new file mode 100644 index 000000000000..ee0f0c5e0eb7 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySortType.java @@ -0,0 +1,25 @@ +/* + * 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.sort; + +/** + * @author Denis Zhdanov + * @since 7/19/12 6:24 PM + */ +public enum ArrangementEntrySortType { + + NO_SORT, BY_NAME +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySorter.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySorter.java new file mode 100644 index 000000000000..3a887db09759 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ArrangementEntrySorter.java @@ -0,0 +1,44 @@ +/* + * 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.sort; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Defines a contract for a strategy that knows how to sort {@link ArrangementEntry arrangement entries} + * {@link ArrangementEntryMatcher#isMatched(ArrangementEntry) matched} against the same rule using particular + * {@link ArrangementEntrySortType sort type}. + *

+ * Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations. + *

+ * Implementations of this interface are expected to be thread-safe. + * + * @author Denis Zhdanov + * @since 7/18/12 12:41 PM + */ +public interface ArrangementEntrySorter { + + /** + * Asks to sort given entries matched against the current rule. Given list defines a default order to be used. + * + * @param entries entries matched against the current rule + */ + void sort(@NotNull List entries); +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ByNameArrangementEntrySorter.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ByNameArrangementEntrySorter.java new file mode 100644 index 000000000000..d9a0360c9eab --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/sort/ByNameArrangementEntrySorter.java @@ -0,0 +1,63 @@ +/* + * 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.sort; + +import com.intellij.psi.codeStyle.arrangement.ArrangementEntry; +import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry; +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @author Denis Zhdanov + * @since 7/19/12 6:17 PM + */ +public class ByNameArrangementEntrySorter implements ArrangementEntrySorter { + + @Override + public void sort(@NotNull List entries) { + TObjectIntHashMap weights = new TObjectIntHashMap(); + for (int i = 0; i < entries.size(); i++) { + weights.put(entries.get(i), i); + } + Collections.sort(entries, new MyComparator(weights)); + } + + private static class MyComparator implements Comparator { + + @NotNull + private final TObjectIntHashMap myFallbackWeights; + + MyComparator(@NotNull TObjectIntHashMap weights) { + myFallbackWeights = weights; + } + + @Override + public int compare(ArrangementEntry o1, ArrangementEntry o2) { + if (o1 instanceof NameAwareArrangementEntry && o2 instanceof NameAwareArrangementEntry) { + String name1 = ((NameAwareArrangementEntry)o1).getName(); + String name2 = ((NameAwareArrangementEntry)o1).getName(); + if (name1 != null && name2 != null) { + return name1.compareTo(name2); + } + } + return myFallbackWeights.get(o1) - myFallbackWeights.get(o2); + } + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerFacade.java b/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerFacade.java deleted file mode 100644 index d60d2d39ce55..000000000000 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/RearrangerFacade.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.intellij.psi.codeStyle.rearranger; - -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.List; - -/** - * Encapsulates language-specific rearrangement logic. - *

- * Implementations of this interface are expected to be thread-safe. - * - * @author Denis Zhdanov - * @since 7/16/12 3:23 PM - * @param entry type - * @param rule type - */ -public interface RearrangerFacade { - - ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.rearranger.facade"); - - /** - * Allows to build rearranger-interested data for the given element. - * - * @param root root element which children should be parsed for the rearrangement - * @param range target offsets range to use for filtering given root's children - * @return given root's children that are subject for further rearrangement - */ - @NotNull - Collection parse(@NotNull PsiElement root, @NotNull TextRange range); - - /** - * Asks to sort given entries matched against the given rule. Given list defines a default order to be used. - * - * @param entries entries matched against the given rule - * @param rule target rule - */ - void sort(@NotNull List entries, @NotNull RearrangerRule rule); -} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerCompositeRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerCompositeRule.java deleted file mode 100644 index 0bc59ca9833e..000000000000 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerCompositeRule.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.rearranger.rule; - -import com.intellij.psi.codeStyle.rearranger.RearrangerEntry; -import com.intellij.psi.codeStyle.rearranger.RearrangerRule; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @author Denis Zhdanov - * @since 7/17/12 11:26 AM - */ -public class RearrangerCompositeRule implements RearrangerRule { - - @NotNull private final List myRules = new ArrayList(); - @NotNull private final Operator myOperator; - - public RearrangerCompositeRule(@NotNull Operator operator, @NotNull RearrangerRule ... rules) { - myOperator = operator; - myRules.addAll(Arrays.asList(rules)); - } - - @Override - public boolean isMatched(@NotNull RearrangerEntry entry) { - for (RearrangerRule rule : myRules) { - boolean matched = rule.isMatched(entry); - if (matched && myOperator == Operator.OR) { - return true; - } - else if (!matched && myOperator == Operator.AND) { - return false; - } - } - return myOperator == Operator.AND; - } - - @NotNull - public Operator getOperator() { - return myOperator; - } - - public void addRule(@NotNull RearrangerRule rule) { - myRules.add(rule); - } - - public enum Operator {AND, OR} -} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerRuleUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerRuleUtil.java deleted file mode 100644 index b1d63954c258..000000000000 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerRuleUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.rearranger.rule; - -import com.intellij.psi.codeStyle.rearranger.RearrangerRule; -import org.jetbrains.annotations.NotNull; - -/** - * @author Denis Zhdanov - * @since 7/17/12 11:24 AM - */ -public class RearrangerRuleUtil { - - private RearrangerRuleUtil() { - } - - @NotNull - public static RearrangerRule or(@NotNull RearrangerRule ... rules) { - return combine(RearrangerCompositeRule.Operator.OR, rules); - } - - @NotNull - public static RearrangerRule and(@NotNull RearrangerRule ... rules) { - return combine(RearrangerCompositeRule.Operator.AND, rules); - } - - @NotNull - private static RearrangerRule combine(@NotNull RearrangerCompositeRule.Operator operator, @NotNull RearrangerRule... rules) { - RearrangerCompositeRule composite = null; - for (RearrangerRule rule : rules) { - if (rule instanceof RearrangerCompositeRule && ((RearrangerCompositeRule)(rule)).getOperator() == operator) { - composite = (RearrangerCompositeRule)rule; - break; - } - } - - if (composite == null) { - return new RearrangerCompositeRule(operator, rules); - } - - for (RearrangerRule rule : rules) { - if (rule != composite) { - composite.addRule(rule); - } - } - return composite; - } -} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerTypeRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerTypeRule.java deleted file mode 100644 index c7a71377925e..000000000000 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/rearranger/rule/RearrangerTypeRule.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.rearranger.rule; - -import com.intellij.psi.codeStyle.rearranger.RearrangerEntry; -import com.intellij.psi.codeStyle.rearranger.RearrangerEntryType; -import com.intellij.psi.codeStyle.rearranger.RearrangerRule; -import com.intellij.psi.codeStyle.rearranger.TypeAwareRearrangerEntry; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Set; - -/** - * Filters {@link RearrangerEntry entries} by {@link TypeAwareRearrangerEntry#getType() their types}. - *

- * Note: type-unaware entry will not be matched by the current rule. - *

- * Thread-safe. - * - * @author Denis Zhdanov - * @since 7/17/12 11:19 AM - */ -public class RearrangerTypeRule implements RearrangerRule { - - private final Set myTypes = EnumSet.noneOf(RearrangerEntryType.class); - - public RearrangerTypeRule(@NotNull RearrangerEntryType ... interestedTypes) { - myTypes.addAll(Arrays.asList(interestedTypes)); - } - - @Override - public boolean isMatched(@NotNull RearrangerEntry entry) { - if (entry instanceof TypeAwareRearrangerEntry) { - return myTypes.contains(((TypeAwareRearrangerEntry)(entry)).getType()); - } - return false; - } -} diff --git a/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java new file mode 100644 index 000000000000..37948f38fa31 --- /dev/null +++ b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementRuleSerializerTest.java @@ -0,0 +1,73 @@ +/* + * 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.match; + +import com.intellij.psi.codeStyle.arrangement.ArrangementRule; +import com.intellij.psi.codeStyle.arrangement.ArrangementRuleSerializer; +import com.intellij.psi.codeStyle.arrangement.ArrangementRuleUtil; +import com.intellij.psi.codeStyle.arrangement.DefaultArrangementRuleSerializer; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Denis Zhdanov + * @since 07/18/2012 + */ +public class DefaultArrangementRuleSerializerTest { + + private ArrangementRuleSerializer mySerializer; + + @Before + public void setUp() { + mySerializer = DefaultArrangementRuleSerializer.INSTANCE; + } + + @Test + public void simpleMatchers() { + doTest(new ByTypeArrangementEntryMatcher(ArrangementEntryType.CLASS)); + doTest(new ByTypeArrangementEntryMatcher(ArrangementEntryType.values())); + } + + @Test + public void compositeMatchers() { + doTest(ArrangementRuleUtil.or( + new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD), + new ByTypeArrangementEntryMatcher(ArrangementEntryType.METHOD)) + ); + + doTest(ArrangementRuleUtil.and( + ArrangementRuleUtil.or( + new ByTypeArrangementEntryMatcher(ArrangementEntryType.METHOD), + new ByNameArrangementEntryMatcher("get*") + ) + )); + } + + private void doTest(@NotNull ArrangementEntryMatcher matcher) { + doTest(new ArrangementRule(matcher)); + } + + private void doTest(@NotNull ArrangementRule rule) { + Element element = mySerializer.serialize(rule); + assertNotNull(String.format("Can't serialize rule '%s'", rule), element); + assertEquals(rule, mySerializer.deserialize(element)); + } +}