IDEA-19061 Integrate the Rearranger-plugin into core-IDEA

1. Standard settings-based entry matcher (de)serialization;
2. Refactoring;
This commit is contained in:
Denis.Zhdanov
2012-08-27 16:54:37 +04:00
parent 612c9962d2
commit f183023405
19 changed files with 286 additions and 531 deletions
@@ -16,8 +16,9 @@
package com.intellij.psi.codeStyle.arrangement
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType
import com.intellij.psi.codeStyle.arrangement.match.ByTypeArrangementEntryMatcher
/**
* @author Denis Zhdanov
* @since 7/20/12 2:45 PM
@@ -26,6 +27,7 @@ class JavaRearrangerByTypeTest extends AbstractRearrangerTest {
JavaRearrangerByTypeTest() {
fileType = JavaFileType.INSTANCE
language = JavaLanguage.INSTANCE
}
void testFieldsBeforeMethods() {
@@ -52,7 +54,7 @@ class Test2 {
public void test() {
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
[new ArrangementRule(atom(ArrangementEntryType.FIELD))]
)
}
@@ -96,7 +98,7 @@ class Test {
return null;
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
[new ArrangementRule(atom(ArrangementEntryType.FIELD))]
)
}
@@ -134,7 +136,7 @@ class Test {
});
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
[new ArrangementRule(atom(ArrangementEntryType.FIELD))]
)
}
@@ -172,7 +174,7 @@ class Test {
});
}
}''',
[new ArrangementRule(new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD))]
[new ArrangementRule(atom(ArrangementEntryType.FIELD))]
)
}
}
@@ -16,7 +16,9 @@
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.sort.ArrangementEntrySortType;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import org.jetbrains.annotations.NotNull;
/**
@@ -31,14 +33,18 @@ import org.jetbrains.annotations.NotNull;
*/
public class ArrangementRule {
@NotNull private final ArrangementEntryMatcher myMatcher;
@NotNull private final ArrangementEntrySortType mySortType;
@NotNull private final ArrangementEntryMatcher myMatcher;
@NotNull private final ArrangementEntryOrderType mySortType;
public ArrangementRule(@NotNull ArrangementEntryMatcher matcher) {
this(matcher, ArrangementEntrySortType.NO_SORT);
public ArrangementRule(@NotNull ArrangementMatchCondition condition) {
this(new StdArrangementEntryMatcher(condition));
}
public ArrangementRule(@NotNull ArrangementEntryMatcher matcher, @NotNull ArrangementEntrySortType type) {
public ArrangementRule(@NotNull ArrangementEntryMatcher matcher) {
this(matcher, ArrangementEntryOrderType.KEEP);
}
public ArrangementRule(@NotNull ArrangementEntryMatcher matcher, @NotNull ArrangementEntryOrderType type) {
myMatcher = matcher;
mySortType = type;
}
@@ -49,7 +55,7 @@ public class ArrangementRule {
}
@NotNull
public ArrangementEntrySortType getSorter() {
public ArrangementEntryOrderType getSorter() {
return mySortType;
}
@@ -18,11 +18,10 @@ package com.intellij.psi.codeStyle.arrangement;
import com.intellij.lang.Language;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -111,8 +110,6 @@ public class ArrangementUtil {
}
//endregion
//region Rule composition
@NotNull
public static ArrangementMatchCondition and(@NotNull ArrangementMatchCondition... nodes) {
final ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
@@ -139,42 +136,6 @@ public class ArrangementUtil {
}
return result.getOperands().size() == 1 ? result.getOperands().iterator().next() : result;
}
// TODO den remove
@NotNull
public static ArrangementEntryMatcher or(@NotNull ArrangementEntryMatcher... matchers) {
return combine(ArrangementOperator.OR, matchers);
}
// TODO den remove
@NotNull
public static ArrangementEntryMatcher and(@NotNull ArrangementEntryMatcher... matchers) {
return combine(ArrangementOperator.AND, matchers);
}
// TODO den remove
@NotNull
private static ArrangementEntryMatcher combine(@NotNull ArrangementOperator 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
//region ArrangementEntry
@@ -16,8 +16,8 @@
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 com.intellij.psi.codeStyle.arrangement.match.DefaultArrangementEntryMatcherSerializer;
import com.intellij.psi.codeStyle.arrangement.order.ArrangementEntryOrderType;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -58,9 +58,9 @@ public class DefaultArrangementRuleSerializer implements ArrangementRuleSerializ
}
Element sortElement = element.getChild(SORT_TYPE_ELEMENT_NAME);
ArrangementEntrySortType sortType = ArrangementEntrySortType.NO_SORT;
ArrangementEntryOrderType sortType = ArrangementEntryOrderType.KEEP;
if (sortElement != null) {
sortType = ArrangementEntrySortType.valueOf(sortElement.getText());
sortType = ArrangementEntryOrderType.valueOf(sortElement.getText());
}
return new ArrangementRule(matcher, sortType);
@@ -0,0 +1,149 @@
/*
* 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.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.util.containers.HashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 7/19/12 1:00 PM
*/
public class DefaultArrangementEntryMatcherSerializer {
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementEntryMatcherSerializer.class.getName());
private static final Set<String> COMPOSITE_OPERATORS = new HashSet<String>();
private static final Set<String> ATOM_SETTINGS_TYPES = new HashSet<String>();
static {
for (ArrangementOperator operator : ArrangementOperator.values()) {
COMPOSITE_OPERATORS.add(operator.toString());
}
for (ArrangementSettingType type : ArrangementSettingType.values()) {
ATOM_SETTINGS_TYPES.add(type.toString());
}
}
@SuppressWarnings("MethodMayBeStatic")
@Nullable
public <T extends ArrangementEntryMatcher> Element serialize(@NotNull T matcher) {
if (matcher instanceof StdArrangementEntryMatcher) {
return serialize(((StdArrangementEntryMatcher)matcher).getCondition());
}
LOG.warn(String.format(
"Can't serialize arrangement entry matcher of class '%s'. Reason: expected to find '%s' instance instead",
matcher.getClass(), StdArrangementEntryMatcher.class
));
return null;
}
@NotNull
private static Element serialize(@NotNull ArrangementMatchCondition condition) {
MySerializationVisitor visitor = new MySerializationVisitor();
condition.invite(visitor);
return visitor.result;
}
@SuppressWarnings("MethodMayBeStatic")
@Nullable
public ArrangementEntryMatcher deserialize(@NotNull Element matcherElement) {
ArrangementMatchCondition condition = deserializeCondition(matcherElement);
return condition == null ? null : new StdArrangementEntryMatcher(condition);
}
@Nullable
private static ArrangementMatchCondition deserializeCondition(@NotNull Element matcherElement) {
String name = matcherElement.getName();
if (!COMPOSITE_OPERATORS.contains(name)) {
if (ATOM_SETTINGS_TYPES.contains(name)) {
return deserializeAtomCondition(matcherElement);
}
else {
LOG.warn(String.format(
"Can't deserialize an arrangement entry matcher from matchElement with name '%s'. Reason: only the following elements"
+ "are supported: %s and %s",
name, COMPOSITE_OPERATORS, ATOM_SETTINGS_TYPES
));
return null;
}
}
else {
ArrangementCompositeMatchCondition composite = new ArrangementCompositeMatchCondition(ArrangementOperator.valueOf(name));
for (Object child : matcherElement.getChildren()) {
ArrangementMatchCondition deserialised = deserializeCondition((Element)child);
if (deserialised != null) {
composite.addOperand(deserialised);
}
}
return composite;
}
}
@Nullable
private static ArrangementMatchCondition deserializeAtomCondition(@NotNull Element matcherElement) {
ArrangementSettingType settingType = ArrangementSettingType.valueOf(matcherElement.getName());
Object value;
switch (settingType) {
case TYPE: value = ArrangementEntryType.valueOf(matcherElement.getText()); break;
case MODIFIER: value = ArrangementModifier.valueOf(matcherElement.getText()); break;
default:
LOG.warn(String.format(
"Can't deserialize an arrangement entry matcher from element of type '%s' with text '%s'",
settingType, matcherElement.getText()
));
return null;
}
return new ArrangementAtomMatchCondition(settingType, value);
}
private static class MySerializationVisitor implements ArrangementMatchConditionVisitor {
Element result;
Element parent;
@Override
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
Element element = new Element(condition.getType().toString()).setText(condition.getValue().toString());
if (result == null) {
result = element;
}
if (parent != null) {
parent.addContent(element);
}
}
@Override
public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
Element composite = new Element(condition.getOperator().toString());
if (result == null) {
result = composite;
}
if (parent != null) {
parent.addContent(composite);
}
parent = composite;
for (ArrangementMatchCondition c : condition.getOperands()) {
c.invite(this);
}
}
}
}
@@ -37,12 +37,12 @@ import java.util.Set;
* @author Denis Zhdanov
* @since 8/26/12 11:07 PM
*/
public class StandardArrangementEntryMatcher implements ArrangementEntryMatcher {
public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
@NotNull private final ArrangementMatchCondition myCondition;
@NotNull private final ArrangementEntryMatcher myDelegate;
public StandardArrangementEntryMatcher(@NotNull ArrangementMatchCondition condition) {
public StdArrangementEntryMatcher(@NotNull ArrangementMatchCondition condition) {
myCondition = condition;
myDelegate = doBuildMatcher(condition);
}
@@ -1,27 +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.arrangement.match.serialization;
import org.jetbrains.annotations.NotNull;
/**
* @author Denis Zhdanov
* @since 7/19/12 12:45 PM
*/
public enum ArrangementEntryMatcherSerializationTag {
TYPE, MODIFIER, OR, AND, NAME
}
@@ -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.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.
* <p/>
* Implementations of this interface are expected to be thread-safe.
*
* @author Denis Zhdanov
* @since 7/19/12 12:31 PM
*/
public interface ArrangementEntryMatcherSerializer<T extends ArrangementEntryMatcher> {
/**
* @return class of the target matcher that can be processed by the current serializer
*/
@NotNull
Class<T> getMatcherClass();
/**
* @return allowed element names of the serialized matcher. Are expected to be unique between
* {@link ArrangementEntryMatcherSerializer} implementations
*/
@NotNull
Set<ArrangementEntryMatcherSerializationTag> 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;
}
@@ -1,54 +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.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<ByNameArrangementEntryMatcher> {
@NotNull
@Override
public Class<ByNameArrangementEntryMatcher> getMatcherClass() {
return ByNameArrangementEntryMatcher.class;
}
@NotNull
@Override
public Set<ArrangementEntryMatcherSerializationTag> 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());
}
}
@@ -1,81 +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.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<ByTypeArrangementEntryMatcher> {
private static final String SEPARATOR = "|";
@NotNull
@Override
public Class<ByTypeArrangementEntryMatcher> getMatcherClass() {
return ByTypeArrangementEntryMatcher.class;
}
@NotNull
@Override
public Set<ArrangementEntryMatcherSerializationTag> 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<ArrangementEntryType> types = EnumSet.noneOf(ArrangementEntryType.class);
for (String s : text.split("\\" + SEPARATOR)) {
types.add(ArrangementEntryType.valueOf(s));
}
return new ByTypeArrangementEntryMatcher(types);
}
}
@@ -1,154 +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.arrangement.match.serialization;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.arrangement.ArrangementOperator;
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<ArrangementEntryMatcherSerializer<?>> mySerializers
= new ClassMap<ArrangementEntryMatcherSerializer<?>>();
@NotNull private final Map<String /* element name */, ArrangementEntryMatcherSerializer<?>> myDeserializers =
new HashMap<String, ArrangementEntryMatcherSerializer<?>>();
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 <T extends ArrangementEntryMatcher> Element serialize(@NotNull T matcher) {
ArrangementEntryMatcherSerializer<T> serializer = (ArrangementEntryMatcherSerializer<T>)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 extends ArrangementEntryMatcher> T deserialize(@NotNull Element matcherElement) {
ArrangementEntryMatcherSerializer<T> serializer = (ArrangementEntryMatcherSerializer<T>)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<CompositeArrangementEntryMatcher> {
@NotNull
@Override
public Class<CompositeArrangementEntryMatcher> getMatcherClass() {
return CompositeArrangementEntryMatcher.class;
}
@NotNull
@Override
public Set<ArrangementEntryMatcherSerializationTag> getTags() {
return EnumSet.of(ArrangementEntryMatcherSerializationTag.AND, ArrangementEntryMatcherSerializationTag.OR);
}
@NotNull
@Override
public Element serialize(@NotNull CompositeArrangementEntryMatcher matcher) {
ArrangementEntryMatcherSerializationTag tag = matcher.getOperator() == ArrangementOperator.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 {
ArrangementOperator operator = ArrangementEntryMatcherSerializationTag.OR.toString().equals(element.getName())
? ArrangementOperator.OR
: ArrangementOperator.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;
}
}
}
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.sort;
package com.intellij.psi.codeStyle.arrangement.order;
/**
* @author Denis Zhdanov
* @since 7/19/12 6:24 PM
*/
public enum ArrangementEntrySortType {
public enum ArrangementEntryOrderType {
NO_SORT, BY_NAME
KEEP, BY_NAME
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.sort;
package com.intellij.psi.codeStyle.arrangement.order;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
@@ -22,9 +22,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Defines a contract for a strategy that knows how to sort {@link ArrangementEntry arrangement entries}
* Defines a contract for a strategy that knows how to order {@link ArrangementEntry arrangement entries}
* {@link ArrangementEntryMatcher#isMatched(ArrangementEntry) matched} against the same rule using particular
* {@link ArrangementEntrySortType sort type}.
* {@link ArrangementEntryOrderType order type}.
* <p/>
* Implementations of this interface are expected to provide correct {@link #equals(Object)} & {@link #hashCode()} implementations.
* <p/>
@@ -33,12 +33,12 @@ import java.util.List;
* @author Denis Zhdanov
* @since 7/18/12 12:41 PM
*/
public interface ArrangementEntrySorter {
public interface ArrangementEntryOrderer {
/**
* 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<? extends ArrangementEntry> entries);
void order(@NotNull List<? extends ArrangementEntry> entries);
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.codeStyle.arrangement.sort;
package com.intellij.psi.codeStyle.arrangement.order;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.NameAwareArrangementEntry;
@@ -28,10 +28,10 @@ import java.util.List;
* @author Denis Zhdanov
* @since 7/19/12 6:17 PM
*/
public class ByNameArrangementEntrySorter implements ArrangementEntrySorter {
public class ByNameArrangementEntryOrderer implements ArrangementEntryOrderer {
@Override
public void sort(@NotNull List<? extends ArrangementEntry> entries) {
public void order(@NotNull List<? extends ArrangementEntry> entries) {
TObjectIntHashMap<ArrangementEntry> weights = new TObjectIntHashMap<ArrangementEntry>();
for (int i = 0; i < entries.size(); i++) {
weights.put(entries.get(i), i);
@@ -0,0 +1,65 @@
/*
* 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.ArrangementOperator;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Denis Zhdanov
* @since 07/18/2012
*/
public class DefaultArrangementEntryMatcherSerializerTest {
private final DefaultArrangementEntryMatcherSerializer mySerializer = new DefaultArrangementEntryMatcherSerializer();
@Test
public void simpleMatchers() {
doTest(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.CLASS));
doTest(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE));
}
@Test
public void compositeMatchers() {
ArrangementCompositeMatchCondition condition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.SYNCHRONIZED));
doTest(condition);
condition = new ArrangementCompositeMatchCondition(ArrangementOperator.AND);
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL));
}
private void doTest(@NotNull ArrangementMatchCondition condition) {
Element element = mySerializer.serialize(new StdArrangementEntryMatcher(condition));
assertNotNull(String.format("Can't serialize match condition '%s'", condition), element);
ArrangementEntryMatcher matcher = mySerializer.deserialize(element);
assertNotNull(matcher);
assertTrue(matcher instanceof StdArrangementEntryMatcher);
assertEquals(condition, ((StdArrangementEntryMatcher)matcher).getCondition());
}
}
@@ -1,73 +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.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementRule;
import com.intellij.psi.codeStyle.arrangement.ArrangementRuleSerializer;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
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(ArrangementUtil.or(
new ByTypeArrangementEntryMatcher(ArrangementEntryType.FIELD),
new ByTypeArrangementEntryMatcher(ArrangementEntryType.METHOD))
);
doTest(ArrangementUtil.and(
ArrangementUtil.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));
}
}
@@ -61,7 +61,7 @@ public class StandardArrangementEntryMatcherTest {
public void atomCondition() {
ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD);
StandardArrangementEntryMatcher matcher = new StandardArrangementEntryMatcher(condition);
StdArrangementEntryMatcher matcher = new StdArrangementEntryMatcher(condition);
assertEquals(condition, matcher.getCondition());
final TypeAwareArrangementEntry fieldEntry = myMockery.mock(TypeAwareArrangementEntry.class, "field");
@@ -84,7 +84,7 @@ public class StandardArrangementEntryMatcherTest {
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD));
condition.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC));
StandardArrangementEntryMatcher matcher = new StandardArrangementEntryMatcher(condition);
StdArrangementEntryMatcher matcher = new StdArrangementEntryMatcher(condition);
assertEquals(condition, matcher.getCondition());
final TypeAwareArrangementEntry fieldEntry = myMockery.mock(TypeAwareArrangementEntry.class, "field");
+1
View File
@@ -21,6 +21,7 @@
<orderEntry type="library" exported="" scope="TEST" name="Mocks" level="project" />
<orderEntry type="module" module-name="java-runtime" exported="" />
<orderEntry type="module" module-name="vcs-impl" />
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
</component>
</module>
@@ -15,23 +15,27 @@
*/
package com.intellij.psi.codeStyle.arrangement
import com.intellij.lang.java.JavaLanguage
import com.intellij.lang.Language
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.util.TextRange
import com.intellij.psi.codeStyle.CodeStyleSettings
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
/**
* @author Denis Zhdanov
* @since 7/20/12 2:54 PM
*/
abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase {
abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFixtureTestCase {
def FileType fileType
FileType fileType
Language language;
@Override
protected void setUp() {
@@ -44,7 +48,22 @@ abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase {
CodeStyleSettingsManager.getInstance(myFixture.project).dropTemporarySettings()
super.tearDown()
}
@NotNull
protected ArrangementAtomMatchCondition atom(@NotNull Object condition) {
def type;
if (condition in ArrangementEntryType) {
type = ArrangementSettingType.TYPE;
}
else if (condition in ArrangementModifier) {
type = ArrangementSettingType.MODIFIER
}
else {
throw new IllegalArgumentException("Unexpected condition of type '${condition.class}': $condition")
}
new ArrangementAtomMatchCondition(type, condition)
}
protected void doTest(@NotNull String initial,
@NotNull String expected,
@NotNull List<ArrangementRule> rules,
@@ -52,18 +71,20 @@ abstract class AbstractRearrangerTest extends LightCodeInsightFixtureTestCase {
{
def (String textToUse, List<TextRange> rangesToUse) = parseRanges(initial)
if (rangesToUse && ranges) {
fail("Duplicate ranges info detected: explicitly given: $ranges, derived from markup: $rangesToUse. Text:\n$initial")
junit.framework.Assert.fail(
"Duplicate ranges info detected: explicitly given: $ranges, derived from markup: $rangesToUse. Text:\n$initial"
)
}
if (!rangesToUse) {
rangesToUse = ranges ?: [TextRange.from(0, initial.length())]
}
myFixture.configureByText(fileType, textToUse)
def settings = CodeStyleSettingsManager.getInstance(myFixture.project).currentSettings.getCommonSettings(JavaLanguage.INSTANCE)
def settings = CodeStyleSettingsManager.getInstance(myFixture.project).currentSettings.getCommonSettings(language)
settings.arrangementRules = rules
ArrangementEngine engine = ServiceManager.getService(myFixture.project, ArrangementEngine)
engine.arrange(myFixture.file, rangesToUse);
assertEquals(expected, myFixture.editor.document.text);
junit.framework.Assert.assertEquals(expected, myFixture.editor.document.text);
}
@NotNull