@SuppressWarnings("unchecked") private static <E extends ArrangementEntry> void doArrange( @NotNull List<ArrangementEntryWrapper<E>> wrappers, @NotNull Context<E> context) { if (wrappers.isEmpty()) { return; } Map<E, ArrangementEntryWrapper<E>> map = ContainerUtilRt.newHashMap(); List<E> arranged = ContainerUtilRt.newArrayList(); List<E> toArrange = ContainerUtilRt.newArrayList(); for (ArrangementEntryWrapper<E> wrapper : wrappers) { E entry = wrapper.getEntry(); map.put(wrapper.getEntry(), wrapper); if (!entry.canBeMatched()) { // Split entries to arrange by 'can not be matched' rules. // See IDEA-104046 for a problem use-case example. if (toArrange.isEmpty()) { arranged.addAll(arrange(toArrange, context.rules, context.rulesByPriority)); } arranged.add(entry); toArrange.clear(); } else { toArrange.add(entry); } } if (!toArrange.isEmpty()) { arranged.addAll(arrange(toArrange, context.rules, context.rulesByPriority)); } context.changer.prepare(wrappers, context); // We apply changes from the last position to the first position in order not to bother with // offsets shifts. for (int i = arranged.size() - 1; i >= 0; i--) { ArrangementEntryWrapper<E> arrangedWrapper = map.get(arranged.get(i)); ArrangementEntryWrapper<E> initialWrapper = wrappers.get(i); context.changer.replace( arrangedWrapper, initialWrapper, i > 0 ? map.get(arranged.get(i - 1)) : null, context); } }
public static void change(UsageInfo[] usages, TypeMigrationLabeler labeler, Project project) { final List<SmartPsiElementPointer<PsiNewExpression>> newExpressionsToCheckDiamonds = new SmartList<>(); final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages); final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); List<UsageInfo> nonCodeUsages = new ArrayList<>(); for (UsageInfo usage : usages) { if (((TypeMigrationUsageInfo) usage).isExcluded()) continue; final PsiElement element = usage.getElement(); if (element instanceof PsiVariable || element instanceof PsiMember || element instanceof PsiExpression || element instanceof PsiReferenceParameterList) { producer.change( (TypeMigrationUsageInfo) usage, expression -> newExpressionsToCheckDiamonds.add( smartPointerManager.createSmartPsiElementPointer(expression))); } else { nonCodeUsages.add(usage); } } for (SmartPsiElementPointer<PsiNewExpression> newExpressionPointer : newExpressionsToCheckDiamonds) { final PsiNewExpression newExpression = newExpressionPointer.getElement(); if (newExpression != null) { labeler.postProcessNewExpression(newExpression); } } for (UsageInfo usageInfo : nonCodeUsages) { final PsiElement element = usageInfo.getElement(); if (element != null) { final PsiReference reference = element.getReference(); if (reference != null) { final Object target = producer.getConversion(usageInfo); if (target instanceof PsiMember) { try { reference.bindToElement((PsiElement) target); } catch (IncorrectOperationException ignored) { } } } } } producer.flush(); }
public void addMoveInfo(int oldStart, int oldEnd, int newStart) { moveInfos.add(new ArrangementMoveInfo(oldStart, oldEnd, newStart)); }
/** * Arranges (re-orders) given entries according to the given rules. * * @param entries entries to arrange * @param rules rules to use for arrangement * @param rulesByPriority rules sorted by priority ('public static' rule will have higher priority * than 'public') * @param <E> arrangement entry type * @return arranged list of the given rules */ @SuppressWarnings("AssignmentToForLoopParameter") @NotNull public static <E extends ArrangementEntry> List<E> arrange( @NotNull Collection<E> entries, @NotNull List<? extends ArrangementMatchRule> rules, @NotNull List<? extends ArrangementMatchRule> rulesByPriority) { 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<ArrangementEntry>(dependencies); dependent.add(Pair.create(first, entry)); } } } Set<E> matched = new HashSet<E>(); MultiMap<ArrangementMatchRule, E> elementsByRule = new MultiMap<ArrangementMatchRule, E>(); 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 (ArrangementMatchRule rule : rules) { if (elementsByRule.containsKey(rule)) { final Collection<E> arrangedEntries = elementsByRule.get(rule); // Sort by name if necessary. if (StdArrangementTokens.Order.BY_NAME.equals(rule.getOrderType())) { sortByName((List<E>) arrangedEntries); } arranged.addAll(arrangedEntries); } } arranged.addAll(unprocessed); for (int i = 0; i < arranged.size() && !dependent.isEmpty(); i++) { E e = arranged.get(i); 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(); arranged.add(i + 1, pair.second); } } } return arranged; }