@NotNull
  private static Couple<Collection<TextRange>> getUsages(
      @NotNull PsiElement target,
      PsiElement psiElement,
      boolean withDeclarations,
      boolean detectAccess) {
    List<TextRange> readRanges = new ArrayList<TextRange>();
    List<TextRange> writeRanges = new ArrayList<TextRange>();
    final ReadWriteAccessDetector detector =
        detectAccess ? ReadWriteAccessDetector.findDetector(target) : null;
    final FindUsagesManager findUsagesManager =
        ((FindManagerImpl) FindManager.getInstance(target.getProject())).getFindUsagesManager();
    final FindUsagesHandler findUsagesHandler =
        findUsagesManager.getFindUsagesHandler(target, true);
    final LocalSearchScope scope = new LocalSearchScope(psiElement);
    Collection<PsiReference> refs =
        findUsagesHandler != null
            ? findUsagesHandler.findReferencesToHighlight(target, scope)
            : ReferencesSearch.search(target, scope).findAll();
    for (PsiReference psiReference : refs) {
      if (psiReference == null) {
        LOG.error(
            "Null reference returned, findUsagesHandler="
                + findUsagesHandler
                + "; target="
                + target
                + " of "
                + target.getClass());
        continue;
      }
      List<TextRange> destination;
      if (detector == null
          || detector.getReferenceAccess(target, psiReference)
              == ReadWriteAccessDetector.Access.Read) {
        destination = readRanges;
      } else {
        destination = writeRanges;
      }
      HighlightUsagesHandler.collectRangesToHighlight(psiReference, destination);
    }

    if (withDeclarations) {
      final TextRange declRange =
          HighlightUsagesHandler.getNameIdentifierRange(psiElement.getContainingFile(), target);
      if (declRange != null) {
        if (detector != null && detector.isDeclarationWriteAccess(target)) {
          writeRanges.add(declRange);
        } else {
          readRanges.add(declRange);
        }
      }
    }

    return Couple.<Collection<TextRange>>of(readRanges, writeRanges);
  }
  public void actionPerformed(AnActionEvent e) {
    DataContext dataContext = e.getDataContext();
    Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
    Project project = PlatformDataKeys.PROJECT.getData(dataContext);
    PsiElement element = getElementToCopy(editor, dataContext);

    if (!doCopy(element, project, editor) && editor != null) {
      Document document = editor.getDocument();
      PsiFile file = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
      if (file != null) {
        String toCopy =
            getFileFqn(file) + ":" + (editor.getCaretModel().getLogicalPosition().line + 1);
        CopyPasteManager.getInstance().setContents(new StringSelection(toCopy));
        setStatusBarText(project, toCopy + " has been copied");
      }
      return;
    }

    HighlightManager highlightManager = HighlightManager.getInstance(project);
    EditorColorsManager manager = EditorColorsManager.getInstance();
    TextAttributes attributes =
        manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
    if (element != null && editor != null) {
      PsiElement nameIdentifier = HighlightUsagesHandler.getNameIdentifier(element);
      if (nameIdentifier != null) {
        highlightManager.addOccurrenceHighlights(
            editor, new PsiElement[] {nameIdentifier}, attributes, true, null);
      } else {
        PsiReference reference =
            TargetElementUtilBase.findReference(editor, editor.getCaretModel().getOffset());
        if (reference != null) {
          highlightManager.addOccurrenceHighlights(
              editor, new PsiReference[] {reference}, attributes, true, null);
        } else {
          highlightManager.addOccurrenceHighlights(
              editor, new PsiElement[] {element}, attributes, true, null);
        }
      }
    }
  }
  @Override
  public void doCollectInformation(@NotNull final ProgressIndicator progress) {
    @SuppressWarnings("unchecked")
    HighlightUsagesHandlerBase<PsiElement> handler =
        HighlightUsagesHandler.createCustomHandler(myEditor, myFile);
    if (handler != null) {
      List<PsiElement> targets = handler.getTargets();
      handler.computeUsages(targets);
      final List<TextRange> readUsages = handler.getReadUsages();
      for (TextRange readUsage : readUsages) {
        LOG.assertTrue(readUsage != null, "null text range from " + handler);
      }
      myReadAccessRanges.addAll(readUsages);
      final List<TextRange> writeUsages = handler.getWriteUsages();
      for (TextRange writeUsage : writeUsages) {
        LOG.assertTrue(writeUsage != null, "null text range from " + handler);
      }
      myWriteAccessRanges.addAll(writeUsages);
      if (!handler.highlightReferences()) return;
    }

    int flags =
        TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED;
    PsiElement myTarget;
    try {
      myTarget = TargetElementUtil.getInstance().findTargetElement(myEditor, flags, myCaretOffset);
    } catch (IndexNotReadyException e) {
      return;
    }

    if (myTarget == null) {
      if (!PsiDocumentManager.getInstance(myProject).isUncommited(myEditor.getDocument())) {
        // when document is committed, try to check injected stuff - it's fast
        Editor injectedEditor =
            InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(
                myEditor, myFile, myCaretOffset);
        myTarget =
            TargetElementUtil.getInstance()
                .findTargetElement(
                    injectedEditor, flags, injectedEditor.getCaretModel().getOffset());
      }
    }

    if (myTarget != null) {
      highlightTargetUsages(myTarget);
    } else {
      PsiReference ref = TargetElementUtil.findReference(myEditor);
      if (ref instanceof PsiPolyVariantReference) {
        if (!ref.getElement().isValid()) {
          throw new PsiInvalidElementAccessException(
              ref.getElement(),
              "Invalid element in " + ref + " of " + ref.getClass() + "; editor=" + myEditor);
        }
        ResolveResult[] results = ((PsiPolyVariantReference) ref).multiResolve(false);
        if (results.length > 0) {
          for (ResolveResult result : results) {
            PsiElement target = result.getElement();
            if (target != null) {
              if (!target.isValid()) {
                throw new PsiInvalidElementAccessException(
                    target,
                    "Invalid element returned from "
                        + ref
                        + " of "
                        + ref.getClass()
                        + "; editor="
                        + myEditor);
              }
              highlightTargetUsages(target);
            }
          }
        }
      }
    }
  }
 protected void ctrlShiftF7() {
   HighlightUsagesHandler.invoke(getProject(), getEditor(), getFile());
 }
  @Override
  @Nullable
  public CommonProblemDescriptor[] checkElement(
      @NotNull final RefEntity refEntity,
      @NotNull final AnalysisScope scope,
      @NotNull final InspectionManager manager,
      @NotNull final GlobalInspectionContext globalContext,
      @NotNull final ProblemDescriptionsProcessor processor) {
    if (refEntity instanceof RefJavaElement) {
      final RefJavaElement refElement = (RefJavaElement) refEntity;

      if (refElement instanceof RefParameter) return null;
      if (refElement.isSyntheticJSP()) return null;

      // ignore entry points.
      if (refElement.isEntry()) return null;

      // ignore implicit constructors. User should not be able to see them.
      if (refElement instanceof RefImplicitConstructor) return null;

      if (refElement instanceof RefField
          && ((RefField) refElement).getElement() instanceof PsiEnumConstant) return null;

      // ignore library override methods.
      if (refElement instanceof RefMethod) {
        RefMethod refMethod = (RefMethod) refElement;
        if (refMethod.isExternalOverride()) return null;
        if (refMethod.isEntry()) return null;
      }

      // ignore anonymous classes. They do not have access modifiers.
      if (refElement instanceof RefClass) {
        RefClass refClass = (RefClass) refElement;
        if (refClass.isAnonymous()
            || refClass.isEntry()
            || refClass.isTestCase()
            || refClass.isServlet()
            || refClass.isApplet()
            || refClass.isLocalClass()) return null;
        if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
      }

      // ignore unreferenced code. They could be a potential entry points.
      if (refElement.getInReferences().isEmpty()) return null;

      // ignore interface members. They always have public access modifier.
      if (refElement.getOwner() instanceof RefClass) {
        RefClass refClass = (RefClass) refElement.getOwner();
        if (refClass.isInterface()) return null;
      }
      String access = getPossibleAccess(refElement);
      if (access != refElement.getAccessModifier() && access != null) {
        final PsiElement element = refElement.getElement();
        final PsiElement nameIdentifier =
            element != null ? HighlightUsagesHandler.getNameIdentifier(element) : null;
        if (nameIdentifier != null) {
          return new ProblemDescriptor[] {
            manager.createProblemDescriptor(
                nameIdentifier,
                access.equals(PsiModifier.PRIVATE)
                    ? CAN_BE_PRIVATE
                    : access.equals(PsiModifier.PACKAGE_LOCAL)
                        ? CAN_BE_PACKAGE_LOCAL
                        : CAN_BE_PROTECTED,
                new AcceptSuggestedAccess(globalContext.getRefManager(), access),
                ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                false)
          };
        }
      }
    }
    return null;
  }