protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    checkExistingMethods(conflicts, true);
    checkExistingMethods(conflicts, false);
    final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final Set<PsiMethod> setters = new HashSet<PsiMethod>();
      final Set<PsiMethod> getters = new HashSet<PsiMethod>();

      for (PsiClass aClass : classes) {
        final PsiMethod getterOverrider =
            myDescriptor.isToEncapsulateGet()
                ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false)
                : null;
        if (getterOverrider != null) {
          getters.add(getterOverrider);
        }
        final PsiMethod setterOverrider =
            myDescriptor.isToEncapsulateSet()
                ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false)
                : null;
        if (setterOverrider != null) {
          setters.add(setterOverrider);
        }
      }
      if (!getters.isEmpty() || !setters.isEmpty()) {
        final PsiField field = fieldDescriptor.getField();
        for (PsiReference reference : ReferencesSearch.search(field)) {
          final PsiElement place = reference.getElement();
          if (place instanceof PsiReferenceExpression) {
            final PsiExpression qualifierExpression =
                ((PsiReferenceExpression) place).getQualifierExpression();
            final PsiClass ancestor;
            if (qualifierExpression == null) {
              ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
            } else {
              ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType());
            }

            final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place);
            for (PsiMethod overridden : isGetter ? getters : setters) {
              if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) {
                conflicts.putValue(
                    overridden,
                    "There is already a "
                        + RefactoringUIUtil.getDescription(overridden, true)
                        + " which would hide generated "
                        + (isGetter ? "getter" : "setter")
                        + " for "
                        + place.getText());
                break;
              }
            }
          }
        }
      }
    }
    return showConflicts(conflicts, refUsages.get());
  }
Esempio n. 2
0
 public String[] knownNamespaces() {
   final PsiElement parentElement = getParent();
   BidirectionalMap<String, String> map = initNamespaceMaps(parentElement);
   Set<String> known = Collections.emptySet();
   if (map != null) {
     known = new HashSet<String>(map.values());
   }
   if (parentElement instanceof XmlTag) {
     if (known.isEmpty()) return ((XmlTag) parentElement).knownNamespaces();
     ContainerUtil.addAll(known, ((XmlTag) parentElement).knownNamespaces());
   } else {
     XmlExtension xmlExtension = XmlExtension.getExtensionByElement(this);
     if (xmlExtension != null) {
       final XmlFile xmlFile = xmlExtension.getContainingFile(this);
       if (xmlFile != null) {
         final XmlTag rootTag = xmlFile.getRootTag();
         if (rootTag != null && rootTag != this) {
           if (known.isEmpty()) return rootTag.knownNamespaces();
           ContainerUtil.addAll(known, rootTag.knownNamespaces());
         }
       }
     }
   }
   return ArrayUtil.toStringArray(known);
 }
  private static Map<String, PsiType> getCompatibleTypeNames(
      @NotNull PsiType type, @Nullable PsiType min, PsiManager manager, GlobalSearchScope scope) {
    if (type instanceof PsiDisjunctionType) type = ((PsiDisjunctionType) type).getLeastUpperBound();

    // if initial type is not assignable to min type we don't take into consideration min type.
    if (min != null && !TypesUtil.isAssignable(min, type, manager, scope)) {
      min = null;
    }

    Map<String, PsiType> map = new LinkedHashMap<String, PsiType>();
    final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type);
    if (unboxed != null) type = unboxed;
    final Set<PsiType> set = new LinkedHashSet<PsiType>();
    set.add(type);
    while (!set.isEmpty()) {
      PsiType cur = set.iterator().next();
      set.remove(cur);
      if (!map.containsValue(cur)
          && (min == null || TypesUtil.isAssignable(min, cur, manager, scope))) {
        if (isPartiallySubstituted(cur)) {
          LOG.assertTrue(cur instanceof PsiClassType);
          PsiClassType rawType = ((PsiClassType) cur).rawType();
          map.put(rawType.getPresentableText(), rawType);
        } else {
          map.put(cur.getPresentableText(), cur);
        }
        for (PsiType superType : cur.getSuperTypes()) {
          if (!map.containsValue(superType)) {
            set.add(superType);
          }
        }
      }
    }
    return map;
  }
  public Set<InferenceVariable> getDependencies(InferenceSession session) {
    final Set<InferenceVariable> dependencies = new LinkedHashSet<InferenceVariable>();
    for (List<PsiType> boundTypes : myBounds.values()) {
      if (boundTypes != null) {
        for (PsiType bound : boundTypes) {
          session.collectDependencies(bound, dependencies);
        }
      }
    }

    if (!session.hasCapture(this) && dependencies.isEmpty()) {
      return dependencies;
    }

    if (!session.hasCapture(this)) {
      return dependencies;
    }

    for (Iterator<InferenceVariable> iterator = dependencies.iterator(); iterator.hasNext(); ) {
      if (!session.hasCapture(iterator.next())) {
        iterator.remove();
      }
    }
    session.collectCaptureDependencies(this, dependencies);
    return dependencies;
  }
    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      AllowedValues a2 = (AllowedValues) o;
      if (canBeOred != a2.canBeOred) {
        return false;
      }
      Set<PsiAnnotationMemberValue> v1 =
          new THashSet<PsiAnnotationMemberValue>(Arrays.asList(values));
      Set<PsiAnnotationMemberValue> v2 =
          new THashSet<PsiAnnotationMemberValue>(Arrays.asList(a2.values));
      if (v1.size() != v2.size()) {
        return false;
      }
      for (PsiAnnotationMemberValue value : v1) {
        for (PsiAnnotationMemberValue value2 : v2) {
          if (same(value, value2, value.getManager())) {
            v2.remove(value2);
            break;
          }
        }
      }
      return v2.isEmpty();
    }
  @Override
  public void run() {
    while (!myDisposed) {
      boolean isEmpty;
      synchronized (filesToResolve) {
        isEmpty = filesToResolve.isEmpty();
      }
      if (enableVetoes.get() > 0
          || isEmpty
          || !resolveProcess.isDone()
          || HeavyProcessLatch.INSTANCE.isRunning()
          || PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) {
        try {
          waitForQueue();
        } catch (InterruptedException e) {
          break;
        }
        continue;
      }
      final Set<VirtualFile> files = pollFilesToResolve();
      if (files.isEmpty()) continue;

      upToDate = false;

      myApplication.invokeLater(
          () -> {
            if (!resolveProcess.isDone()) return;
            log("Started to resolve " + files.size() + " files");

            Task.Backgroundable backgroundable =
                new Task.Backgroundable(myProject, "Resolving files...", false) {
                  @Override
                  public void run(@NotNull final ProgressIndicator indicator) {
                    if (!myApplication.isDisposed()) {
                      processBatch(indicator, files);
                    }
                  }
                };
            ProgressIndicator indicator;
            if (files.size() > 1) {
              // show progress
              indicator = new BackgroundableProcessIndicator(backgroundable);
            } else {
              indicator = new MyProgress();
            }
            resolveProcess =
                ((ProgressManagerImpl) ProgressManager.getInstance())
                    .runProcessWithProgressAsynchronously(backgroundable, indicator, null);
          },
          myProject.getDisposed());

      flushLog();
    }
  }
