Search in sources :

Example 11 with ArrangementSectionRule

use of com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule in project intellij-community by JetBrains.

the class ArrangementSettingsSerializationTest method testCustomTokenSerializeLessThanDefault.

@Test
public void testCustomTokenSerializeLessThanDefault() throws IOException {
    final Set<StdArrangementRuleAliasToken> tokens = ContainerUtil.newHashSet(visibilityToken());
    final ArrayList<ArrangementGroupingRule> groupings = ContainerUtil.newArrayList(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
    final ArrayList<ArrangementSectionRule> rules = ContainerUtil.newArrayList(section(true, FIELD));
    final StdArrangementExtendableSettings settings = extendableSettings(groupings, rules, tokens);
    final Set<StdArrangementRuleAliasToken> defaultTokens = ContainerUtil.newHashSet(visibilityToken(), modifiersToken());
    final StdArrangementExtendableSettings defaultSettings = extendableSettings(groupings, rules, defaultTokens);
    final Element holder = doSerializationTest(settings, defaultSettings);
    final String expected = "<holder>\n" + "  <tokens>\n" + "    <token id=\"visibility\" name=\"visibility\">\n" + "      <rules>\n" + "        <rule>\n" + "          <match>\n" + "            <AND>\n" + "              <PUBLIC>true</PUBLIC>\n" + "            </AND>\n" + "          </match>\n" + "        </rule>\n" + "        <rule>\n" + "          <match>\n" + "            <AND>\n" + "              <PROTECTED>true</PROTECTED>\n" + "            </AND>\n" + "          </match>\n" + "        </rule>\n" + "        <rule>\n" + "          <match>\n" + "            <AND>\n" + "              <PRIVATE>true</PRIVATE>\n" + "            </AND>\n" + "          </match>\n" + "        </rule>\n" + "      </rules>\n" + "    </token>\n" + "  </tokens>\n" + "</holder>";
    assertXmlOutputEquals(expected, holder);
}
Also used : StdArrangementRuleAliasToken(com.intellij.psi.codeStyle.arrangement.std.StdArrangementRuleAliasToken) ArrangementGroupingRule(com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule) StdArrangementExtendableSettings(com.intellij.psi.codeStyle.arrangement.std.StdArrangementExtendableSettings) Element(org.jdom.Element) ArrangementSectionRule(com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule) Test(org.junit.Test)

Example 12 with ArrangementSectionRule

use of com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule in project intellij-community by JetBrains.

the class MemberOrderService method getAnchor.

/**
   * Tries to find an element at the given context which should be the previous sibling for the given 'member'element according to the
   * {@link CommonCodeStyleSettings#getArrangementSettings() user-defined arrangement rules}.
   * <p/>
   * E.g. the IDE might generate given 'member' element and wants to know element after which it should be inserted
   * 
   * @param member    target member which anchor should be calculated
   * @param settings  code style settings to use
   * @param context   given member's context
   * @return          given member's anchor if the one can be computed;
   *                  given 'context' element if given member should be the first child
   *                  {@code null} otherwise
   */
@SuppressWarnings("MethodMayBeStatic")
@Nullable
public PsiElement getAnchor(@NotNull PsiElement member, @NotNull CommonCodeStyleSettings settings, @NotNull PsiElement context) {
    Language language = context.getLanguage();
    Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(language);
    if (rearranger == null) {
        return null;
    }
    ArrangementSettings arrangementSettings = settings.getArrangementSettings();
    if (arrangementSettings == null && rearranger instanceof ArrangementStandardSettingsAware) {
        arrangementSettings = ((ArrangementStandardSettingsAware) rearranger).getDefaultSettings();
    }
    if (arrangementSettings == null) {
        return null;
    }
    Pair<? extends ArrangementEntry, ? extends List<? extends ArrangementEntry>> pair = rearranger.parseWithNew(context, null, Collections.singleton(context.getTextRange()), member, arrangementSettings);
    if (pair == null || pair.second.isEmpty()) {
        return null;
    }
    ArrangementEntry memberEntry = pair.first;
    List<? extends ArrangementEntry> entries = pair.second;
    ArrangementEntry parentEntry = entries.get(0);
    List<? extends ArrangementEntry> nonArranged = parentEntry.getChildren();
    List<ArrangementEntry> entriesWithNew = new ArrayList<>(nonArranged);
    entriesWithNew.add(memberEntry);
    //TODO: check insert new element
    final List<? extends ArrangementMatchRule> rulesByPriority = arrangementSettings.getRulesSortedByPriority();
    final List<ArrangementSectionRule> extendedSectionRules = ArrangementUtil.getExtendedSectionRules(arrangementSettings);
    List<ArrangementEntry> arranged = ArrangementEngine.arrange(entriesWithNew, extendedSectionRules, rulesByPriority, null);
    int i = arranged.indexOf(memberEntry);
    if (i <= 0) {
        return context;
    }
    ArrangementEntry anchorEntry = null;
    if (i >= arranged.size() - 1) {
        anchorEntry = nonArranged.get(nonArranged.size() - 1);
    } else {
        Set<ArrangementEntry> entriesBelow = new HashSet<>();
        entriesBelow.addAll(arranged.subList(i + 1, arranged.size()));
        for (ArrangementEntry entry : nonArranged) {
            if (entriesBelow.contains(entry)) {
                break;
            }
            anchorEntry = entry;
        }
    }
    if (anchorEntry == null) {
        return context;
    }
    int offset = anchorEntry.getEndOffset() - 1 - context.getTextRange().getStartOffset();
    PsiElement element = context.findElementAt(offset);
    for (PsiElement e = element; e != null && e.getTextRange().getStartOffset() >= anchorEntry.getStartOffset(); e = e.getParent()) {
        element = e;
    }
    return element;
}
Also used : ArrangementStandardSettingsAware(com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware) ArrayList(java.util.ArrayList) Language(com.intellij.lang.Language) ArrangementSectionRule(com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule) PsiElement(com.intellij.psi.PsiElement) HashSet(com.intellij.util.containers.HashSet) Nullable(org.jetbrains.annotations.Nullable)

Example 13 with ArrangementSectionRule

use of com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule in project intellij-community by JetBrains.

the class ArrangementEngine method arrange.

/**
   * Arranges (re-orders) given entries according to the given rules.
   *
   * @param entries            entries to arrange
   * @param sectionRules       rules to use for arrangement
   * @param rulesByPriority    rules sorted by priority ('public static' rule will have higher priority than 'public')
   * @param entryToSection     mapping from arrangement entry to the parent section
   * @return                   arranged list of the given rules
   */
@SuppressWarnings("AssignmentToForLoopParameter")
@NotNull
public static <E extends ArrangementEntry> List<E> arrange(@NotNull Collection<E> entries, @NotNull List<ArrangementSectionRule> sectionRules, @NotNull List<? extends ArrangementMatchRule> rulesByPriority, @Nullable Map<E, ArrangementSectionRule> entryToSection) {
    List<E> arranged = ContainerUtilRt.newArrayList();
    Set<E> unprocessed = ContainerUtilRt.newLinkedHashSet();
    List<Pair<Set<ArrangementEntry>, E>> dependent = ContainerUtilRt.newArrayList();
    for (E entry : entries) {
        List<? extends ArrangementEntry> dependencies = entry.getDependencies();
        if (dependencies == null) {
            unprocessed.add(entry);
        } else {
            if (dependencies.size() == 1 && dependencies.get(0) == entry.getParent()) {
                // Handle a situation when the entry is configured to be at the first parent's children.
                arranged.add(entry);
            } else {
                Set<ArrangementEntry> first = new HashSet<>(dependencies);
                dependent.add(Pair.create(first, entry));
            }
        }
    }
    Set<E> matched = new HashSet<>();
    MultiMap<ArrangementMatchRule, E> elementsByRule = new MultiMap<>();
    for (ArrangementMatchRule rule : rulesByPriority) {
        matched.clear();
        for (E entry : unprocessed) {
            if (entry.canBeMatched() && rule.getMatcher().isMatched(entry)) {
                elementsByRule.putValue(rule, entry);
                matched.add(entry);
            }
        }
        unprocessed.removeAll(matched);
    }
    for (ArrangementSectionRule sectionRule : sectionRules) {
        for (ArrangementMatchRule rule : sectionRule.getMatchRules()) {
            final Collection<E> arrangedEntries = arrangeByRule(arranged, elementsByRule, rule);
            if (entryToSection != null && arrangedEntries != null) {
                for (E entry : arrangedEntries) {
                    entryToSection.put(entry, sectionRule);
                }
            }
        }
    }
    arranged.addAll(unprocessed);
    for (int i = 0; i < arranged.size() && !dependent.isEmpty(); i++) {
        E e = arranged.get(i);
        List<E> shouldBeAddedAfterCurrentElement = ContainerUtil.newArrayList();
        for (Iterator<Pair<Set<ArrangementEntry>, E>> iterator = dependent.iterator(); iterator.hasNext(); ) {
            Pair<Set<ArrangementEntry>, E> pair = iterator.next();
            pair.first.remove(e);
            if (pair.first.isEmpty()) {
                iterator.remove();
                shouldBeAddedAfterCurrentElement.add(pair.second);
            }
        }
        // add dependent entries to the same section as main entry
        if (entryToSection != null && entryToSection.containsKey(e)) {
            final ArrangementSectionRule rule = entryToSection.get(e);
            for (E e1 : shouldBeAddedAfterCurrentElement) {
                entryToSection.put(e1, rule);
            }
        }
        arranged.addAll(i + 1, shouldBeAddedAfterCurrentElement);
    }
    return arranged;
}
Also used : ArrangementMatchRule(com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule) HashSet(com.intellij.util.containers.HashSet) ArrangementSectionRule(com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule) Pair(com.intellij.openapi.util.Pair) HashSet(com.intellij.util.containers.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ArrangementSectionRule (com.intellij.psi.codeStyle.arrangement.match.ArrangementSectionRule)13 ArrangementGroupingRule (com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule)6 Test (org.junit.Test)6 StdArrangementExtendableSettings (com.intellij.psi.codeStyle.arrangement.std.StdArrangementExtendableSettings)5 StdArrangementRuleAliasToken (com.intellij.psi.codeStyle.arrangement.std.StdArrangementRuleAliasToken)5 Element (org.jdom.Element)5 StdArrangementMatchRule (com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule)3 TextRange (com.intellij.openapi.util.TextRange)2 HashSet (com.intellij.util.containers.HashSet)2 NotNull (org.jetbrains.annotations.NotNull)2 ArrangementSectionRuleData (com.intellij.application.options.codeStyle.arrangement.match.ArrangementSectionRuleManager.ArrangementSectionRuleData)1 ArrangementRuleAliasDialog (com.intellij.application.options.codeStyle.arrangement.match.tokens.ArrangementRuleAliasDialog)1 Language (com.intellij.lang.Language)1 FoldRegion (com.intellij.openapi.editor.FoldRegion)1 FoldingModel (com.intellij.openapi.editor.FoldingModel)1 Pair (com.intellij.openapi.util.Pair)1 PsiElement (com.intellij.psi.PsiElement)1 CommonCodeStyleSettings (com.intellij.psi.codeStyle.CommonCodeStyleSettings)1 ArrangementEngine (com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine)1 ArrangementMatchRule (com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule)1