@Nullable
 @Override
 protected RefactoringEventData getAfterData(UsageInfo[] usages) {
   RefactoringEventData data = new RefactoringEventData();
   List<PsiElement> elements = new ArrayList<PsiElement>();
   if (myNameToGetter != null) {
     elements.addAll(myNameToGetter.values());
   }
   if (myNameToSetter != null) {
     elements.addAll(myNameToSetter.values());
   }
   data.addElements(elements);
   return data;
 }
  @Nullable
  private PsiMethod collectExceptions(List<PsiClassType> unhandled) {
    PsiElement targetElement = null;
    PsiMethod targetMethod = null;

    final PsiElement psiElement =
        myWrongElement instanceof PsiMethodReferenceExpression
            ? myWrongElement
            : PsiTreeUtil.getParentOfType(
                myWrongElement, PsiFunctionalExpression.class, PsiMethod.class);
    if (psiElement instanceof PsiFunctionalExpression) {
      targetMethod = LambdaUtil.getFunctionalInterfaceMethod(psiElement);
      targetElement =
          psiElement instanceof PsiLambdaExpression
              ? ((PsiLambdaExpression) psiElement).getBody()
              : psiElement;
    } else if (psiElement instanceof PsiMethod) {
      targetMethod = (PsiMethod) psiElement;
      targetElement = psiElement;
    }

    if (targetElement == null || targetMethod == null || !targetMethod.getThrowsList().isPhysical())
      return null;
    List<PsiClassType> exceptions =
        getUnhandledExceptions(myWrongElement, targetElement, targetMethod);
    if (exceptions == null || exceptions.isEmpty()) return null;
    unhandled.addAll(exceptions);
    return targetMethod;
  }
  private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() {
    ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors;
    if (cached != null) {
      return cached;
    }

    Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap();

    List<MultiHostInjector> allInjectors = ContainerUtil.newArrayList();
    allInjectors.addAll(myManualInjectors);
    Collections.addAll(
        allInjectors, MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getExtensions(myProject));
    if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) {
      allInjectors.add(PsiManagerRegisteredInjectorsAdapter.INSTANCE);
    }

    for (MultiHostInjector injector : allInjectors) {
      for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) {
        LOG.assertTrue(place != null, injector);
        MultiHostInjector[] existing = injectors.get(place);
        injectors.put(
            place,
            existing == null
                ? new MultiHostInjector[] {injector}
                : ArrayUtil.append(existing, injector));
      }
    }

    ClassMapCachingNulls<MultiHostInjector> result =
        new ClassMapCachingNulls<>(injectors, new MultiHostInjector[0], allInjectors);
    cachedInjectors = result;
    return result;
  }
  private static void getImplementListsInner(
      GrTypeDefinition grType, List<PsiClassType> result, Set<PsiClass> visited) {
    if (!visited.add(grType)) return;

    final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause());
    List<PsiClassType> fromDelegates = getImplementsFromDelegate(grType, visited);
    if (fromDelegates != null) {
      result.addAll(fromDelegates);
    }
    result.addAll(Arrays.asList(implementsTypes));

    if (!grType.isInterface()
        && !ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT)
        && !ContainerUtil.or(getReferenceListTypes(grType.getExtendsClause()), IS_GROOVY_OBJECT)) {
      result.add(getGroovyObjectType(grType));
    }
  }
 public static void addExpandingReflectedMethods(List<PsiMethod> result, PsiMethod method) {
   if (method instanceof GrMethod) {
     final GrReflectedMethod[] reflectedMethods = ((GrMethod) method).getReflectedMethods();
     if (reflectedMethods.length > 0) {
       result.addAll(Arrays.asList(reflectedMethods));
       return;
     }
   }
   result.add(method);
 }
 public ExtractClassProcessor(
     PsiClass sourceClass,
     List<PsiField> fields,
     List<PsiMethod> methods,
     List<PsiClass> classes,
     String packageName,
     MoveDestination moveDestination,
     String newClassName,
     String newVisibility,
     boolean generateAccessors,
     List<MemberInfo> enumConstants) {
   super(sourceClass.getProject());
   this.sourceClass = sourceClass;
   this.newPackageName = packageName;
   myMoveDestination = moveDestination;
   myNewVisibility = newVisibility;
   myGenerateAccessors = generateAccessors;
   this.enumConstants = new ArrayList<PsiField>();
   for (MemberInfo constant : enumConstants) {
     if (constant.isChecked()) {
       this.enumConstants.add((PsiField) constant.getMember());
     }
   }
   this.fields = new ArrayList<PsiField>(fields);
   this.methods = new ArrayList<PsiMethod>(methods);
   this.innerClasses = new ArrayList<PsiClass>(classes);
   this.newClassName = newClassName;
   delegateFieldName = calculateDelegateFieldName();
   requiresBackpointer =
       new BackpointerUsageVisitor(fields, innerClasses, methods, sourceClass)
           .backpointerRequired();
   if (requiresBackpointer) {
     ContainerUtil.addAll(typeParams, sourceClass.getTypeParameters());
   } else {
     final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>();
     final TypeParametersVisitor visitor = new TypeParametersVisitor(typeParamSet);
     for (PsiField field : fields) {
       field.accept(visitor);
     }
     for (PsiMethod method : methods) {
       method.accept(visitor);
       // do not include method's type parameters in class signature
       typeParamSet.removeAll(Arrays.asList(method.getTypeParameters()));
     }
     typeParams.addAll(typeParamSet);
   }
   myClass =
       new WriteCommandAction<PsiClass>(myProject, getCommandName()) {
         @Override
         protected void run(@NotNull Result<PsiClass> result) throws Throwable {
           result.setResult(buildClass());
         }
       }.execute().getResultObject();
   myExtractEnumProcessor = new ExtractEnumProcessor(myProject, this.enumConstants, myClass);
 }
  @Override
  public List<RefEntity> getChildren() {
    List<RefEntity> superChildren = super.getChildren();
    if (myParameters == null) return superChildren;
    if (superChildren == null || superChildren.isEmpty())
      return Arrays.<RefEntity>asList(myParameters);

    List<RefEntity> allChildren =
        new ArrayList<RefEntity>(superChildren.size() + myParameters.length);
    allChildren.addAll(superChildren);
    Collections.addAll(allChildren, myParameters);
    return allChildren;
  }
  /**
   * The key method of contributor. It collects all delegating methods of clazz
   *
   * @param clazz class to process
   * @param processedWithoutDeprecated already visited classes which deprecated methods were not
   *     processsed
   * @param processedAll already visited classes which all methods were processed
   * @param collector result collection
   */
  private static void process(
      PsiClass clazz,
      PsiSubstitutor superClassSubstitutor,
      boolean shouldProcessDeprecated,
      Set<PsiClass> processedWithoutDeprecated,
      Set<PsiClass> processedAll,
      List<PsiMethod> collector,
      GrTypeDefinition classToDelegateTo,
      boolean keepParameterAnnotations) {
    final List<PsiMethod> result = new ArrayList<PsiMethod>();

    // process super methods before delegated methods
    for (PsiClassType superType : getSuperTypes(clazz)) {
      processClassInner(
          superType,
          superClassSubstitutor,
          shouldProcessDeprecated,
          result,
          classToDelegateTo,
          processedWithoutDeprecated,
          processedAll,
          keepParameterAnnotations);
    }

    if (clazz instanceof GrTypeDefinition) {
      // search for @Delegate fields and collect methods from them
      for (GrField field : ((GrTypeDefinition) clazz).getFields()) {
        final PsiAnnotation delegate =
            PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE);
        if (delegate == null) continue;

        final PsiType type = field.getDeclaredType();
        if (!(type instanceof PsiClassType)) continue;

        processClassInner(
            (PsiClassType) type,
            superClassSubstitutor,
            shouldDelegateDeprecated(delegate),
            result,
            classToDelegateTo,
            processedWithoutDeprecated,
            processedAll,
            shouldKeepParameterAnnotations(delegate));
      }
    }

    collector.addAll(result);
  }
  @NotNull
  @Override
  public RefElement[] getEntryPoints() {
    validateEntryPoints();
    List<RefElement> entries = new ArrayList<RefElement>();
    Collection<SmartRefElementPointer> collection = myPersistentEntryPoints.values();
    for (SmartRefElementPointer refElementPointer : collection) {
      final RefEntity elt = refElementPointer.getRefElement();
      if (elt instanceof RefElement) {
        entries.add((RefElement) elt);
      }
    }
    entries.addAll(myTemporaryEntryPoints);

    return entries.toArray(new RefElement[entries.size()]);
  }
 public void findUsages(@NotNull List<FixableUsageInfo> usages) {
   for (PsiField field : fields) {
     findUsagesForField(field, usages);
     usages.add(new RemoveField(field));
   }
   usages.addAll(
       myExtractEnumProcessor.findEnumConstantUsages(new ArrayList<FixableUsageInfo>(usages)));
   for (PsiClass innerClass : innerClasses) {
     findUsagesForInnerClass(innerClass, usages);
     usages.add(new RemoveInnerClass(innerClass));
   }
   for (PsiMethod method : methods) {
     if (method.hasModifierProperty(PsiModifier.STATIC)) {
       findUsagesForStaticMethod(method, usages);
     } else {
       findUsagesForMethod(method, usages);
     }
   }
 }
  @Override
  protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
    if (!Registry.is("editor.injected.highlighting.enabled")) return;

    final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);

    final List<PsiElement> inside = new ArrayList<PsiElement>();
    final List<PsiElement> outside = new ArrayList<PsiElement>();
    List<ProperTextRange> insideRanges = new ArrayList<ProperTextRange>();
    List<ProperTextRange> outsideRanges = new ArrayList<ProperTextRange>();
    // TODO: this thing is just called TWICE with same arguments eating CPU on huge files :(
    Divider.divideInsideAndOutside(
        myFile,
        myRestrictRange.getStartOffset(),
        myRestrictRange.getEndOffset(),
        myPriorityRange,
        inside,
        insideRanges,
        outside,
        outsideRanges,
        false,
        SHOULD_HIGHIGHT_FILTER);

    // all infos for the "injected fragment for the host which is inside" are indeed inside
    // but some of the infos for the "injected fragment for the host which is outside" can be still
    // inside
    Set<HighlightInfo> injectedResult = new THashSet<HighlightInfo>();
    Set<PsiFile> injected = getInjectedPsiFiles(inside, outside, progress);
    setProgressLimit(injected.size());

    if (!addInjectedPsiHighlights(
        injected, progress, Collections.synchronizedSet(injectedResult))) {
      throw new ProcessCanceledException();
    }
    final List<HighlightInfo> injectionsOutside =
        new ArrayList<HighlightInfo>(gotHighlights.size());

    Set<HighlightInfo> result;
    synchronized (injectedResult) {
      // sync here because all writes happened in another thread
      result = injectedResult;
    }
    for (HighlightInfo info : result) {
      if (myRestrictRange.contains(info)) {
        gotHighlights.add(info);
      } else {
        // nonconditionally apply injected results regardless whether they are in
        // myStartOffset,myEndOffset
        injectionsOutside.add(info);
      }
    }

    if (!injectionsOutside.isEmpty()) {
      final ProperTextRange priorityIntersection = myPriorityRange.intersection(myRestrictRange);
      if ((!inside.isEmpty() || !gotHighlights.isEmpty())
          && priorityIntersection
              != null) { // do not apply when there were no elements to highlight
        // clear infos found in visible area to avoid applying them twice
        final List<HighlightInfo> toApplyInside = new ArrayList<HighlightInfo>(gotHighlights);
        myHighlights.addAll(toApplyInside);
        gotHighlights.clear();

        myHighlightInfoProcessor.highlightsInsideVisiblePartAreProduced(
            myHighlightingSession, toApplyInside, myPriorityRange, myRestrictRange, getId());
      }

      List<HighlightInfo> toApply = new ArrayList<HighlightInfo>();
      for (HighlightInfo info : gotHighlights) {
        if (!myRestrictRange.containsRange(info.getStartOffset(), info.getEndOffset())) continue;
        if (!myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
          toApply.add(info);
        }
      }
      toApply.addAll(injectionsOutside);

      myHighlightInfoProcessor.highlightsOutsideVisiblePartAreProduced(
          myHighlightingSession,
          toApply,
          myRestrictRange,
          new ProperTextRange(0, myDocument.getTextLength()),
          getId());
    } else {
      // else apply only result (by default apply command) and only within inside
      myHighlights.addAll(gotHighlights);
      myHighlightInfoProcessor.highlightsInsideVisiblePartAreProduced(
          myHighlightingSession, myHighlights, myRestrictRange, myRestrictRange, getId());
    }
  }
  public boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) {
    UsageInfo[] usagesIn = refUsages.get();
    MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    RenameUtil.addConflictDescriptions(usagesIn, conflicts);
    RenamePsiElementProcessor.forElement(myPrimaryElement)
        .findExistingNameConflicts(myPrimaryElement, myNewName, conflicts);
    if (!conflicts.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        throw new ConflictsInTestsException(conflicts.values());
      }
      ConflictsDialog conflictsDialog = prepareConflictsDialog(conflicts, refUsages.get());
      conflictsDialog.show();
      if (!conflictsDialog.isOK()) {
        if (conflictsDialog.isShowConflicts()) prepareSuccessful();
        return false;
      }
    }

    final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>();
    if (!myRenamers.isEmpty()) {
      if (!findRenamedVariables(variableUsages)) return false;
      final LinkedHashMap<PsiElement, String> renames = new LinkedHashMap<PsiElement, String>();
      for (final AutomaticRenamer renamer : myRenamers) {
        final List<? extends PsiNamedElement> variables = renamer.getElements();
        for (final PsiNamedElement variable : variables) {
          final String newName = renamer.getNewName(variable);
          if (newName != null) {
            addElement(variable, newName);
            prepareRenaming(variable, newName, renames);
          }
        }
      }
      if (!renames.isEmpty()) {
        myAllRenames.putAll(renames);
        final Runnable runnable =
            new Runnable() {
              public void run() {
                for (Map.Entry<PsiElement, String> entry : renames.entrySet()) {
                  final UsageInfo[] usages =
                      RenameUtil.findUsages(
                          entry.getKey(),
                          entry.getValue(),
                          mySearchInComments,
                          mySearchTextOccurrences,
                          myAllRenames);
                  Collections.addAll(variableUsages, usages);
                }
              }
            };
        if (!ProgressManager.getInstance()
            .runProcessWithProgressSynchronously(
                runnable, RefactoringBundle.message("searching.for.variables"), true, myProject)) {
          return false;
        }
      }
    }

    final Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn));
    usagesSet.addAll(variableUsages);
    final List<UnresolvableCollisionUsageInfo> conflictUsages =
        RenameUtil.removeConflictUsages(usagesSet);
    if (conflictUsages != null) {
      mySkippedUsages.addAll(conflictUsages);
    }
    refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()]));

    prepareSuccessful();
    return true;
  }
 /**
  * If setting indicates, move all overloaded methods (of the same name) adjacent with the first
  * encountered. Sort in the configured order (original order, or by number of parameters).
  */
 public static void handleOverloadedMethods(
     List<ClassContentsEntry> contents, RearrangerSettings settings) {
   if (!settings.isKeepOverloadedMethodsTogether()) return;
   /**
    * first, detect overloaded methods and move them to the first method's list of overloaded
    * methods. Make two passes, first for extracted methods, then for non-extracted methods. This
    * will organize any overloaded methods for extracted methods with them (as opposed to whichever
    * was seen first.)
    */
   cullOverloadedMethods(contents, true);
   LOG.debug("entered handleOverloadedMethods(): move overloaded methods together");
   cullOverloadedMethods(contents, false);
   List<ClassContentsEntry> copy = new ArrayList<ClassContentsEntry>(contents);
   for (ClassContentsEntry rangeEntry : copy) {
     if (rangeEntry instanceof RelatableEntry) {
       MethodEntry current = (MethodEntry) rangeEntry;
       if (current.myOverloadedMethods.size() > 0) {
         List<MethodEntry> newList =
             new ArrayList<MethodEntry>(current.myOverloadedMethods.size() + 1);
         newList.add(current);
         /**
          * we are looking at the head of a list of overloaded methods. We need to sort the list if
          * necessary and, if the head of the list has changed, replace it in the contents array.
          */
         switch (settings.getOverloadedOrder()) {
           case RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL:
             // list is already in original order, except perhaps that the top-most extracted
             // method
             // comes first (if there is one).
             newList.addAll(current.myOverloadedMethods);
             break;
           case RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS:
           case RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS:
             for (MethodEntry entry : current.myOverloadedMethods) {
               boolean inserted = false;
               for (int index = 0; index < newList.size(); index++) {
                 MethodEntry me = newList.get(index);
                 if (settings.getOverloadedOrder()
                         == RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS
                     ? me.getnParameters() > entry.getnParameters()
                     : me.getnParameters() < entry.getnParameters()) {
                   newList.add(index, entry);
                   inserted = true;
                   break;
                 }
               }
               if (!inserted) {
                 newList.add(entry);
               }
             }
             break;
         }
         current.myOverloadedMethods.clear();
         /**
          * if the head of the arraylist is not the same as "current", then the sort operation
          * moved another method to the head of the list. Replace that in the contents array. Then
          * assign a new ordered list.
          */
         int index = contents.indexOf(current);
         if (newList.get(0) != current) {
           contents.set(index, ((MethodEntry) newList.get(0)));
         }
         /** insert the remaining overloaded methods after the current entry. */
         newList.remove(0);
         for (int j = 0; j < newList.size(); j++) {
           contents.add(index + j + 1, ((MethodEntry) newList.get(j)));
         }
       }
     }
   }
 }
 public void addAllPersistentEntries(EntryPointsManagerBase manager) {
   myPersistentEntryPoints.putAll(manager.myPersistentEntryPoints);
   myPatterns.addAll(manager.getPatterns());
 }
