blob: 25ede0477ebade97eec93c3017e0fe92adac7733 [file] [log] [blame]
package com.intellij.xml.arrangement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.*;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_ATTRIBUTE;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.XML_TAG;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.General.*;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.KEEP;
/**
* @author Eugene.Kudelevsky
*/
public class XmlRearranger
implements Rearranger<XmlElementArrangementEntry>,
ArrangementStandardSettingsAware {
private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES = ContainerUtilRt.newLinkedHashSet(XML_TAG, XML_ATTRIBUTE);
private static final List<StdArrangementMatchRule> DEFAULT_MATCH_RULES = new ArrayList<StdArrangementMatchRule>();
private static final StdArrangementSettings DEFAULT_SETTINGS;
static {
DEFAULT_MATCH_RULES.add(new StdArrangementMatchRule(new StdArrangementEntryMatcher(
new ArrangementAtomMatchCondition(StdArrangementTokens.Regexp.NAME, "xmlns:.*"))));
DEFAULT_SETTINGS = StdArrangementSettings.createByMatchRules(
Collections.<ArrangementGroupingRule>emptyList(), DEFAULT_MATCH_RULES);
}
private static final DefaultArrangementSettingsSerializer SETTINGS_SERIALIZER = new DefaultArrangementSettingsSerializer(DEFAULT_SETTINGS);
@NotNull
public static StdArrangementMatchRule attrArrangementRule(@NotNull String nameFilter,
@NotNull String namespaceFilter,
@NotNull ArrangementSettingsToken orderType) {
return new StdArrangementMatchRule(new StdArrangementEntryMatcher(ArrangementUtil.combine(
new ArrangementAtomMatchCondition(StdArrangementTokens.Regexp.NAME, nameFilter),
new ArrangementAtomMatchCondition(StdArrangementTokens.Regexp.XML_NAMESPACE, namespaceFilter)
)), orderType);
}
@NotNull
@Override
public ArrangementSettingsSerializer getSerializer() {
return SETTINGS_SERIALIZER;
}
@Nullable
@Override
public StdArrangementSettings getDefaultSettings() {
return DEFAULT_SETTINGS;
}
@Override
public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) {
return SUPPORTED_TYPES.contains(token) || StdArrangementTokens.Regexp.NAME.equals(token) || StdArrangementTokens.Regexp.XML_NAMESPACE.equals(token) || KEEP.equals(token)
|| BY_NAME.equals(token) || SUPPORTED_TYPES.contains(token);
}
@NotNull
@Override
public Collection<Set<ArrangementSettingsToken>> getMutexes() {
return Collections.singleton(SUPPORTED_TYPES);
}
@Nullable
@Override
public Pair<XmlElementArrangementEntry, List<XmlElementArrangementEntry>> parseWithNew(@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull PsiElement element,
@NotNull ArrangementSettings settings)
{
final XmlArrangementParseInfo newEntryInfo = new XmlArrangementParseInfo();
element.accept(new XmlArrangementVisitor(newEntryInfo, Collections.singleton(element.getTextRange())));
if (newEntryInfo.getEntries().size() != 1) {
return null;
}
final XmlElementArrangementEntry entry = newEntryInfo.getEntries().get(0);
final XmlArrangementParseInfo existingEntriesInfo = new XmlArrangementParseInfo();
root.accept(new XmlArrangementVisitor(existingEntriesInfo, ranges));
return Pair.create(entry, existingEntriesInfo.getEntries());
}
@NotNull
@Override
public List<XmlElementArrangementEntry> parse(@NotNull PsiElement root,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@NotNull ArrangementSettings settings) {
final XmlArrangementParseInfo parseInfo = new XmlArrangementParseInfo();
root.accept(new XmlArrangementVisitor(parseInfo, ranges));
return parseInfo.getEntries();
}
@Override
public int getBlankLines(@NotNull CodeStyleSettings settings,
@Nullable XmlElementArrangementEntry parent,
@Nullable XmlElementArrangementEntry previous,
@NotNull XmlElementArrangementEntry target) {
return -1;
}
@Nullable
@Override
public List<CompositeArrangementSettingsToken> getSupportedGroupingTokens() {
return null;
}
@Nullable
@Override
public List<CompositeArrangementSettingsToken> getSupportedMatchingTokens() {
return ContainerUtilRt.newArrayList(
new CompositeArrangementSettingsToken(TYPE, SUPPORTED_TYPES),
new CompositeArrangementSettingsToken(StdArrangementTokens.Regexp.NAME),
new CompositeArrangementSettingsToken(StdArrangementTokens.Regexp.XML_NAMESPACE),
new CompositeArrangementSettingsToken(ORDER, KEEP, BY_NAME)
);
}
@NotNull
@Override
public ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
throw new IllegalArgumentException("Can't build a matcher for condition " + condition);
}
}