public static boolean processImplementations(final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) { if (!FunctionalExpressionSearch.search(psiClass, scope).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { return processor.process(expression); } })) { return false; } final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces"); return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() { public boolean execute(@NotNull PsiClass element) { if (!showInterfaces && element.isInterface()) { return true; } return processor.process(element); } })); }
public static void collectInheritingClasses(@NotNull PsiClass aClass, @NotNull Collection<LineMarkerInfo> result, @NotNull Map<PsiClass, PsiClass> subClassCache) { if (aClass.hasModifierProperty(PsiModifier.FINAL)) { return; } if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object. PsiClass subClass = subClassCache.get(aClass); if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod; PsiElement range = aClass.getNameIdentifier(); if (range == null) { range = aClass; } MarkerType type = MarkerType.SUBCLASSED_CLASS; LineMarkerInfo info = new LineMarkerInfo<PsiElement>(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(), type.getNavigationHandler(), GutterIconRenderer.Alignment.RIGHT); NavigateAction.setNavigateAction(info, aClass.isInterface() ? "Go to implementation(s)" : "Go to subclass(es)", IdeActions.ACTION_GOTO_IMPLEMENTATION); result.add(info); } }
private static String getOverriddenMethodTooltip(@NotNull PsiMethod method) { PsiElementProcessor.CollectElementsWithLimit<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5); OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(processor)); boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); if (processor.isOverflow()){ return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); } PsiMethod[] overridings = processor.toArray(PsiMethod.EMPTY_ARRAY); if (overridings.length == 0) { final PsiClass aClass = method.getContainingClass(); if (aClass != null && FunctionalExpressionSearch.search(aClass).findFirst() != null) { return "Has functional implementations"; } return null; } Comparator<PsiMethod> comparator = new MethodCellRenderer(false).getComparator(); Arrays.sort(overridings, comparator); String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header"); @NonNls String pattern = " <a href=\"#javaClass/{1}\">{1}</a>"; return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); }
@NotNull protected final Object[] buildChildren(@NotNull final HierarchyNodeDescriptor descriptor) { final Object element = ((TypeHierarchyNodeDescriptor)descriptor).getPsiClass(); if (!(element instanceof PsiClass)) return ArrayUtil.EMPTY_OBJECT_ARRAY; final PsiClass psiClass = (PsiClass)element; if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { return new Object[]{IdeBundle.message("node.hierarchy.java.lang.object")}; } if (psiClass instanceof PsiAnonymousClass) return ArrayUtil.EMPTY_OBJECT_ARRAY; if (psiClass.hasModifierProperty(PsiModifier.FINAL)) return ArrayUtil.EMPTY_OBJECT_ARRAY; final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); final List<PsiClass> classes = new ArrayList<PsiClass>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); final List<HierarchyNodeDescriptor> descriptors = new ArrayList<HierarchyNodeDescriptor>(classes.size()); for (PsiClass aClass : classes) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); } FunctionalExpressionSearch.search(psiClass, searchScope).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, expression, false)); return true; } }); return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); }
@Override @NotNull protected UsageInfo[] findUsages() { final PsiClass[] inheritors = ClassInheritorsSearch.search(myClass, false).toArray(PsiClass.EMPTY_ARRAY); final List<UsageInfo> usages = new ArrayList<UsageInfo>(inheritors.length); for (PsiClass inheritor : inheritors) { usages.add(new UsageInfo(inheritor)); } final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myClass); if (interfaceMethod != null && isMoved(interfaceMethod)) { FunctionalExpressionSearch.search(myClass).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { usages.add(new UsageInfo(expression)); return true; } }); } return usages.toArray(new UsageInfo[usages.size()]); }
private static boolean findClassInheritors(final PsiClass element) { final Collection<PsiElement> inheritors = new ArrayList<PsiElement>(); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){ @Override public void run() { ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { final PsiClass inheritor = ClassInheritorsSearch.search(element).findFirst(); if (inheritor != null) { inheritors.add(inheritor); } else { final PsiFunctionalExpression functionalExpression = FunctionalExpressionSearch.search(element).findFirst(); if (functionalExpression != null) { inheritors.add(functionalExpression); } } } }); } }, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) return false; return inheritors.isEmpty(); }
private void findSimpleUsages(final PsiMethod method, final ArrayList<UsageInfo> result) { PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); findUsagesInCallers(result); final ArrayList<PsiMethod> methods = new ArrayList<PsiMethod>(Arrays.asList(overridingMethods)); methods.add(method); for (PsiMethod psiMethod : methods) { for (PsiFunctionalExpression functionalExpression : FunctionalExpressionSearch.search(psiMethod)) { result.add(new FunctionalInterfaceChangedUsageInfo(functionalExpression, psiMethod)); } } //Parameter name changes are not propagated findParametersUsage(method, result, overridingMethods); }
public static boolean processImplementations(final PsiMethod psiMethod, final Processor<PsiElement> consumer, final SearchScope searchScope) { if(!FunctionalExpressionSearch.search(psiMethod, searchScope).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { return consumer.process(expression); } })) { return false; } List<PsiMethod> methods = new ArrayList<PsiMethod>(); getOverridingMethods(psiMethod, methods, searchScope); return ContainerUtil.process(methods, consumer); }
public static boolean processImplementations(final PsiMethod psiMethod, final Processor<PsiElement> consumer, final SearchScope searchScope) { if (!FunctionalExpressionSearch.search(psiMethod, searchScope).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { return consumer.process(expression); } })) { return false; } List<PsiMethod> methods = new ArrayList<PsiMethod>(); getOverridingMethods(psiMethod, methods, searchScope); return ContainerUtil.process(methods, consumer); }
public static String getSubclassedClassTooltip(@NotNull PsiClass aClass) { PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(5, new THashSet<PsiClass>()); ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(processor)); if (processor.isOverflow()) { return aClass.isInterface() ? DaemonBundle.message("interface.is.implemented.too.many") : DaemonBundle.message("class.is.subclassed.too.many"); } PsiClass[] subclasses = processor.toArray(PsiClass.EMPTY_ARRAY); if (subclasses.length == 0) { final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> functionalImplementations = new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>()); FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(functionalImplementations)); if (!functionalImplementations.getCollection().isEmpty()) { return "Has functional implementations"; } return null; } Comparator<PsiClass> comparator = new PsiClassListCellRenderer().getComparator(); Arrays.sort(subclasses, comparator); String start = aClass.isInterface() ? DaemonBundle.message("interface.is.implemented.by.header") : DaemonBundle.message("class.is.subclassed.by.header"); @NonNls String pattern = " <a href=\"#javaClass/{0}\">{0}</a>"; return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); }
public static void navigateToSubclassedClass(MouseEvent e, @NotNull final PsiClass aClass) { if (DumbService.isDumb(aClass.getProject())) { DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); return; } final PsiElementProcessor.CollectElementsWithLimit<PsiClass> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(2, new THashSet<PsiClass>()); final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>()); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter<PsiClass>(collectProcessor)); if (collectProcessor.getCollection().size() < 2) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(collectExprProcessor)); } } }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { return; } final List<NavigatablePsiElement> inheritors = new ArrayList<NavigatablePsiElement>(); inheritors.addAll(collectProcessor.getCollection()); inheritors.addAll(collectExprProcessor.getCollection()); if (inheritors.isEmpty()) return; final PsiClassOrFunctionalExpressionListCellRenderer renderer = new PsiClassOrFunctionalExpressionListCellRenderer(); final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); Collections.sort(inheritors, renderer.getComparator()); PsiElementListNavigator.openTargets(e, inheritors.toArray(new NavigatablePsiElement[inheritors.size()]), subclassUpdater.getCaption(inheritors.size()), CodeInsightBundle.message("goto.implementation.findUsages.title", aClass.getName()), renderer, subclassUpdater); }
@Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); ClassInheritorsSearch.search(myClass, ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() { @Override public SearchScope compute() { return myClass.getUseScope(); } }), true).forEach(new CommonProcessors.CollectProcessor<PsiClass>() { @Override public boolean process(final PsiClass o) { if (!updateComponent(o, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(o); } }); FunctionalExpressionSearch.search(myClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() { @Override public boolean process(final PsiFunctionalExpression expr) { if (!updateComponent(expr, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(expr); } }); }
@Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); OverridingMethodsSearch.search(myMethod, true).forEach( new CommonProcessors.CollectProcessor<PsiMethod>() { @Override public boolean process(PsiMethod psiMethod) { if (!updateComponent(psiMethod, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(psiMethod); } }); final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() { @Override public PsiClass compute() { return myMethod.getContainingClass(); } }); FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() { @Override public boolean process(final PsiFunctionalExpression expr) { if (!updateComponent(expr, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(expr); } }); }
@NotNull @Override protected final Object[] buildChildren(@NotNull final HierarchyNodeDescriptor descriptor) { final PsiElement psiElement = ((MethodHierarchyNodeDescriptor)descriptor).getPsiClass(); if (!(psiElement instanceof PsiClass)) return ArrayUtil.EMPTY_OBJECT_ARRAY; final PsiClass psiClass = (PsiClass)psiElement; final Collection<PsiClass> subclasses = getSubclasses(psiClass); final List<HierarchyNodeDescriptor> descriptors = new ArrayList<HierarchyNodeDescriptor>(subclasses.size()); for (final PsiClass aClass : subclasses) { if (HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) { if (shouldHideClass(aClass)) { continue; } } final MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); descriptors.add(d); } final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor)descriptor).getMethod(psiClass, false); if (existingMethod != null) { FunctionalExpressionSearch.search(existingMethod).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); return true; } }); } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); }
private static void findFunctionalExpressions(final List<UsageInfo> usages, PsiMethod... methods) { for (PsiMethod method : methods) { final PsiClass containingClass = method.getContainingClass(); FunctionalExpressionSearch.search(method).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { usages.add(new SafeDeleteFunctionalExpressionUsageInfo(expression, containingClass)); return true; } }); } }
public void testMethodArgument() throws Exception { myFixture.configureByFile(getTestName(false) + ".java"); final PsiElement elementAtCaret = myFixture.getElementAtCaret(); assertNotNull(elementAtCaret); final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false); assertTrue(psiClass != null && psiClass.isInterface()); final Collection<PsiFunctionalExpression> expressions = FunctionalExpressionSearch.search(psiClass).findAll(); assertTrue(expressions.size() == 1); final PsiFunctionalExpression next = expressions.iterator().next(); assertNotNull(next); assertEquals("() -> {}", next.getText()); }
public void testMethodArgumentByTypeParameter() throws Exception { myFixture.configureByFile(getTestName(false) + ".java"); final PsiElement elementAtCaret = myFixture.getElementAtCaret(); assertNotNull(elementAtCaret); final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false); assertTrue(psiClass != null && psiClass.isInterface()); final Collection<PsiFunctionalExpression> expressions = FunctionalExpressionSearch.search(psiClass).findAll(); assertTrue(expressions.size() == 1); final PsiFunctionalExpression next = expressions.iterator().next(); assertNotNull(next); assertEquals("() -> {}", next.getText()); }
@NotNull @Override protected Object[] buildChildren(@NotNull final HierarchyNodeDescriptor descriptor) { final HaxeClass theHaxeClass = ((HaxeMethodHierarchyNodeDescriptor) descriptor).getHaxeClass(); if (null == theHaxeClass) return ArrayUtil.EMPTY_OBJECT_ARRAY; if (theHaxeClass instanceof HaxeAnonymousType) return ArrayUtil.EMPTY_OBJECT_ARRAY; if (theHaxeClass.hasModifierProperty(HaxePsiModifier.FINAL)) return ArrayUtil.EMPTY_OBJECT_ARRAY; final Collection<HaxeClass> subclasses = getSubclasses(theHaxeClass); final List<HierarchyNodeDescriptor> descriptors = new ArrayList<HierarchyNodeDescriptor>(subclasses.size()); for (final PsiClass aClass : subclasses) { if (HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) { if (shouldHideClass(aClass)) { continue; } } final HaxeMethodHierarchyNodeDescriptor d = new HaxeMethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); descriptors.add(d); } final PsiMethod existingMethod = ((HaxeMethodHierarchyNodeDescriptor)descriptor).getMethod(theHaxeClass, false); if (existingMethod != null) { FunctionalExpressionSearch.search(existingMethod).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { descriptors.add(new HaxeMethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, HaxeMethodHierarchyTreeStructure.this)); return true; } }); } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); }
public static boolean processImplementations(final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) { if(!FunctionalExpressionSearch.search(psiClass, scope).forEach(expression -> { return processor.process(expression); })) { return false; } return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new PsiElementProcessorAdapter<>((PsiElementProcessor<PsiClass>) element -> processor.process(element))); }
private static String getOverriddenMethodTooltip(@NotNull PsiMethod method) { PsiElementProcessor.CollectElementsWithLimit<PsiMethod> processor = new PsiElementProcessor.CollectElementsWithLimit<>(5); GlobalSearchScope scope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(method)); OverridingMethodsSearch.search(method, scope, true).forEach(new PsiElementProcessorAdapter<>(processor)); boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); if(processor.isOverflow()) { return DaemonBundle.message(isAbstract ? "method.is.implemented.too.many" : "method.is.overridden.too.many"); } PsiMethod[] overridings = processor.toArray(PsiMethod.EMPTY_ARRAY); if(overridings.length == 0) { final PsiClass aClass = method.getContainingClass(); if(aClass != null && FunctionalExpressionSearch.search(aClass).findFirst() != null) { return "Has functional implementations"; } return null; } Comparator<PsiMethod> comparator = new MethodCellRenderer(false).getComparator(); Arrays.sort(overridings, comparator); String start = DaemonBundle.message(isAbstract ? "method.is.implemented.header" : "method.is.overriden.header"); @NonNls String pattern = " <a href=\"#javaClass/{1}\">{1}</a>"; return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); }
public static String getSubclassedClassTooltip(@NotNull PsiClass aClass) { PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<>(5, new THashSet<>()); ClassInheritorsSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(processor)); if(processor.isOverflow()) { return DaemonBundle.message(aClass.isInterface() ? "interface.is.implemented.too.many" : "class.is.subclassed.too.many"); } PsiClass[] subclasses = processor.toArray(PsiClass.EMPTY_ARRAY); if(subclasses.length == 0) { final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> functionalImplementations = new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<>()); FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(functionalImplementations)); if(!functionalImplementations.getCollection().isEmpty()) { return "Has functional implementations"; } return null; } Comparator<PsiClass> comparator = PsiClassListCellRenderer.INSTANCE.getComparator(); Arrays.sort(subclasses, comparator); String start = DaemonBundle.message(aClass.isInterface() ? "interface.is.implemented.by.header" : "class.is.subclassed.by.header"); @NonNls String pattern = " <a href=\"#javaClass/{0}\">{0}</a>"; return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); }
public static void navigateToSubclassedClass(MouseEvent e, @NotNull final PsiClass aClass) { if(DumbService.isDumb(aClass.getProject())) { DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); return; } final PsiElementProcessor.FindElement<PsiClass> collectProcessor = new PsiElementProcessor.FindElement<>(); final PsiElementProcessor.FindElement<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.FindElement<>(); if(!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { ClassInheritorsSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectProcessor)); if(collectProcessor.getFoundElement() == null) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor)); } }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent) e.getComponent())) { return; } final List<NavigatablePsiElement> inheritors = new ArrayList<>(); ContainerUtil.addIfNotNull(inheritors, collectProcessor.getFoundElement()); ContainerUtil.addIfNotNull(inheritors, collectExprProcessor.getFoundElement()); if(inheritors.isEmpty()) { return; } final PsiClassOrFunctionalExpressionListCellRenderer renderer = new PsiClassOrFunctionalExpressionListCellRenderer(); final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); Collections.sort(inheritors, renderer.getComparator()); PsiElementListNavigator.openTargets(e, inheritors.toArray(new NavigatablePsiElement[inheritors.size()]), subclassUpdater.getCaption(inheritors.size()), CodeInsightBundle.message("goto" + ".implementation.findUsages.title", aClass.getName()), renderer, subclassUpdater); }
@Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); ClassInheritorsSearch.search(myClass, ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() { @Override public SearchScope compute() { return myClass.getUseScope(); } }), true).forEach(new CommonProcessors.CollectProcessor<PsiClass>() { @Override public boolean process(final PsiClass o) { if(!updateComponent(o, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(o); } }); FunctionalExpressionSearch.search(myClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() { @Override public boolean process(final PsiFunctionalExpression expr) { if(!updateComponent(expr, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(expr); } }); }
@Override public void run(@NotNull final ProgressIndicator indicator) { super.run(indicator); GlobalSearchScope scope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(myMethod)); OverridingMethodsSearch.search(myMethod, scope, true).forEach(new CommonProcessors.CollectProcessor<PsiMethod>() { @Override public boolean process(PsiMethod psiMethod) { if(!updateComponent(psiMethod, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(psiMethod); } }); PsiClass psiClass = ApplicationManager.getApplication().runReadAction((Computable<PsiClass>) myMethod::getContainingClass); FunctionalExpressionSearch.search(psiClass).forEach(new CommonProcessors.CollectProcessor<PsiFunctionalExpression>() { @Override public boolean process(final PsiFunctionalExpression expr) { if(!updateComponent(expr, myRenderer.getComparator())) { indicator.cancel(); } indicator.checkCanceled(); return super.process(expr); } }); }
@Override @NotNull protected final Object[] buildChildren(@NotNull final HierarchyNodeDescriptor descriptor) { final Object element = ((TypeHierarchyNodeDescriptor) descriptor).getPsiClass(); if(!(element instanceof PsiClass)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } final PsiClass psiClass = (PsiClass) element; if(CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) { return new Object[]{IdeBundle.message("node.hierarchy.java.lang.object")}; } if(psiClass instanceof PsiAnonymousClass) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } if(psiClass.hasModifierProperty(PsiModifier.FINAL)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } final SearchScope searchScope = psiClass.getUseScope().intersectWith(getSearchScope(myCurrentScopeType, psiClass)); final List<PsiClass> classes = new ArrayList<PsiClass>(ClassInheritorsSearch.search(psiClass, searchScope, false).findAll()); final List<HierarchyNodeDescriptor> descriptors = new ArrayList<HierarchyNodeDescriptor>(classes.size()); for(PsiClass aClass : classes) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, aClass, false)); } FunctionalExpressionSearch.search(psiClass, searchScope).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { descriptors.add(new TypeHierarchyNodeDescriptor(myProject, descriptor, expression, false)); return true; } }); return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); }
private static boolean findClassInheritors(final PsiClass element) { final Collection<PsiElement> inheritors = new ArrayList<PsiElement>(); if(!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { final PsiClass inheritor = ClassInheritorsSearch.search(element).findFirst(); if(inheritor != null) { inheritors.add(inheritor); } else { final PsiFunctionalExpression functionalExpression = FunctionalExpressionSearch.search(element).findFirst(); if(functionalExpression != null) { inheritors.add(functionalExpression); } } } }); } }, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) { return false; } return inheritors.isEmpty(); }
@Override public void processQuery(@NotNull FunctionalExpressionSearch.SearchParameters queryParameters, @NotNull Processor<PsiFunctionalExpression> consumer) { final GlobalSearchScope useScope; final PsiClass aClass; final Project project; final int expectedFunExprParamsCount; AccessToken token = ReadAction.start(); try { aClass = queryParameters.getElementToSearch(); if (!aClass.isValid() || !LambdaUtil.isFunctionalClass(aClass)) return; project = aClass.getProject(); final Set<Module> highLevelModules = getJava8Modules(project); if (highLevelModules.isEmpty()) return; useScope = convertToGlobalScope(project, queryParameters.getEffectiveSearchScope()); final MethodSignature functionalInterfaceMethod = LambdaUtil.getFunction(aClass); LOG.assertTrue(functionalInterfaceMethod != null); expectedFunExprParamsCount = functionalInterfaceMethod.getParameterTypes().length; } finally { token.finish(); } //collect all files with '::' and '->' in useScope Set<VirtualFile> candidateFiles = getFilesWithFunctionalExpressionsScope(project, new JavaSourceFilterScope(useScope)); if (candidateFiles.size() < SMART_SEARCH_THRESHOLD) { searchInFiles(aClass, consumer, candidateFiles, expectedFunExprParamsCount); return; } final GlobalSearchScope candidateScope = GlobalSearchScope.filesScope(project, candidateFiles); //collect all methods with parameter of functional interface or free type parameter type final Collection<PsiMethod> methodCandidates = getCandidateMethodsWithSuitableParams(aClass, project, useScope, candidateFiles, candidateScope); final LinkedHashSet<VirtualFile> filesToProcess = new LinkedHashSet<VirtualFile>(); final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance(); //find all usages of method candidates in files with functional expressions for (final PsiMethod psiMethod : methodCandidates) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { if (!psiMethod.isValid()) return; final int parametersCount = psiMethod.getParameterList().getParametersCount(); final boolean varArgs = psiMethod.isVarArgs(); final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); final GlobalSearchScope methodUseScope = convertToGlobalScope(project, psiMethod.getUseScope()); fileBasedIndex.processValues(JavaFunctionalExpressionIndex.JAVA_FUNCTIONAL_EXPRESSION_INDEX_ID, psiMethod.getName(), null, //functional expressions checker: number and type of parameters at call site should correspond to //candidate method currently check new SuitableFilesProcessor(filesToProcess, expectedFunExprParamsCount, parametersCount, varArgs, parameters), useScope.intersectWith(methodUseScope)); } }); } //search for functional expressions in non-call contexts collectFilesWithTypeOccurrencesAndFieldAssignments(aClass, candidateScope, filesToProcess); searchInFiles(aClass, consumer, filesToProcess, expectedFunExprParamsCount); }
private static void navigateToOverriddenMethod(MouseEvent e, @NotNull final PsiMethod method) { if (DumbService.isDumb(method.getProject())) { DumbService.getInstance(method.getProject()).showDumbModeNotification( "Navigation to overriding classes is not possible during index update"); return; } final PsiElementProcessor.CollectElementsWithLimit<PsiMethod> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(2, new THashSet<PsiMethod>()); final PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression>(2, new THashSet<PsiFunctionalExpression>()); final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter<PsiMethod>(collectProcessor)); if (isAbstract && collectProcessor.getCollection().size() < 2) { final PsiClass aClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() { @Override public PsiClass compute() { return method.getContainingClass(); } }); if (aClass != null) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(collectExprProcessor)); } } } }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { return; } final PsiMethod[] methodOverriders = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); final List<NavigatablePsiElement> overridings = new ArrayList<NavigatablePsiElement>(); overridings.addAll(collectProcessor.getCollection()); overridings.addAll(collectExprProcessor.getCollection()); if (overridings.isEmpty()) return; boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(methodOverriders); MethodOrFunctionalExpressionCellRenderer renderer = new MethodOrFunctionalExpressionCellRenderer(showMethodNames); Collections.sort(overridings, renderer.getComparator()); final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); PsiElementListNavigator.openTargets(e, overridings.toArray(new NavigatablePsiElement[overridings.size()]), methodsUpdater.getCaption(overridings.size()), "Overriding methods of " + method.getName(), renderer, methodsUpdater); }
@Override protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { final PsiClass anInterface = (PsiClass)element.getParent(); final SearchScope searchScope = anInterface.getUseScope(); final Query<PsiClass> query = ClassInheritorsSearch.search(anInterface, searchScope, false); final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); query.forEach(new Processor<PsiClass>() { @Override public boolean process(PsiClass aClass) { final PsiReferenceList extendsList = aClass.getExtendsList(); if (extendsList == null) { return true; } final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements(); if (referenceElements.length > 0) { final PsiElement target = referenceElements[0].resolve(); if (target != null) { conflicts.putValue(aClass, IntentionPowerPackBundle.message( "0.already.extends.1.and.will.not.compile.after.converting.2.to.a.class", RefactoringUIUtil.getDescription(aClass, true), RefactoringUIUtil.getDescription(target, true), RefactoringUIUtil.getDescription(anInterface, false))); } } return true; } }); final PsiFunctionalExpression functionalExpression = FunctionalExpressionSearch.search(anInterface, searchScope).findFirst(); if (functionalExpression != null) { final String conflictMessage = ClassPresentationUtil.getFunctionalExpressionPresentation(functionalExpression, true) + " will not compile after converting " + RefactoringUIUtil.getDescription(anInterface, false) + " to a class"; conflicts.putValue(functionalExpression, conflictMessage); } final boolean conflictsDialogOK; if (conflicts.isEmpty()) { conflictsDialogOK = true; } else { if (getApplication().isUnitTestMode()) { throw new BaseRefactoringProcessor.ConflictsInTestsException(conflicts.values()); } final ConflictsDialog conflictsDialog = new ConflictsDialog(anInterface.getProject(), conflicts, new Runnable() { @Override public void run() { final AccessToken token = start(); try { convertInterfaceToClass(anInterface); } finally { token.finish(); } } }); conflictsDialogOK = conflictsDialog.showAndGet(); } if (conflictsDialogOK) { convertInterfaceToClass(anInterface); } }
protected List<LineMarkerInfo> collectInheritingClasses(@NotNull PsiClass aClass) { if(aClass.hasModifierProperty(PsiModifier.FINAL)) { return Collections.emptyList(); } if(CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { return Collections.emptyList(); // It's useless to have overridden markers for object. } PsiClass subClass = DirectClassInheritorsSearch.search(aClass).findFirst(); if(subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { final Icon icon; if(aClass.isInterface()) { if(!myImplementedOption.isEnabled()) { return Collections.emptyList(); } icon = AllIcons.Gutter.ImplementedMethod; } else { if(!myOverriddenOption.isEnabled()) { return Collections.emptyList(); } icon = AllIcons.Gutter.OverridenMethod; } PsiElement range = aClass.getNameIdentifier(); if(range == null) { range = aClass; } MarkerType type = MarkerType.SUBCLASSED_CLASS; LineMarkerInfo info = new LineMarkerInfo<>(range, range.getTextRange(), icon, Pass.LINE_MARKERS, type.getTooltip(), type.getNavigationHandler(), GutterIconRenderer.Alignment.RIGHT); NavigateAction.setNavigateAction(info, aClass.isInterface() ? "Go to implementation(s)" : "Go to subclass(es)", IdeActions.ACTION_GOTO_IMPLEMENTATION); return Collections.singletonList(info); } return Collections.emptyList(); }
private List<LineMarkerInfo> collectOverridingMethods(@NotNull final Iterable<PsiMethod> _methods, @NotNull PsiClass containingClass) { if(!myOverriddenOption.isEnabled() && !myImplementedOption.isEnabled()) { return Collections.emptyList(); } final Set<PsiMethod> overridden = new HashSet<>(); Set<PsiMethod> methodSet = ContainerUtil.newHashSet(_methods); AllOverridingMethodsSearch.search(containingClass).forEach(pair -> { ProgressManager.checkCanceled(); final PsiMethod superMethod = pair.getFirst(); if(methodSet.remove(superMethod)) { overridden.add(superMethod); } return !methodSet.isEmpty(); }); if(!methodSet.isEmpty()) { final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(containingClass); if(interfaceMethod != null && FunctionalExpressionSearch.search(containingClass).findFirst() != null) { overridden.add(interfaceMethod); } } List<LineMarkerInfo> result = new ArrayList<>(); for(PsiMethod method : overridden) { ProgressManager.checkCanceled(); boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT); if(overrides) { if(!myOverriddenOption.isEnabled()) { return Collections.emptyList(); } } else { if(!myImplementedOption.isEnabled()) { return Collections.emptyList(); } } PsiElement range = getMethodRange(method); final MarkerType type = MarkerType.OVERRIDDEN_METHOD; final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; LineMarkerInfo<PsiElement> info = new LineMarkerInfo<>(range, range.getTextRange(), icon, Pass.LINE_MARKERS, type.getTooltip(), type.getNavigationHandler(), GutterIconRenderer.Alignment .RIGHT); NavigateAction.setNavigateAction(info, overrides ? "Go to overriding methods" : "Go to implementation(s)", IdeActions.ACTION_GOTO_IMPLEMENTATION); result.add(info); } return result; }
private static void navigateToOverriddenMethod(MouseEvent e, @NotNull final PsiMethod method) { if(DumbService.isDumb(method.getProject())) { DumbService.getInstance(method.getProject()).showDumbModeNotification("Navigation to overriding classes is not possible during index update"); return; } PsiElementProcessor.CollectElementsWithLimit<PsiMethod> collectProcessor = new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<>()); PsiElementProcessor.CollectElementsWithLimit<PsiFunctionalExpression> collectExprProcessor = new PsiElementProcessor.CollectElementsWithLimit<>(2, new THashSet<>()); final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); if(!ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { GlobalSearchScope scope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(method)); OverridingMethodsSearch.search(method, scope, true).forEach(new PsiElementProcessorAdapter<>(collectProcessor)); if(isAbstract && collectProcessor.getCollection().size() < 2) { final PsiClass aClass = ReadAction.compute(method::getContainingClass); if(aClass != null) { FunctionalExpressionSearch.search(aClass).forEach(new PsiElementProcessorAdapter<>(collectExprProcessor)); } } }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent) e.getComponent())) { return; } final PsiMethod[] methodOverriders = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); final List<NavigatablePsiElement> overridings = new ArrayList<>(); overridings.addAll(collectProcessor.getCollection()); overridings.addAll(collectExprProcessor.getCollection()); if(overridings.isEmpty()) { return; } boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(methodOverriders); MethodOrFunctionalExpressionCellRenderer renderer = new MethodOrFunctionalExpressionCellRenderer(showMethodNames); Collections.sort(overridings, renderer.getComparator()); final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); PsiElementListNavigator.openTargets(e, overridings.toArray(new NavigatablePsiElement[overridings.size()]), methodsUpdater.getCaption(overridings.size()), "Overriding methods of " + method .getName(), renderer, methodsUpdater); }
@NotNull @Override protected final Object[] buildChildren(@NotNull final HierarchyNodeDescriptor descriptor) { final PsiElement psiElement = ((MethodHierarchyNodeDescriptor) descriptor).getPsiClass(); if(!(psiElement instanceof PsiClass)) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } final PsiClass psiClass = (PsiClass) psiElement; final Collection<PsiClass> subclasses = getSubclasses(psiClass); final List<HierarchyNodeDescriptor> descriptors = new ArrayList<HierarchyNodeDescriptor>(subclasses.size()); for(final PsiClass aClass : subclasses) { if(HierarchyBrowserManager.getInstance(myProject).getState().HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED) { if(shouldHideClass(aClass)) { continue; } } final MethodHierarchyNodeDescriptor d = new MethodHierarchyNodeDescriptor(myProject, descriptor, aClass, false, this); descriptors.add(d); } final PsiMethod existingMethod = ((MethodHierarchyNodeDescriptor) descriptor).getMethod(psiClass, false); if(existingMethod != null) { FunctionalExpressionSearch.search(existingMethod).forEach(new Processor<PsiFunctionalExpression>() { @Override public boolean process(PsiFunctionalExpression expression) { descriptors.add(new MethodHierarchyNodeDescriptor(myProject, descriptor, expression, false, MethodHierarchyTreeStructure.this)); return true; } }); } return descriptors.toArray(new HierarchyNodeDescriptor[descriptors.size()]); }