public static void doRenameGenericNamedElement(
      @NotNull PsiElement namedElement,
      String newName,
      UsageInfo[] usages,
      @Nullable RefactoringElementListener listener)
      throws IncorrectOperationException {
    PsiWritableMetaData writableMetaData = null;
    if (namedElement instanceof PsiMetaOwner) {
      final PsiMetaData metaData = ((PsiMetaOwner) namedElement).getMetaData();
      if (metaData instanceof PsiWritableMetaData) {
        writableMetaData = (PsiWritableMetaData) metaData;
      }
    }
    if (writableMetaData == null && !(namedElement instanceof PsiNamedElement)) {
      LOG.error("Unknown element type:" + namedElement);
    }

    boolean hasBindables = false;
    for (UsageInfo usage : usages) {
      if (!(usage.getReference() instanceof BindablePsiReference)) {
        rename(usage, newName);
      } else {
        hasBindables = true;
      }
    }

    if (writableMetaData != null) {
      writableMetaData.setName(newName);
    } else {
      PsiElement namedElementAfterRename = ((PsiNamedElement) namedElement).setName(newName);
      if (namedElementAfterRename != null) namedElement = namedElementAfterRename;
    }

    if (hasBindables) {
      for (UsageInfo usage : usages) {
        final PsiReference ref = usage.getReference();
        if (ref instanceof BindablePsiReference) {
          try {
            ref.bindToElement(namedElement);
          } catch (IncorrectOperationException e) { // fall back to old scheme
            ref.handleElementRename(newName);
          }
        }
      }
    }
    if (listener != null) {
      listener.elementRenamed(namedElement);
    }
  }
 @Nullable
 static PsiElement resolveReference(final PsiReference psiReference) {
   if (psiReference instanceof PsiPolyVariantReference) {
     final ResolveResult[] results = ((PsiPolyVariantReference) psiReference).multiResolve(true);
     if (results.length == 1) return results[0].getElement();
   }
   return psiReference.resolve();
 }
  // need to shorten references in type argument list
  public static void shortenReference(final PsiFile file, final int offset)
      throws IncorrectOperationException {
    Project project = file.getProject();
    final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
    Document document = manager.getDocument(file);
    if (document == null) {
      PsiUtilCore.ensureValid(file);
      LOG.error("No document for " + file);
      return;
    }

    manager.commitDocument(document);
    final PsiReference ref = file.findReferenceAt(offset);
    if (ref != null) {
      PsiElement element = ref.getElement();
      if (element != null) {
        JavaCodeStyleManager.getInstance(project).shortenClassReferences(element);
        PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
      }
    }
  }
  @NotNull
  public static UsageInfo[] findUsages(
      final PsiElement element,
      final String newName,
      boolean searchInStringsAndComments,
      boolean searchForTextOccurrences,
      Map<? extends PsiElement, String> allRenames) {
    final List<UsageInfo> result = Collections.synchronizedList(new ArrayList<UsageInfo>());

    PsiManager manager = element.getManager();
    GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
    RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);

    Collection<PsiReference> refs = processor.findReferences(element, searchInStringsAndComments);
    for (final PsiReference ref : refs) {
      if (ref == null) {
        LOG.error("null reference from processor " + processor);
        continue;
      }
      PsiElement referenceElement = ref.getElement();
      result.add(
          new MoveRenameUsageInfo(
              referenceElement,
              ref,
              ref.getRangeInElement().getStartOffset(),
              ref.getRangeInElement().getEndOffset(),
              element,
              ref.resolve() == null));
    }

    processor.findCollisions(element, newName, allRenames, result);

    final PsiElement searchForInComments =
        processor.getElementToSearchInStringsAndComments(element);

    if (searchInStringsAndComments && searchForInComments != null) {
      String stringToSearch =
          ElementDescriptionUtil.getElementDescription(
              searchForInComments, NonCodeSearchDescriptionLocation.STRINGS_AND_COMMENTS);
      if (stringToSearch.length() > 0) {
        final String stringToReplace = getStringToReplace(element, newName, false, processor);
        TextOccurrencesUtil.UsageInfoFactory factory =
            new NonCodeUsageInfoFactory(searchForInComments, stringToReplace);
        TextOccurrencesUtil.addUsagesInStringsAndComments(
            searchForInComments, stringToSearch, result, factory);
      }
    }

    if (searchForTextOccurrences && searchForInComments != null) {
      String stringToSearch =
          ElementDescriptionUtil.getElementDescription(
              searchForInComments, NonCodeSearchDescriptionLocation.NON_JAVA);
      if (stringToSearch.length() > 0) {
        final String stringToReplace = getStringToReplace(element, newName, true, processor);
        addTextOccurrence(
            searchForInComments, result, projectScope, stringToSearch, stringToReplace);
      }

      final Pair<String, String> additionalStringToSearch =
          processor.getTextOccurrenceSearchStrings(searchForInComments, newName);
      if (additionalStringToSearch != null && additionalStringToSearch.first.length() > 0) {
        addTextOccurrence(
            searchForInComments,
            result,
            projectScope,
            additionalStringToSearch.first,
            additionalStringToSearch.second);
      }
    }

    return result.toArray(new UsageInfo[result.size()]);
  }
 public static void rename(UsageInfo info, String newName) throws IncorrectOperationException {
   if (info.getElement() == null) return;
   PsiReference ref = info.getReference();
   if (ref == null) return;
   ref.handleElementRename(newName);
 }
  public static int insertClassReference(
      PsiClass psiClass, PsiFile file, int startOffset, int endOffset) {
    final Project project = file.getProject();
    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
    documentManager.commitAllDocuments();

    final PsiManager manager = file.getManager();

    final Document document =
        FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile());

    final PsiReference reference = file.findReferenceAt(startOffset);
    if (reference != null) {
      final PsiElement resolved = reference.resolve();
      if (resolved instanceof PsiClass) {
        if (((PsiClass) resolved).getQualifiedName() == null
            || manager.areElementsEquivalent(psiClass, resolved)) {
          return endOffset;
        }
      }
    }

    String name = psiClass.getName();
    if (name == null) {
      return endOffset;
    }

    assert document != null;
    document.replaceString(startOffset, endOffset, name);

    int newEndOffset = startOffset + name.length();
    final RangeMarker toDelete = insertTemporary(newEndOffset, document, " ");

    documentManager.commitAllDocuments();

    PsiElement element = file.findElementAt(startOffset);
    if (element instanceof PsiIdentifier) {
      PsiElement parent = element.getParent();
      if (parent instanceof PsiJavaCodeReferenceElement
          && !((PsiJavaCodeReferenceElement) parent).isQualified()
          && !(parent.getParent() instanceof PsiPackageStatement)) {
        PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent;

        if (psiClass.isValid()
            && !psiClass.getManager().areElementsEquivalent(psiClass, resolveReference(ref))) {
          final boolean staticImport = ref instanceof PsiImportStaticReferenceElement;
          PsiElement newElement;
          try {
            newElement =
                staticImport
                    ? ((PsiImportStaticReferenceElement) ref).bindToTargetClass(psiClass)
                    : ref.bindToElement(psiClass);
          } catch (IncorrectOperationException e) {
            return endOffset; // can happen if fqn contains reserved words, for example
          }

          final RangeMarker rangeMarker = document.createRangeMarker(newElement.getTextRange());
          documentManager.doPostponedOperationsAndUnblockDocument(document);
          documentManager.commitDocument(document);

          newElement =
              CodeInsightUtilCore.findElementInRange(
                  file,
                  rangeMarker.getStartOffset(),
                  rangeMarker.getEndOffset(),
                  PsiJavaCodeReferenceElement.class,
                  JavaLanguage.INSTANCE);
          rangeMarker.dispose();
          if (newElement != null) {
            newEndOffset = newElement.getTextRange().getEndOffset();
            if (!(newElement instanceof PsiReferenceExpression)) {
              PsiReferenceParameterList parameterList =
                  ((PsiJavaCodeReferenceElement) newElement).getParameterList();
              if (parameterList != null) {
                newEndOffset = parameterList.getTextRange().getStartOffset();
              }
            }

            if (!staticImport
                && !psiClass
                    .getManager()
                    .areElementsEquivalent(psiClass, resolveReference((PsiReference) newElement))
                && !PsiUtil.isInnerClass(psiClass)) {
              final String qName = psiClass.getQualifiedName();
              if (qName != null) {
                document.replaceString(
                    newElement.getTextRange().getStartOffset(), newEndOffset, qName);
                newEndOffset = newElement.getTextRange().getStartOffset() + qName.length();
              }
            }
          }
        }
      }
    }

    if (toDelete.isValid()) {
      document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset());
    }

    return newEndOffset;
  }