private static List<FunctionDescriptor> getSuperFunctionsForMethod(
      @NotNull PsiMethodWrapper method,
      @NotNull BindingTrace trace,
      @NotNull ClassDescriptor containingClass) {
    List<FunctionDescriptor> superFunctions = Lists.newArrayList();

    Map<ClassDescriptor, JetType> superclassToSupertype =
        getSuperclassToSupertypeMap(containingClass);

    Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> superclassToFunctions =
        getSuperclassToFunctionsMultimap(method, trace.getBindingContext(), containingClass);

    for (HierarchicalMethodSignature superSignature :
        method.getPsiMethod().getHierarchicalMethodSignature().getSuperSignatures()) {
      PsiMethod superMethod = superSignature.getMethod();

      PsiClass psiClass = superMethod.getContainingClass();
      assert psiClass != null;
      String classFqNameString = psiClass.getQualifiedName();
      assert classFqNameString != null;
      FqName classFqName = new FqName(classFqNameString);

      if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(classFqName).isEmpty()) {
        for (FunctionDescriptor superFun :
            JavaToKotlinMethodMap.INSTANCE.getFunctions(superMethod, containingClass)) {
          superFunctions.add(substituteSuperFunction(superclassToSupertype, superFun));
        }
        continue;
      }

      DeclarationDescriptor superFun =
          superMethod instanceof JetClsMethod
              ? trace.get(
                  BindingContext.DECLARATION_TO_DESCRIPTOR,
                  ((JetClsMethod) superMethod).getOrigin())
              : findSuperFunction(superclassToFunctions.get(classFqName), superMethod);
      if (superFun == null) {
        reportCantFindSuperFunction(method);
        continue;
      }

      assert superFun instanceof FunctionDescriptor : superFun.getClass().getName();

      superFunctions.add(
          substituteSuperFunction(superclassToSupertype, (FunctionDescriptor) superFun));
    }

    // sorting for diagnostic stability
    Collections.sort(
        superFunctions,
        new Comparator<FunctionDescriptor>() {
          @Override
          public int compare(FunctionDescriptor fun1, FunctionDescriptor fun2) {
            FqNameUnsafe fqName1 = getFQName(fun1.getContainingDeclaration());
            FqNameUnsafe fqName2 = getFQName(fun2.getContainingDeclaration());
            return fqName1.getFqName().compareTo(fqName2.getFqName());
          }
        });
    return superFunctions;
  }
  private Collection<AbstractTreeNode> createGeneralList() {
    ArrayList<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>();

    PsiFile psiFile = getValue();
    final TodoItem[] items =
        findAllTodos(psiFile, myBuilder.getTodoTreeStructure().getSearchHelper());
    final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);

    if (document != null) {
      for (final TodoItem todoItem : items) {
        if (todoItem.getTextRange().getEndOffset() < document.getTextLength() + 1) {
          final SmartTodoItemPointer pointer = new SmartTodoItemPointer(todoItem, document);
          TodoFilter todoFilter = getToDoFilter();
          if (todoFilter != null) {
            if (todoFilter.contains(todoItem.getPattern())) {
              children.add(new TodoItemNode(getProject(), pointer, myBuilder));
            }
          } else {
            children.add(new TodoItemNode(getProject(), pointer, myBuilder));
          }
        }
      }
    }
    Collections.sort(children, SmartTodoItemPointerComparator.ourInstance);
    return children;
  }
  private static void logStats(Collection<PsiFile> otherFiles, long start) {
    long time = System.currentTimeMillis() - start;

    final Multiset<String> stats = HashMultiset.create();
    for (PsiFile file : otherFiles) {
      stats.add(
          StringUtil.notNullize(file.getViewProvider().getVirtualFile().getExtension())
              .toLowerCase());
    }

    List<String> extensions = ContainerUtil.newArrayList(stats.elementSet());
    Collections.sort(
        extensions,
        new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            return stats.count(o2) - stats.count(o1);
          }
        });

    String message =
        "Search in "
            + otherFiles.size()
            + " files with unknown types took "
            + time
            + "ms.\n"
            + "Mapping their extensions to an existing file type (e.g. Plain Text) might speed up the search.\n"
            + "Most frequent non-indexed file extensions: ";
    for (int i = 0; i < Math.min(10, extensions.size()); i++) {
      String extension = extensions.get(i);
      message += extension + "(" + stats.count(extension) + ") ";
    }
    LOG.info(message);
  }
 private List<DeclarationDescriptor> sortDeclarations(Collection<DeclarationDescriptor> input) {
   ArrayList<DeclarationDescriptor> r = new ArrayList<DeclarationDescriptor>(input);
   Collections.sort(
       r,
       new Comparator<DeclarationDescriptor>() {
         @Override
         public int compare(DeclarationDescriptor o1, DeclarationDescriptor o2) {
           return o1.getName().compareTo(o2.getName());
         }
       });
   return r;
 }
 public void applyFix(
     @NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
   final PsiElement element =
       PsiTreeUtil.getParentOfType(
           descriptor.getPsiElement(), PsiJavaCodeReferenceElement.class);
   if (element instanceof PsiJavaCodeReferenceElement) {
     final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) element;
     Collections.sort(
         myClassesToImport, new PsiProximityComparator(referenceElement.getElement()));
     final JList list =
         new JBList(myClassesToImport.toArray(new PsiClass[myClassesToImport.size()]));
     list.setCellRenderer(new FQNameCellRenderer());
     final Runnable runnable =
         new Runnable() {
           public void run() {
             if (!element.isValid()) return;
             final int index = list.getSelectedIndex();
             if (index < 0) return;
             new WriteCommandAction(project, element.getContainingFile()) {
               protected void run(final Result result) throws Throwable {
                 final PsiClass psiClass = myClassesToImport.get(index);
                 if (psiClass.isValid()) {
                   PsiDocumentManager.getInstance(project).commitAllDocuments();
                   referenceElement.bindToElement(psiClass);
                 }
               }
             }.execute();
           }
         };
     final AsyncResult<DataContext> asyncResult =
         DataManager.getInstance().getDataContextFromFocus();
     asyncResult.doWhenDone(
         new AsyncResult.Handler<DataContext>() {
           @Override
           public void run(DataContext dataContext) {
             final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
             assert editor != null; // available for on the fly mode only
             new PopupChooserBuilder(list)
                 .setTitle(QuickFixBundle.message("class.to.import.chooser.title"))
                 .setItemChoosenCallback(runnable)
                 .createPopup()
                 .showInBestPositionFor(editor);
           }
         });
   }
 }
 public void testLeafExpressionsMoreComplex() throws Exception {
   SliceTreeStructure treeStructure = configureTree("Duplicate");
   SliceNode root = (SliceNode) treeStructure.getRootElement();
   Collection<PsiElement> leaves =
       SliceLeafAnalyzer.calcLeafExpressions(root, treeStructure, SliceLeafAnalyzer.createMap());
   assertNotNull(leaves);
   assertEquals(2, leaves.size());
   List<PsiElement> list = new ArrayList<PsiElement>(leaves);
   Collections.sort(
       list,
       new Comparator<PsiElement>() {
         @Override
         public int compare(PsiElement o1, PsiElement o2) {
           return o1.getText().compareTo(o2.getText());
         }
       });
   assertTrue(list.get(0) instanceof PsiLiteralExpression);
   assertEquals(false, ((PsiLiteral) list.get(0)).getValue());
   assertTrue(list.get(1) instanceof PsiLiteralExpression);
   assertEquals(true, ((PsiLiteral) list.get(1)).getValue());
 }
  private static void checkStructure(final SliceNode root, @NonNls String dataExpected) {
    List<SliceNode> actualNodes = new ArrayList<SliceNode>((Collection) root.getChildren());
    Collections.sort(actualNodes, SliceTreeBuilder.SLICE_NODE_COMPARATOR);

    Object[] actualStrings =
        ContainerUtil.map2Array(
            actualNodes,
            new Function<SliceNode, Object>() {
              @Override
              public Object fun(SliceNode node) {
                return node.toString();
              }
            });

    String[] childrenExpected =
        dataExpected.length() == 0 ? ArrayUtil.EMPTY_STRING_ARRAY : dataExpected.split("\n");
    String curChildren = "";
    String curNode = null;
    int iactual = 0;
    for (int iexp = 0; iexp <= childrenExpected.length; iexp++) {
      String e = iexp == childrenExpected.length ? null : childrenExpected[iexp];
      boolean isTopLevel = e == null || e.charAt(0) != ' ';
      if (isTopLevel) {
        if (curNode != null) {
          assertTrue(iactual < actualStrings.length);
          Object actual = actualStrings[iactual];
          assertEquals(curNode, actual);
          checkStructure(actualNodes.get(iactual), curChildren);
          iactual++;
        }

        curNode = e;
        curChildren = "";
      } else {
        curChildren += StringUtil.trimStart(e, "  ") + "\n";
      }
    }
    assertEquals(actualNodes.size(), iactual);
  }
 public List<PsiVariable> getInputVariables(
     final PsiElement codeFragment, PsiElement[] elements, PsiVariable[] outputVariables) {
   final List<PsiVariable> inputVariables =
       ControlFlowUtil.getInputVariables(myControlFlow, myFlowStart, myFlowEnd);
   List<PsiVariable> myInputVariables;
   if (skipVariablesFromExitStatements(outputVariables)) {
     List<PsiVariable> inputVariableList = new ArrayList<>(inputVariables);
     removeParametersUsedInExitsOnly(codeFragment, inputVariableList);
     myInputVariables = inputVariableList;
   } else {
     List<PsiVariable> inputVariableList = new ArrayList<>(inputVariables);
     for (Iterator<PsiVariable> iterator = inputVariableList.iterator(); iterator.hasNext(); ) {
       PsiVariable variable = iterator.next();
       for (PsiElement element : elements) {
         if (PsiTreeUtil.isAncestor(element, variable, false)) {
           iterator.remove();
           break;
         }
       }
     }
     myInputVariables = inputVariableList;
   }
   // varargs variables go last, otherwise order is induced by original ordering
   Collections.sort(
       myInputVariables,
       (v1, v2) -> {
         if (v1.getType() instanceof PsiEllipsisType) {
           return 1;
         }
         if (v2.getType() instanceof PsiEllipsisType) {
           return -1;
         }
         return v1.getTextOffset() - v2.getTextOffset();
       });
   return myInputVariables;
 }
  private void tryToMoveInitializers(
      PsiMethod constructor,
      HashSet<PsiMethod> subConstructors,
      LinkedHashSet<PsiField> movedFields)
      throws IncorrectOperationException {
    final LinkedHashMap<PsiField, Initializer> fieldsToInitializers =
        new LinkedHashMap<PsiField, Initializer>();
    boolean anyFound = false;

    for (PsiField field : movedFields) {
      PsiStatement commonInitializer = null;
      final ArrayList<PsiElement> fieldInitializersToRemove = new ArrayList<PsiElement>();
      for (PsiMethod subConstructor : subConstructors) {
        commonInitializer =
            hasCommonInitializer(
                commonInitializer, subConstructor, field, fieldInitializersToRemove);
        if (commonInitializer == null) break;
      }
      if (commonInitializer != null) {
        final ParametersAndMovedFieldsUsedCollector visitor =
            new ParametersAndMovedFieldsUsedCollector(movedFields);
        commonInitializer.accept(visitor);
        fieldsToInitializers.put(
            field,
            new Initializer(
                commonInitializer,
                visitor.getUsedFields(),
                visitor.getUsedParameters(),
                fieldInitializersToRemove));
        anyFound = true;
      }
    }

    if (!anyFound) return;

    {
      final Set<PsiField> initializedFields = fieldsToInitializers.keySet();
      Set<PsiField> unmovable =
          RefactoringUtil.transitiveClosure(
              new RefactoringUtil.Graph<PsiField>() {
                public Set<PsiField> getVertices() {
                  return initializedFields;
                }

                public Set<PsiField> getTargets(PsiField source) {
                  return fieldsToInitializers.get(source).movedFieldsUsed;
                }
              },
              new Condition<PsiField>() {
                public boolean value(PsiField object) {
                  return !initializedFields.contains(object);
                }
              });

      for (PsiField psiField : unmovable) {
        fieldsToInitializers.remove(psiField);
      }
    }

    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myProject);

    if (constructor == null) {
      constructor = (PsiMethod) myTargetSuperClass.add(factory.createConstructor());
      final String visibilityModifier =
          VisibilityUtil.getVisibilityModifier(myTargetSuperClass.getModifierList());
      PsiUtil.setModifierProperty(constructor, visibilityModifier, true);
    }

    ArrayList<PsiField> initializedFields = new ArrayList<PsiField>(fieldsToInitializers.keySet());

    Collections.sort(
        initializedFields,
        new Comparator<PsiField>() {
          public int compare(PsiField field1, PsiField field2) {
            Initializer i1 = fieldsToInitializers.get(field1);
            Initializer i2 = fieldsToInitializers.get(field2);
            if (i1.movedFieldsUsed.contains(field2)) return 1;
            if (i2.movedFieldsUsed.contains(field1)) return -1;
            return 0;
          }
        });

    for (final PsiField initializedField : initializedFields) {
      Initializer initializer = fieldsToInitializers.get(initializedField);

      // correct constructor parameters and subConstructors super calls
      final PsiParameterList parameterList = constructor.getParameterList();
      for (final PsiParameter parameter : initializer.usedParameters) {
        parameterList.add(parameter);
      }

      for (final PsiMethod subConstructor : subConstructors) {
        modifySuperCall(subConstructor, initializer.usedParameters);
      }

      PsiStatement assignmentStatement =
          (PsiStatement) constructor.getBody().add(initializer.initializer);

      PsiManager manager = PsiManager.getInstance(myProject);
      ChangeContextUtil.decodeContextInfo(
          assignmentStatement,
          myTargetSuperClass,
          RefactoringChangeUtil.createThisExpression(manager, null));
      for (PsiElement psiElement : initializer.statementsToRemove) {
        psiElement.delete();
      }
    }
  }
  private static boolean addParameterToConstructor(
      final Project project,
      final PsiFile file,
      final Editor editor,
      final PsiMethod constructor,
      final PsiField[] fields)
      throws IncorrectOperationException {
    final PsiParameterList parameterList = constructor.getParameterList();
    final PsiParameter[] parameters = parameterList.getParameters();
    ParameterInfoImpl[] newParamInfos = new ParameterInfoImpl[parameters.length + fields.length];
    final List<PsiVariable> params = new ArrayList<PsiVariable>(Arrays.asList(parameters));
    Collections.addAll(params, fields);
    Collections.sort(params, new FieldParameterComparator(parameterList));

    int i = 0;
    final HashMap<PsiField, String> usedFields = new HashMap<PsiField, String>();
    for (PsiVariable param : params) {
      final PsiType paramType = param.getType();
      if (param instanceof PsiParameter) {
        newParamInfos[i++] =
            new ParameterInfoImpl(
                parameterList.getParameterIndex((PsiParameter) param),
                param.getName(),
                paramType,
                param.getName());
      } else {
        final String uniqueParameterName = getUniqueParameterName(parameters, param, usedFields);
        usedFields.put((PsiField) param, uniqueParameterName);
        newParamInfos[i++] =
            new ParameterInfoImpl(-1, uniqueParameterName, paramType, uniqueParameterName);
      }
    }
    final SmartPointerManager manager = SmartPointerManager.getInstance(project);
    final SmartPsiElementPointer constructorPointer =
        manager.createSmartPsiElementPointer(constructor);

    final PsiMethod fromText =
        JavaPsiFacade.getElementFactory(project)
            .createMethodFromText(createDummyMethod(constructor, newParamInfos), constructor);
    final PsiClass containingClass = constructor.getContainingClass();
    if (containingClass == null) return false;
    final int minUsagesNumber =
        containingClass.findMethodsBySignature(fromText, false).length > 0 ? 0 : 1;
    final List<ParameterInfoImpl> parameterInfos =
        ChangeMethodSignatureFromUsageFix.performChange(
            project, editor, file, constructor, minUsagesNumber, newParamInfos, true, true);

    final ParameterInfoImpl[] resultParams =
        parameterInfos != null
            ? parameterInfos.toArray(new ParameterInfoImpl[parameterInfos.size()])
            : newParamInfos;
    return ApplicationManager.getApplication()
        .runWriteAction(
            new Computable<Boolean>() {
              @Override
              public Boolean compute() {
                return doCreate(
                    project, editor, parameters, constructorPointer, resultParams, usedFields);
              }
            });
  }
  @NotNull
  @Override
  public Runnable processFile(final PsiFile file) {
    VirtualFile vFile = file.getVirtualFile();
    if (vFile instanceof VirtualFileWindow) vFile = ((VirtualFileWindow) vFile).getDelegate();
    final Project project = file.getProject();
    if (vFile == null
        || !ProjectRootManager.getInstance(project).getFileIndex().isInSourceContent(vFile)) {
      return EmptyRunnable.INSTANCE;
    }
    final List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>();
    final Set<String> demandedForNested = new HashSet<>();
    collectNamesToImport(names, demandedForNested, (XmlFile) file);
    Collections.sort(names, (o1, o2) -> StringUtil.compare(o1.first, o2.first, true));
    final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project);
    final List<Pair<String, Boolean>> sortedNames =
        ImportHelper.sortItemsAccordingToSettings(names, settings);
    final HashSet<String> onDemand = new HashSet<String>();
    ImportHelper.collectOnDemandImports(sortedNames, onDemand, settings);
    onDemand.addAll(demandedForNested);
    final Set<String> imported = new HashSet<String>();
    final List<String> imports = new ArrayList<String>();
    for (Pair<String, Boolean> pair : sortedNames) {
      final String qName = pair.first;
      final String packageName = StringUtil.getPackageName(qName);
      if (imported.contains(packageName) || imported.contains(qName)) {
        continue;
      }
      if (onDemand.contains(packageName)) {
        imported.add(packageName);
        imports.add("<?import " + packageName + ".*?>");
      } else {
        imported.add(qName);
        imports.add("<?import " + qName + "?>");
      }
    }
    final PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject());

    final XmlFile dummyFile =
        (XmlFile)
            factory.createFileFromText(
                "_Dummy_.fxml", StdFileTypes.XML, StringUtil.join(imports, "\n"));
    final XmlDocument document = dummyFile.getDocument();
    final XmlProlog newImportList = document != null ? document.getProlog() : null;
    if (newImportList == null) return EmptyRunnable.getInstance();
    return () -> {
      final XmlDocument xmlDocument = ((XmlFile) file).getDocument();
      final XmlProlog prolog = xmlDocument != null ? xmlDocument.getProlog() : null;
      if (prolog != null) {
        final Collection<XmlProcessingInstruction> instructions =
            PsiTreeUtil.findChildrenOfType(prolog, XmlProcessingInstruction.class);
        for (final XmlProcessingInstruction instruction : instructions) {
          final ASTNode node = instruction.getNode();
          final ASTNode nameNode = node.findChildByType(XmlTokenType.XML_NAME);
          if (nameNode != null && nameNode.getText().equals("import")) {
            instruction.delete();
          }
        }
        prolog.add(newImportList);
      } else {
        document.addBefore(newImportList, document.getRootTag());
      }
    };
  }
  @Override
  @Nullable
  public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
    final PsiFile containingFile = listOwner.getContainingFile();
    if (!(containingFile instanceof PsiJavaFile)) {
      return null;
    }
    final PsiJavaFile javaFile = (PsiJavaFile) containingFile;
    final String packageName = javaFile.getPackageName();
    final VirtualFile virtualFile = containingFile.getVirtualFile();
    if (virtualFile == null) return null;

    final List<PsiFile> files = myExternalAnnotations.get(virtualFile);
    if (files == NULL_LIST) return null;
    if (files != null) {
      boolean allValid = true;
      for (PsiFile file : files) {
        allValid &= file.isValid();
      }
      if (allValid) {
        return files;
      }
    }

    if (virtualFile == null) {
      return null;
    }

    Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>();
    for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) {
      final VirtualFile ext =
          root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML);
      if (ext == null) continue;
      final PsiFile psiFile = myPsiManager.findFile(ext);
      if (psiFile == null) continue;
      possibleAnnotationsXmls.add(psiFile);
    }
    List<PsiFile> result;
    if (possibleAnnotationsXmls.isEmpty()) {
      myExternalAnnotations.put(virtualFile, NULL_LIST);
      result = null;
    } else {
      result = new SmartList<PsiFile>(possibleAnnotationsXmls);
      // sorting by writability: writable go first
      Collections.sort(
          result,
          new Comparator<PsiFile>() {
            @Override
            public int compare(PsiFile f1, PsiFile f2) {
              boolean w1 = f1.isWritable();
              boolean w2 = f2.isWritable();
              if (w1 == w2) {
                return 0;
              }
              return w1 ? -1 : 1;
            }
          });

      myExternalAnnotations.put(virtualFile, result);
    }
    return result;
  }