private static PsiSubstitutor obtainFinalSubstitutor(
      PsiClass superClass,
      PsiSubstitutor superSubstitutor,
      PsiSubstitutor derivedSubstitutor,
      boolean inRawContext) {
    if (inRawContext) {
      Set<PsiTypeParameter> typeParams = superSubstitutor.getSubstitutionMap().keySet();
      PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject());
      superSubstitutor =
          factory.createRawSubstitutor(
              derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()]));
    }
    Map<PsiTypeParameter, PsiType> map = null;
    for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) {
      PsiType type = superSubstitutor.substitute(typeParameter);
      final PsiType t = derivedSubstitutor.substitute(type);
      if (map == null) {
        map = new THashMap<PsiTypeParameter, PsiType>();
      }
      map.put(typeParameter, t);
    }

    return map == null
        ? PsiSubstitutor.EMPTY
        : JavaPsiFacade.getInstance(superClass.getProject())
            .getElementFactory()
            .createSubstitutor(map);
  }
 @Override
 @NotNull
 public Document[] getUncommittedDocuments() {
   ApplicationManager.getApplication().assertIsDispatchThread();
   Document[] documents =
       myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]);
   return ArrayUtil.stripTrailingNulls(documents);
 }
 @NotNull
 private static GlobalSearchScope forDirectory(
     @NotNull Project project, boolean withSubdirectories, @NotNull VirtualFile directory) {
   Set<VirtualFile> result = new LinkedHashSet<>();
   result.add(directory);
   addSourceDirectoriesFromLibraries(project, directory, result);
   VirtualFile[] array = result.toArray(new VirtualFile[result.size()]);
   return GlobalSearchScopesCore.directoriesScope(project, withSubdirectories, array);
 }
  @Override
  @NotNull
  public Object[] getVariants() {
    Set<PsiPackage> subPackages = new HashSet<>();
    for (PsiPackage psiPackage : getContext()) {
      subPackages.addAll(
          Arrays.asList(psiPackage.getSubPackages(myReferenceSet.getResolveScope())));
    }

    return subPackages.toArray();
  }
  @NotNull
  public PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
    PsiVariable[] myOutputVariables =
        ControlFlowUtil.getOutputVariables(
            myControlFlow, myFlowStart, myFlowEnd, myExitPoints.toArray());
    if (collectVariablesAtExitPoints) {
      // variables declared in selected block used in return statements are to be considered output
      // variables when extracting guard methods
      final Set<PsiVariable> outputVariables = new HashSet<>(Arrays.asList(myOutputVariables));
      for (PsiStatement statement : myExitStatements) {
        statement.accept(
            new JavaRecursiveElementVisitor() {

              @Override
              public void visitReferenceExpression(PsiReferenceExpression expression) {
                super.visitReferenceExpression(expression);
                final PsiElement resolved = expression.resolve();
                if (resolved instanceof PsiVariable) {
                  final PsiVariable variable = (PsiVariable) resolved;
                  if (isWrittenInside(variable)) {
                    outputVariables.add(variable);
                  }
                }
              }

              private boolean isWrittenInside(final PsiVariable variable) {
                final List<Instruction> instructions = myControlFlow.getInstructions();
                for (int i = myFlowStart; i < myFlowEnd; i++) {
                  Instruction instruction = instructions.get(i);
                  if (instruction instanceof WriteVariableInstruction
                      && variable.equals(((WriteVariableInstruction) instruction).variable)) {
                    return true;
                  }
                }

                return false;
              }
            });
      }

      myOutputVariables = outputVariables.toArray(new PsiVariable[outputVariables.size()]);
    }
    Arrays.sort(myOutputVariables, PsiUtil.BY_POSITION);
    return myOutputVariables;
  }
 @Override
 @NotNull
 public Document[] getUncommittedDocuments() {
   ApplicationManager.getApplication().assertIsDispatchThread();
   return myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]);
 }
  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;
  }