Esempio n. 7
0
 @Override
 public boolean process(PsiClass inheritor) {
   ProgressManager.checkCanceled();
   for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) {
     ProgressManager.checkCanceled();
     PsiClass anInterface = interfaceType.resolveGenerics().getElement();
     if (anInterface != null && myCheckedInterfaces.add(PsiAnchor.create(anInterface))) {
       processInterface(inheritor, anInterface);
     }
   }
   return !myRemainingMethods.isEmpty();
 }
  @Override
  public void commitAllDocuments() {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (myUncommittedDocuments.isEmpty()) return;

    final Document[] documents = getUncommittedDocuments();
    for (Document document : documents) {
      commitDocument(document);
    }

    LOG.assertTrue(!hasUncommitedDocuments(), myUncommittedDocuments);
  }
 /**
  * Cancel previously registered action and schedules (new) action to be executed when all
  * documents are committed.
  *
  * @param key the (unique) id of the action.
  * @param action The action to be executed after automatic commit. This action will overwrite any
  *     action which was registered under this key earlier. The action will be executed in EDT.
  * @return true if action has been run immediately, or false if action was scheduled for execution
  *     later.
  */
 public boolean cancelAndRunWhenAllCommitted(
     @NonNls @NotNull Object key, @NotNull final Runnable action) {
   ApplicationManager.getApplication().assertIsDispatchThread();
   if (myProject.isDisposed()) {
     action.run();
     return true;
   }
   if (myUncommittedDocuments.isEmpty()) {
     action.run();
     assert actionsWhenAllDocumentsAreCommitted.isEmpty() : actionsWhenAllDocumentsAreCommitted;
     return true;
   }
   actionsWhenAllDocumentsAreCommitted.put(key, action);
   return false;
 }
  @Override
  public void writeExternal(Element element) throws WriteExternalException {
    super.writeExternal(element);
    JavaRunConfigurationExtensionManager.getInstance().writeExternal(this, element);
    writeModule(element);
    DefaultJDOMExternalizer.writeExternal(this, element);
    DefaultJDOMExternalizer.writeExternal(getPersistantData(), element);
    EnvironmentVariablesComponent.writeExternal(element, getPersistantData().getEnvs());

    Element propertiesElement = element.getChild("properties");

    if (propertiesElement == null) {
      propertiesElement = new Element("properties");
      element.addContent(propertiesElement);
    }

    Map<String, String> properties = getPersistantData().TEST_PROPERTIES;
    for (Map.Entry<String, String> entry : properties.entrySet()) {
      Element property = new Element("property");
      property.setAttribute("name", entry.getKey());
      property.setAttribute("value", entry.getValue());
      propertiesElement.addContent(property);
    }

    Element listenersElement = element.getChild("listeners");
    if (listenersElement == null) {
      listenersElement = new Element("listeners");
      element.addContent(listenersElement);
    }

    List<String> listeners = getPersistantData().TEST_LISTENERS;
    for (String listener : listeners) {
      Element listenerElement = new Element("listener");
      listenerElement.setAttribute("class", listener);
      listenersElement.addContent(listenerElement);
    }
    final Set<String> patterns = getPersistantData().getPatterns();
    if (!patterns.isEmpty()) {
      final Element patternsElement = new Element(PATTERNS_EL_NAME);
      for (String o : patterns) {
        final Element patternElement = new Element(PATTERN_EL_NAME);
        patternElement.setAttribute(TEST_CLASS_ATT_NAME, o);
        patternsElement.addContent(patternElement);
      }
      element.addContent(patternsElement);
    }
  }
  private static boolean hasSuperMethodsWithoutExceptions(
      @NotNull PsiMethod[] superMethods, @NotNull Set<PsiClassType> unhandledExceptions) {
    for (PsiMethod superMethod : superMethods) {
      PsiClassType[] referencedTypes = superMethod.getThrowsList().getReferencedTypes();

      Set<PsiClassType> exceptions = new HashSet<PsiClassType>(unhandledExceptions);
      for (PsiClassType referencedType : referencedTypes) {
        for (PsiClassType exception : unhandledExceptions) {
          if (referencedType.isAssignableFrom(exception)) exceptions.remove(exception);
        }
      }

      if (!exceptions.isEmpty()) return true;
    }

    return false;
  }
  public void findUsages(
      @NotNull final Processor<UsageInfo> consumer,
      @NotNull FindUsagesProcessPresentation processPresentation) {
    try {
      myProgress.setIndeterminate(true);
      myProgress.setText("Scanning indexed files...");
      final Set<PsiFile> filesForFastWordSearch =
          ApplicationManager.getApplication()
              .runReadAction(
                  new Computable<Set<PsiFile>>() {
                    @Override
                    public Set<PsiFile> compute() {
                      return getFilesForFastWordSearch();
                    }
                  });
      myProgress.setIndeterminate(false);

      searchInFiles(filesForFastWordSearch, processPresentation, consumer);

      myProgress.setIndeterminate(true);
      myProgress.setText("Scanning non-indexed files...");
      boolean skipIndexed = canRelyOnIndices();
      final Collection<PsiFile> otherFiles =
          collectFilesInScope(filesForFastWordSearch, skipIndexed);
      myProgress.setIndeterminate(false);

      long start = System.currentTimeMillis();
      searchInFiles(otherFiles, processPresentation, consumer);
      if (skipIndexed && otherFiles.size() > 1000) {
        logStats(otherFiles, start);
      }
    } catch (ProcessCanceledException e) {
      // fine
    }

    if (!myLargeFiles.isEmpty()) {
      processPresentation.setLargeFilesWereNotScanned(myLargeFiles);
    }

    if (!myProgress.isCanceled()) {
      myProgress.setText(FindBundle.message("find.progress.search.completed"));
    }
  }
 /**
  * Schedules action to be executed when all documents are committed.
  *
  * @return true if action has been run immediately, or false if action was scheduled for execution
  *     later.
  */
 @Override
 public boolean performWhenAllCommitted(@NotNull final Runnable action) {
   ApplicationManager.getApplication().assertIsDispatchThread();
   assert !myProject.isDisposed() : "Already disposed: " + myProject;
   if (myUncommittedDocuments.isEmpty()) {
     action.run();
     return true;
   }
   CompositeRunnable actions =
       (CompositeRunnable) actionsWhenAllDocumentsAreCommitted.get(PERFORM_ALWAYS_KEY);
   if (actions == null) {
     actions = new CompositeRunnable();
     actionsWhenAllDocumentsAreCommitted.put(PERFORM_ALWAYS_KEY, actions);
   }
   actions.add(action);
   myDocumentCommitProcessor.log(
       "PDI: added performWhenAllCommitted", null, false, action, myUncommittedDocuments);
   return false;
 }
  // returns false if canceled
  private boolean addInjectedPsiHighlights(
      @NotNull final Set<PsiFile> injectedFiles,
      @NotNull final ProgressIndicator progress,
      @NotNull final Collection<HighlightInfo> outInfos) {
    if (injectedFiles.isEmpty()) return true;
    final InjectedLanguageManager injectedLanguageManager =
        InjectedLanguageManager.getInstance(myProject);
    final TextAttributes injectedAttributes =
        myGlobalScheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);

    return JobLauncher.getInstance()
        .invokeConcurrentlyUnderProgress(
            new ArrayList<PsiFile>(injectedFiles),
            progress,
            isFailFastOnAcquireReadAction(),
            new Processor<PsiFile>() {
              @Override
              public boolean process(final PsiFile injectedPsi) {
                return addInjectedPsiHighlights(
                    injectedPsi, injectedAttributes, outInfos, progress, injectedLanguageManager);
              }
            });
  }
  @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());
    }
  }
  @NotNull
  private Set<PsiFile> getFilesForFastWordSearch() {
    String stringToFind = myFindModel.getStringToFind();
    if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) {
      return Collections.emptySet();
    }

    SearchScope customScope = myFindModel.getCustomScope();
    GlobalSearchScope scope =
        myPsiDirectory != null
            ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true)
            : myModule != null
                ? myModule.getModuleContentScope()
                : customScope instanceof GlobalSearchScope
                    ? (GlobalSearchScope) customScope
                    : toGlobal(customScope);
    if (scope == null) {
      scope = ProjectScope.getContentScope(myProject);
    }

    final Set<PsiFile> resultFiles = new LinkedHashSet<PsiFile>();

    if (TrigramIndex.ENABLED) {
      final Set<Integer> keys = ContainerUtil.newTroveSet();
      TrigramBuilder.processTrigrams(
          stringToFind,
          new TrigramBuilder.TrigramProcessor() {
            @Override
            public boolean execute(int value) {
              keys.add(value);
              return true;
            }
          });

      if (!keys.isEmpty()) {
        final List<VirtualFile> hits = new ArrayList<VirtualFile>();
        final GlobalSearchScope finalScope = scope;
        ApplicationManager.getApplication()
            .runReadAction(
                new Runnable() {
                  @Override
                  public void run() {
                    FileBasedIndex.getInstance()
                        .getFilesWithKey(
                            TrigramIndex.INDEX_ID,
                            keys,
                            new CommonProcessors.CollectProcessor<VirtualFile>(hits),
                            finalScope);
                  }
                });

        for (VirtualFile hit : hits) {
          if (myFileMask.value(hit)) {
            PsiFile file = findFile(hit);
            if (file != null) {
              resultFiles.add(file);
            }
          }
        }

        return resultFiles;
      }
    }

    PsiSearchHelperImpl helper =
        (PsiSearchHelperImpl) PsiSearchHelper.SERVICE.getInstance(myProject);
    helper.processFilesWithText(
        scope,
        UsageSearchContext.ANY,
        myFindModel.isCaseSensitive(),
        stringToFind,
        new Processor<VirtualFile>() {
          @Override
          public boolean process(VirtualFile file) {
            if (myFileMask.value(file)) {
              ContainerUtil.addIfNotNull(resultFiles, findFile(file));
            }
            return true;
          }
        });

    // in case our word splitting is incorrect
    CacheManager cacheManager = CacheManager.SERVICE.getInstance(myProject);
    PsiFile[] filesWithWord =
        cacheManager.getFilesWithWord(
            stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive());
    for (PsiFile file : filesWithWord) {
      if (myFileMask.value(file.getVirtualFile())) {
        resultFiles.add(file);
      }
    }

    return resultFiles;
  }
 @Override
 @NotNull
 public PsiElement[] getSecondaryElements() {
   PsiElement element = getPsiElement();
   if (ApplicationManager.getApplication().isUnitTestMode()) return PsiElement.EMPTY_ARRAY;
   if (element instanceof PsiField) {
     final PsiField field = (PsiField) element;
     PsiClass containingClass = field.getContainingClass();
     if (containingClass != null) {
       String fieldName = field.getName();
       final String propertyName =
           JavaCodeStyleManager.getInstance(getProject())
               .variableNameToPropertyName(fieldName, VariableKind.FIELD);
       Set<PsiMethod> accessors = new THashSet<PsiMethod>();
       boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
       PsiMethod getter =
           PropertyUtil.findPropertyGetterWithType(
               propertyName,
               isStatic,
               field.getType(),
               ContainerUtil.iterate(containingClass.getMethods()));
       if (getter != null) accessors.add(getter);
       PsiMethod setter =
           PropertyUtil.findPropertySetterWithType(
               propertyName,
               isStatic,
               field.getType(),
               ContainerUtil.iterate(containingClass.getMethods()));
       if (setter != null) accessors.add(setter);
       accessors.addAll(PropertyUtil.getAccessors(containingClass, fieldName));
       if (!accessors.isEmpty()) {
         final boolean doSearch;
         boolean containsPhysical =
             ContainerUtil.find(
                     accessors,
                     new Condition<PsiMethod>() {
                       @Override
                       public boolean value(PsiMethod psiMethod) {
                         return psiMethod.isPhysical();
                       }
                     })
                 != null;
         if (!containsPhysical) {
           doSearch = true;
         } else {
           doSearch =
               Messages.showOkCancelDialog(
                       FindBundle.message("find.field.accessors.prompt", fieldName),
                       FindBundle.message("find.field.accessors.title"),
                       CommonBundle.getYesButtonText(),
                       CommonBundle.getNoButtonText(),
                       Messages.getQuestionIcon())
                   == DialogWrapper.OK_EXIT_CODE;
         }
         if (doSearch) {
           final Set<PsiElement> elements = new THashSet<PsiElement>();
           for (PsiMethod accessor : accessors) {
             ContainerUtil.addAll(
                 elements, SuperMethodWarningUtil.checkSuperMethods(accessor, ACTION_STRING));
           }
           return PsiUtilBase.toPsiElementArray(elements);
         }
       }
     }
   }
   return super.getSecondaryElements();
 }
  public static void visitRefInDocTag(
      final PsiDocTag tag,
      final JavadocManager manager,
      final PsiElement context,
      final ArrayList<ProblemDescriptor> problems,
      final InspectionManager inspectionManager,
      final boolean onTheFly) {
    final String tagName = tag.getName();
    final PsiDocTagValue value = tag.getValueElement();
    if (value == null) return;
    final JavadocTagInfo info = manager.getTagInfo(tagName);
    if (info != null && !info.isValidInContext(context)) return;
    final String message = info == null || !info.isInline() ? null : info.checkTagValue(value);
    if (message != null) {
      problems.add(createDescriptor(value, message, inspectionManager, onTheFly));
    }

    final PsiReference reference = value.getReference();
    if (reference == null) return;
    final PsiElement element = reference.resolve();
    if (element != null) return;
    final int textOffset = value.getTextOffset();
    if (textOffset == value.getTextRange().getEndOffset()) return;
    final PsiDocTagValue valueElement = tag.getValueElement();
    if (valueElement == null) return;

    final CharSequence paramName =
        value
            .getContainingFile()
            .getViewProvider()
            .getContents()
            .subSequence(textOffset, value.getTextRange().getEndOffset());
    final String params = "<code>" + paramName + "</code>";
    final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
    if (onTheFly && "param".equals(tagName)) {
      final PsiDocCommentOwner commentOwner =
          PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class);
      if (commentOwner instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) commentOwner;
        final PsiParameter[] parameters = method.getParameterList().getParameters();
        final PsiDocTag[] tags = tag.getContainingComment().getTags();
        final Set<String> unboundParams = new HashSet<String>();
        for (PsiParameter parameter : parameters) {
          if (!JavaDocLocalInspection.isFound(tags, parameter)) {
            unboundParams.add(parameter.getName());
          }
        }
        if (!unboundParams.isEmpty()) {
          fixes.add(new RenameReferenceQuickFix(unboundParams));
        }
      }
    }
    fixes.add(new RemoveTagFix(tagName, paramName));

    problems.add(
        inspectionManager.createProblemDescriptor(
            valueElement,
            reference.getRangeInElement(),
            cannotResolveSymbolMessage(params),
            ProblemHighlightType.LIKE_UNKNOWN_SYMBOL,
            onTheFly,
            fixes.toArray(new LocalQuickFix[fixes.size()])));
  }
  // currently only one level here..
  public boolean contains(@NotNull String name, @NotNull final VirtualFile vFile) {
    final ProjectFileIndex projectFileIndex =
        ProjectRootManager.getInstance(myProject).getFileIndex();
    final Set<Boolean> find = new HashSet<Boolean>();
    final ContentIterator contentIterator =
        new ContentIterator() {
          public boolean processFile(VirtualFile fileOrDir) {
            if (fileOrDir != null && fileOrDir.getPath().equals(vFile.getPath())) {
              find.add(Boolean.TRUE);
            }
            return true;
          }
        };

    Collection<TreeItem<Pair<AbstractUrl, String>>> urls = getFavoritesListRootUrls(name);
    for (TreeItem<Pair<AbstractUrl, String>> pair : urls) {
      AbstractUrl abstractUrl = pair.getData().getFirst();
      if (abstractUrl == null) {
        continue;
      }
      final Object[] path = abstractUrl.createPath(myProject);
      if (path == null || path.length < 1 || path[0] == null) {
        continue;
      }
      Object element = path[path.length - 1];
      if (element instanceof SmartPsiElementPointer) {
        final VirtualFile virtualFile =
            PsiUtilBase.getVirtualFile(((SmartPsiElementPointer) element).getElement());
        if (virtualFile == null) continue;
        if (vFile.getPath().equals(virtualFile.getPath())) {
          return true;
        }
        if (!virtualFile.isDirectory()) {
          continue;
        }
        projectFileIndex.iterateContentUnderDirectory(virtualFile, contentIterator);
      }

      if (element instanceof PsiElement) {
        final VirtualFile virtualFile = PsiUtilBase.getVirtualFile((PsiElement) element);
        if (virtualFile == null) continue;
        if (vFile.getPath().equals(virtualFile.getPath())) {
          return true;
        }
        if (!virtualFile.isDirectory()) {
          continue;
        }
        projectFileIndex.iterateContentUnderDirectory(virtualFile, contentIterator);
      }
      if (element instanceof Module) {
        ModuleRootManager.getInstance((Module) element)
            .getFileIndex()
            .iterateContent(contentIterator);
      }
      if (element instanceof LibraryGroupElement) {
        final boolean inLibrary =
            ModuleRootManager.getInstance(((LibraryGroupElement) element).getModule())
                    .getFileIndex()
                    .isInContent(vFile)
                && projectFileIndex.isInLibraryClasses(vFile);
        if (inLibrary) {
          return true;
        }
      }
      if (element instanceof NamedLibraryElement) {
        NamedLibraryElement namedLibraryElement = (NamedLibraryElement) element;
        final VirtualFile[] files =
            namedLibraryElement.getOrderEntry().getRootFiles(OrderRootType.CLASSES);
        if (files != null && ArrayUtil.find(files, vFile) > -1) {
          return true;
        }
      }
      if (element instanceof ModuleGroup) {
        ModuleGroup group = (ModuleGroup) element;
        final Collection<Module> modules = group.modulesInGroup(myProject, true);
        for (Module module : modules) {
          ModuleRootManager.getInstance(module).getFileIndex().iterateContent(contentIterator);
        }
      }

      for (FavoriteNodeProvider provider :
          Extensions.getExtensions(FavoriteNodeProvider.EP_NAME, myProject)) {
        if (provider.elementContainsFile(element, vFile)) {
          return true;
        }
      }

      if (!find.isEmpty()) {
        return true;
      }
    }
    return false;
  }
  @Nullable
  public UsageInfo[] preprocessUsages(final Project project, final UsageInfo[] usages) {
    final ArrayList<UsageInfo> result = new ArrayList<>();
    final ArrayList<UsageInfo> overridingMethods = new ArrayList<>();
    final ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> delegatingParams = new ArrayList<>();
    final ArrayList<SafeDeleteMethodCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>();
    for (UsageInfo usage : usages) {
      if (usage.isNonCodeUsage) {
        result.add(usage);
      } else if (usage instanceof SafeDeleteMethodCalleeUsageInfo) {
        calleesSafeToDelete.add((SafeDeleteMethodCalleeUsageInfo) usage);
      } else if (usage instanceof SafeDeleteOverridingMethodUsageInfo) {
        overridingMethods.add(usage);
      } else if (usage instanceof SafeDeleteParameterCallHierarchyUsageInfo) {
        delegatingParams.add((SafeDeleteParameterCallHierarchyUsageInfo) usage);
      } else if (usage instanceof SafeDeleteAnnotation) {
        result.add(
            new SafeDeleteAnnotation(
                (PsiAnnotation) usage.getElement(),
                ((SafeDeleteAnnotation) usage).getReferencedElement(),
                true));
      } else {
        result.add(usage);
      }
    }

    if (!overridingMethods.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(overridingMethods);
      } else {
        OverridingMethodsDialog dialog = new OverridingMethodsDialog(project, overridingMethods);
        if (!dialog.showAndGet()) {
          return null;
        }
        final ArrayList<UsageInfo> selected = dialog.getSelected();
        final Set<UsageInfo> unselected = new HashSet<>(overridingMethods);
        unselected.removeAll(selected);

        if (!unselected.isEmpty()) {
          final List<PsiMethod> unselectedMethods =
              ContainerUtil.map(
                  unselected,
                  info -> ((SafeDeleteOverridingMethodUsageInfo) info).getOverridingMethod());

          for (Iterator<UsageInfo> iterator = result.iterator(); iterator.hasNext(); ) {
            final UsageInfo info = iterator.next();
            if (info instanceof SafeDeleteOverrideAnnotation
                && !allSuperMethodsSelectedToDelete(
                    unselectedMethods, ((SafeDeleteOverrideAnnotation) info).getMethod())) {
              iterator.remove();
            }
          }
        }

        result.addAll(selected);
      }
    }

    if (!delegatingParams.isEmpty()) {
      final SafeDeleteParameterCallHierarchyUsageInfo parameterHierarchyUsageInfo =
          delegatingParams.get(0);
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(delegatingParams);
      } else {
        final PsiMethod method = parameterHierarchyUsageInfo.getCalledMethod();
        final PsiParameter parameter = parameterHierarchyUsageInfo.getReferencedElement();
        final int parameterIndex = method.getParameterList().getParameterIndex(parameter);
        final JavaCallerChooser chooser =
            new SafeDeleteJavaCallerChooser(method, project, result) {
              @Override
              protected ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> getTopLevelItems() {
                return delegatingParams;
              }

              @Override
              protected int getParameterIdx() {
                return parameterIndex;
              }
            };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
      }
    }

    if (!calleesSafeToDelete.isEmpty()) {
      if (ApplicationManager.getApplication().isUnitTestMode()) {
        result.addAll(calleesSafeToDelete);
      } else {
        final PsiMethod method = calleesSafeToDelete.get(0).getCallerMethod();
        final ArrayList<UsageInfo> list = new ArrayList<>();
        JavaCallerChooser chooser =
            new SafeDeleteJavaCalleeChooser(method, project, list) {
              @Override
              protected ArrayList<SafeDeleteMethodCalleeUsageInfo> getTopLevelItems() {
                return calleesSafeToDelete;
              }
            };
        TreeUtil.expand(chooser.getTree(), 2);
        if (!chooser.showAndGet()) {
          return null;
        }
        result.addAll(list);
        final List<PsiElement> methodsToDelete = new ArrayList<>();
        for (UsageInfo info : list) {
          methodsToDelete.add(info.getElement());
        }
        methodsToDelete.add(method);
        final Condition<PsiElement> insideDeletedCondition =
            getUsageInsideDeletedFilter(
                methodsToDelete.toArray(new PsiElement[methodsToDelete.size()]));
        for (UsageInfo info : list) {
          SafeDeleteProcessor.addNonCodeUsages(
              info.getElement(),
              result,
              insideDeletedCondition,
              JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD,
              JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD);
        }
      }
    }

    return result.toArray(new UsageInfo[result.size()]);
  }
  private static Set<PsiMethod> validateOverridingMethods(
      PsiMethod originalMethod,
      final Collection<PsiReference> originalReferences,
      Collection<PsiMethod> overridingMethods,
      HashMap<PsiMethod, Collection<PsiReference>> methodToReferences,
      List<UsageInfo> usages,
      final PsiElement[] allElementsToDelete) {
    Set<PsiMethod> validOverriding = new LinkedHashSet<>(overridingMethods);
    Set<PsiMethod> multipleInterfaceImplementations = new HashSet<>();
    boolean anyNewBadRefs;
    do {
      anyNewBadRefs = false;
      for (PsiMethod overridingMethod : overridingMethods) {
        if (validOverriding.contains(overridingMethod)) {
          final Collection<PsiReference> overridingReferences =
              methodToReferences.get(overridingMethod);
          boolean anyOverridingRefs = false;
          for (final PsiReference overridingReference : overridingReferences) {
            final PsiElement element = overridingReference.getElement();
            if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) {
              anyOverridingRefs = true;
              break;
            }
          }
          if (!anyOverridingRefs
              && isMultipleInterfacesImplementation(
                  overridingMethod, originalMethod, allElementsToDelete)) {
            anyOverridingRefs = true;
            multipleInterfaceImplementations.add(overridingMethod);
          }

          if (anyOverridingRefs) {
            validOverriding.remove(overridingMethod);
            anyNewBadRefs = true;

            for (PsiReference reference : originalReferences) {
              final PsiElement element = reference.getElement();
              if (!isInside(element, allElementsToDelete)
                  && !isInside(element, overridingMethods)) {
                usages.add(
                    new SafeDeleteReferenceJavaDeleteUsageInfo(element, originalMethod, false));
                validOverriding.clear();
              }
            }
          }
        }
      }
    } while (anyNewBadRefs && !validOverriding.isEmpty());

    for (PsiMethod method : validOverriding) {
      if (method != originalMethod) {

        usages.add(new SafeDeleteOverridingMethodUsageInfo(method, originalMethod));
      }
    }

    for (PsiMethod method : overridingMethods) {
      if (!validOverriding.contains(method)
          && !multipleInterfaceImplementations.contains(method)
          && canBePrivate(
              method, methodToReferences.get(method), validOverriding, allElementsToDelete)) {
        usages.add(new SafeDeletePrivatizeMethod(method, originalMethod));
      } else {
        usages.add(new SafeDeleteOverrideAnnotation(method, originalMethod));
      }
    }
    return validOverriding;
  }
  private void processBatch(
      @NotNull final ProgressIndicator indicator, @NotNull Set<VirtualFile> files) {
    assert !myApplication.isDispatchThread();
    final int resolvedInPreviousBatch = this.resolvedInPreviousBatch;
    final int totalSize = files.size() + resolvedInPreviousBatch;
    final ConcurrentIntObjectMap<int[]> fileToForwardIds =
        ContainerUtil.createConcurrentIntObjectMap();
    final Set<VirtualFile> toProcess = Collections.synchronizedSet(files);
    indicator.setIndeterminate(false);
    ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable) indicator);
    long start = System.currentTimeMillis();
    Processor<VirtualFile> processor =
        file -> {
          double fraction = 1 - toProcess.size() * 1.0 / totalSize;
          indicator.setFraction(fraction);
          try {
            if (!file.isDirectory() && toResolve(file, myProject)) {
              int fileId = getAbsId(file);
              int i = totalSize - toProcess.size();
              indicator.setText(i + "/" + totalSize + ": Resolving " + file.getPresentableUrl());
              int[] forwardIds = processFile(file, fileId, indicator);
              if (forwardIds == null) {
                // queueUpdate(file);
                return false;
              }
              fileToForwardIds.put(fileId, forwardIds);
            }
            toProcess.remove(file);
            return true;
          } catch (RuntimeException e) {
            indicator.checkCanceled();
          }
          return true;
        };
    boolean success = true;
    try {
      success = processFilesConcurrently(files, indicator, processor);
    } finally {
      this.resolvedInPreviousBatch = toProcess.isEmpty() ? 0 : totalSize - toProcess.size();
      queue(toProcess, "re-added after fail. success=" + success);
      storeIds(fileToForwardIds);

      long end = System.currentTimeMillis();
      log(
          "Resolved batch of "
              + (totalSize - toProcess.size())
              + " from "
              + totalSize
              + " files in "
              + ((end - start) / 1000)
              + "sec. (Gap: "
              + storage.gap
              + ")");
      synchronized (filesToResolve) {
        upToDate = filesToResolve.isEmpty();
        log("upToDate = " + upToDate);
        if (upToDate) {
          for (Listener listener : myListeners) {
            listener.allFilesResolved();
          }
        }
      }
    }
  }
  @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;
  }
 @Override
 public boolean hasUncommitedDocuments() {
   return !myIsCommitInProgress && !myUncommittedDocuments.isEmpty();
 }
  // returns false if canceled
  private boolean addInjectedPsiHighlights(
      @NotNull final Set<PsiFile> injectedFiles,
      @NotNull final ProgressIndicator progress,
      @NotNull final Collection<HighlightInfo> outInfos) {
    if (injectedFiles.isEmpty()) return true;
    final InjectedLanguageManager injectedLanguageManager =
        InjectedLanguageManager.getInstance(myProject);
    final TextAttributes injectedAttributes =
        myGlobalScheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);

    return JobUtil.invokeConcurrentlyUnderProgress(
        new ArrayList<PsiFile>(injectedFiles),
        progress,
        myFailFastOnAcquireReadAction,
        new Processor<PsiFile>() {
          @Override
          public boolean process(final PsiFile injectedPsi) {
            DocumentWindow documentWindow =
                (DocumentWindow)
                    PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi);
            if (documentWindow == null) return true;
            Place places = InjectedLanguageUtil.getShreds(injectedPsi);
            for (PsiLanguageInjectionHost.Shred place : places) {
              TextRange textRange =
                  place.getRangeInsideHost().shiftRight(place.host.getTextRange().getStartOffset());
              if (textRange.isEmpty()) continue;
              String desc =
                  injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
              HighlightInfo info =
                  HighlightInfo.createHighlightInfo(
                      HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT,
                      textRange,
                      null,
                      desc,
                      injectedAttributes);
              info.fromInjection = true;
              outInfos.add(info);
            }

            HighlightInfoHolder holder = createInfoHolder(injectedPsi);
            runHighlightVisitorsForInjected(injectedPsi, holder, progress);
            for (int i = 0; i < holder.size(); i++) {
              HighlightInfo info = holder.get(i);
              final int startOffset = documentWindow.injectedToHost(info.startOffset);
              final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
              addPatchedInfos(
                  info,
                  injectedPsi,
                  documentWindow,
                  injectedLanguageManager,
                  fixedTextRange,
                  outInfos);
            }
            holder.clear();
            highlightInjectedSyntax(injectedPsi, holder);
            for (int i = 0; i < holder.size(); i++) {
              HighlightInfo info = holder.get(i);
              final int startOffset = info.startOffset;
              final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
              if (fixedTextRange == null) {
                info.fromInjection = true;
                outInfos.add(info);
              } else {
                HighlightInfo patched =
                    new HighlightInfo(
                        info.forcedTextAttributes,
                        info.forcedTextAttributesKey,
                        info.type,
                        fixedTextRange.getStartOffset(),
                        fixedTextRange.getEndOffset(),
                        info.description,
                        info.toolTip,
                        info.type.getSeverity(null),
                        info.isAfterEndOfLine,
                        null,
                        false);
                patched.fromInjection = true;
                outInfos.add(patched);
              }
            }

            if (!isDumbMode()) {
              List<HighlightInfo> todos = new ArrayList<HighlightInfo>();
              highlightTodos(
                  injectedPsi,
                  injectedPsi.getText(),
                  0,
                  injectedPsi.getTextLength(),
                  progress,
                  myPriorityRange,
                  todos,
                  todos);
              for (HighlightInfo info : todos) {
                addPatchedInfos(
                    info, injectedPsi, documentWindow, injectedLanguageManager, null, outInfos);
              }
            }
            return true;
          }
        });
  }