Beispiel #15
0
  @NotNull
  public Class classToClass(@NotNull PsiClass psiClass) {
    Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList());
    List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass);
    List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters());
    List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes());
    List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes());
    IdentifierImpl name = new IdentifierImpl(psiClass.getName());
    List<Expression> baseClassParams = new LinkedList<Expression>();

    List<Member> members = getMembers(psiClass);

    // we try to find super() call and generate class declaration like that: class A(name: String, i
    // : Int) : Base(name)
    SuperVisitor visitor = new SuperVisitor();
    psiClass.accept(visitor);
    Collection<PsiExpressionList> resolvedSuperCallParameters =
        visitor.getResolvedSuperCallParameters();
    if (resolvedSuperCallParameters.size() == 1) {
      baseClassParams.addAll(
          expressionsToExpressionList(
              resolvedSuperCallParameters.toArray(new PsiExpressionList[1])[0].getExpressions()));
    }

    // we create primary constructor from all non final fields and fields without initializers
    if (!psiClass.isEnum()
        && !psiClass.isInterface()
        && psiClass.getConstructors().length > 1
        && getPrimaryConstructorForThisCase(psiClass) == null) {
      List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields);
      Map<String, String> initializers = new HashMap<String, String>();

      for (Member m : members) {
        // and modify secondaries
        if (m.getKind() == INode.Kind.CONSTRUCTOR) {
          Function f = (Function) m;
          if (!((Constructor) f).isPrimary()) {
            for (Field fo : finalOrWithEmptyInitializer) {
              String init = getDefaultInitializer(fo);
              initializers.put(fo.getIdentifier().toKotlin(), init);
            }

            List<Statement> newStatements = new LinkedList<Statement>();

            for (Statement s : f.getBlock().getStatements()) {
              boolean isRemoved = false;

              if (s.getKind() == INode.Kind.ASSIGNMENT_EXPRESSION) {
                AssignmentExpression assignmentExpression = (AssignmentExpression) s;
                if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) {
                  for (Field fo : finalOrWithEmptyInitializer) {
                    String id = fo.getIdentifier().toKotlin();
                    if (((CallChainExpression) assignmentExpression.getLeft())
                        .getIdentifier()
                        .toKotlin()
                        .endsWith("." + id)) {
                      initializers.put(id, assignmentExpression.getRight().toKotlin());
                      isRemoved = true;
                    }
                  }
                }
              }
              if (!isRemoved) {
                newStatements.add(s);
              }
            }

            newStatements.add(
                0,
                new DummyStringExpression(
                    "val __ = "
                        + createPrimaryConstructorInvocation(
                            name.toKotlin(), finalOrWithEmptyInitializer, initializers)));

            f.setBlock(new Block(newStatements));
          }
        }
      }

      members.add(
          new Constructor(
              Identifier.EMPTY_IDENTIFIER,
              Collections.<String>emptySet(),
              new ClassType(name),
              Collections.<Element>emptyList(),
              new ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
              new Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
              true));
    }

    if (psiClass.isInterface()) {
      return new Trait(
          this,
          name,
          modifiers,
          typeParameters,
          extendsTypes,
          Collections.<Expression>emptyList(),
          implementsTypes,
          members);
    }
    if (psiClass.isEnum()) {
      return new Enum(
          this,
          name,
          modifiers,
          typeParameters,
          Collections.<Type>emptyList(),
          Collections.<Expression>emptyList(),
          implementsTypes,
          members);
    }
    return new Class(
        this,
        name,
        modifiers,
        typeParameters,
        extendsTypes,
        baseClassParams,
        implementsTypes,
        members);
  }