Esempio n. 1
0
  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();
  }
 private static <E extends ArrangementEntry> void sortByName(@NotNull List<E> entries) {
   if (entries.size() < 2) {
     return;
   }
   final TObjectIntHashMap<E> weights = new TObjectIntHashMap<E>();
   int i = 0;
   for (E e : entries) {
     weights.put(e, ++i);
   }
   ContainerUtil.sort(
       entries,
       new Comparator<E>() {
         @Override
         public int compare(E e1, E e2) {
           String name1 =
               e1 instanceof NameAwareArrangementEntry
                   ? ((NameAwareArrangementEntry) e1).getName()
                   : null;
           String name2 =
               e2 instanceof NameAwareArrangementEntry
                   ? ((NameAwareArrangementEntry) e2).getName()
                   : null;
           if (name1 != null && name2 != null) {
             return name1.compareTo(name2);
           } else if (name1 == null && name2 == null) {
             return weights.get(e1) - weights.get(e2);
           } else if (name2 == null) {
             return -1;
           } else {
             return 1;
           }
         }
       });
 }
  @NotNull
  private List<AnnotationData> collectExternalAnnotations(@NotNull PsiModifierListOwner listOwner) {
    if (!hasAnyAnnotationsRoots()) return Collections.emptyList();

    List<AnnotationData> cached;
    while (true) {
      cached = (List<AnnotationData>) cache.get(listOwner);
      if (cached == NO_DATA || !cached.isEmpty()) return cached;
      List<AnnotationData> computed = doCollect(listOwner, false);
      if (cache.replace(listOwner, cached, computed)) {
        cached = computed;
        break;
      }
    }
    return cached;
  }
 @Override
 @Nullable
 public PsiAnnotation[] findExternalAnnotations(@NotNull final PsiModifierListOwner listOwner) {
   final List<AnnotationData> result = collectExternalAnnotations(listOwner);
   return result.isEmpty()
       ? null
       : ContainerUtil.map2Array(
           result,
           PsiAnnotation.EMPTY_ARRAY,
           new Function<AnnotationData, PsiAnnotation>() {
             @Override
             public PsiAnnotation fun(AnnotationData data) {
               return data.getAnnotation(BaseExternalAnnotationsManager.this);
             }
           });
 }
 public void addMoveInfo(int oldStart, int oldEnd, int newStart) {
   moveInfos.add(new ArrangementMoveInfo(oldStart, oldEnd, newStart));
 }
  @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);
    }
  }
  /**
   * 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;
  }