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()); }
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(); } }
@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; } }); }