Rewrite to Kotlin: overridden properties markers tooltip and navigation
This commit is contained in:
@@ -16,32 +16,23 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.highlighter;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerProvider;
|
||||
import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper;
|
||||
import com.intellij.codeInsight.daemon.impl.LineMarkerNavigator;
|
||||
import com.intellij.codeInsight.daemon.impl.MarkerType;
|
||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
import com.intellij.ide.util.PsiClassListCellRenderer;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.asJava.LightClassUtil;
|
||||
@@ -49,17 +40,18 @@ import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.Modality;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.ProjectRootsUtil;
|
||||
import org.jetbrains.jet.plugin.highlighter.markers.MarkersPackage;
|
||||
import org.jetbrains.jet.plugin.highlighter.markers.ResolveWithParentsResult;
|
||||
import org.jetbrains.jet.plugin.highlighter.markers.SuperDeclarationMarkerNavigationHandler;
|
||||
import org.jetbrains.jet.plugin.highlighter.markers.SuperDeclarationMarkerTooltip;
|
||||
import org.jetbrains.jet.plugin.search.ideaExtensions.KotlinDefinitionsSearcher;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
public static final Icon OVERRIDING_MARK = AllIcons.Gutter.OverridingMethod;
|
||||
@@ -116,85 +108,19 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
assert element.getParent() instanceof JetProperty : "This tooltip provider should be placed only on identifies in properties";
|
||||
JetProperty property = (JetProperty) element.getParent();
|
||||
|
||||
PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiClass>(5);
|
||||
Processor<PsiMethod> consumer = new AdapterProcessor<PsiMethod, PsiClass>(
|
||||
new CommonProcessors.UniqueProcessor<PsiClass>(new PsiElementProcessorAdapter<PsiClass>(processor)),
|
||||
new Function<PsiMethod, PsiClass>() {
|
||||
@Override
|
||||
public PsiClass fun(PsiMethod method) {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
});
|
||||
|
||||
for (PsiMethod method : LightClassUtil.getLightClassPropertyMethods(property)) {
|
||||
if (!processor.isOverflow()) {
|
||||
OverridingMethodsSearch.search(method, true).forEach(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isImplemented = isImplemented(property);
|
||||
if (processor.isOverflow()) {
|
||||
return isImplemented ?
|
||||
JetBundle.message("property.is.implemented.too.many") :
|
||||
JetBundle.message("property.is.overridden.too.many");
|
||||
}
|
||||
|
||||
List<PsiClass> collectedClasses = Lists.newArrayList(processor.getCollection());
|
||||
if (collectedClasses.isEmpty()) return null;
|
||||
|
||||
Collections.sort(collectedClasses, new PsiClassListCellRenderer().getComparator());
|
||||
|
||||
String start = isImplemented ?
|
||||
JetBundle.message("property.is.implemented.header") :
|
||||
JetBundle.message("property.is.overridden.header");
|
||||
|
||||
@NonNls String pattern = " {0}";
|
||||
return GutterIconTooltipHelper.composeText(collectedClasses, start, pattern);
|
||||
return MarkersPackage.getOverriddenPropertyTooltip(property);
|
||||
}
|
||||
},
|
||||
|
||||
new LineMarkerNavigator() {
|
||||
@Override
|
||||
public void browse(@Nullable MouseEvent e, @Nullable final PsiElement element) {
|
||||
public void browse(@Nullable MouseEvent e, @Nullable PsiElement element) {
|
||||
if (element == null) return;
|
||||
|
||||
assert element.getParent() instanceof JetProperty : "This marker navigator should be placed only on identifies in properties";
|
||||
JetProperty property = (JetProperty) element.getParent();
|
||||
|
||||
if (DumbService.isDumb(element.getProject())) {
|
||||
DumbService.getInstance(element.getProject()).showDumbModeNotification("Navigation to overriding classes is not possible during index update");
|
||||
return;
|
||||
}
|
||||
|
||||
final LightClassUtil.PropertyAccessorsPsiMethods psiPropertyMethods =
|
||||
LightClassUtil.getLightClassPropertyMethods((JetProperty) element.getParent());
|
||||
|
||||
final CommonProcessors.CollectUniquesProcessor<PsiElement> elementProcessor = new CommonProcessors.CollectUniquesProcessor<PsiElement>();
|
||||
Runnable jetPsiMethodProcessor = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(psiPropertyMethods, GlobalSearchScope.allScope(element.getProject()), elementProcessor);
|
||||
}
|
||||
};
|
||||
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
jetPsiMethodProcessor,
|
||||
MarkerType.SEARCHING_FOR_OVERRIDING_METHODS, true,
|
||||
element.getProject(),
|
||||
e != null ? (JComponent) e.getComponent() : null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer();
|
||||
List<PsiElement> elements = Ordering.from(renderer.getComparator()).sortedCopy(elementProcessor.getResults());
|
||||
|
||||
NavigatablePsiElement[] navigatableElements = Iterables.toArray(
|
||||
Iterables.filter(elements, NavigatablePsiElement.class), NavigatablePsiElement.class);
|
||||
|
||||
PsiElementListNavigator.openTargets(e, navigatableElements,
|
||||
JetBundle.message("navigation.title.overriding.property", property.getName()),
|
||||
JetBundle.message("navigation.findUsages.title.overriding.property", property.getName()),
|
||||
renderer);
|
||||
MarkersPackage.navigateToPropertyOverriddenDeclarations(e, property);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -310,7 +236,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isImplemented(JetNamedDeclaration declaration) {
|
||||
public static boolean isImplemented(JetNamedDeclaration declaration) {
|
||||
if (declaration.hasModifier(JetTokens.ABSTRACT_KEYWORD)) return true;
|
||||
|
||||
PsiElement parent = declaration.getParent();
|
||||
@@ -344,7 +270,8 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
|
||||
anchor, anchor.getTextOffset(),
|
||||
isImplemented(property) ? IMPLEMENTED_MARK : OVERRIDDEN_MARK,
|
||||
Pass.UPDATE_OVERRIDEN_MARKERS,
|
||||
OVERRIDDEN_PROPERTY.getTooltip(), OVERRIDDEN_PROPERTY.getNavigationHandler(),
|
||||
OVERRIDDEN_PROPERTY.getTooltip(),
|
||||
OVERRIDDEN_PROPERTY.getNavigationHandler(),
|
||||
GutterIconRenderer.Alignment.RIGHT);
|
||||
|
||||
result.add(info);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.highlighter.markers
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import com.intellij.psi.search.PsiElementProcessor
|
||||
import com.intellij.psi.PsiClass
|
||||
import org.jetbrains.jet.plugin.JetBundle
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import org.jetbrains.jet.asJava.LightClassUtil
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.AdapterProcessor
|
||||
import com.intellij.util.CommonProcessors
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter
|
||||
import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper
|
||||
import com.intellij.psi.PsiElement
|
||||
import java.awt.event.MouseEvent
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import org.jetbrains.jet.plugin.search.ideaExtensions.KotlinDefinitionsSearcher
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.codeInsight.daemon.impl.MarkerType
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
||||
import com.intellij.ide.util.PsiClassListCellRenderer
|
||||
import javax.swing.JComponent
|
||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
|
||||
import com.intellij.psi.NavigatablePsiElement
|
||||
import com.intellij.util.Function
|
||||
import org.jetbrains.jet.plugin.highlighter.JetLineMarkerProvider
|
||||
|
||||
fun getOverriddenPropertyTooltip(property: JetProperty): String? {
|
||||
val overriddenInClassesProcessor = PsiElementProcessor.CollectElementsWithLimit<PsiClass>(5)
|
||||
|
||||
val consumer = AdapterProcessor<PsiMethod, PsiClass>(
|
||||
CommonProcessors.UniqueProcessor<PsiClass>(PsiElementProcessorAdapter(overriddenInClassesProcessor)),
|
||||
Function { (method: PsiMethod?): PsiClass? -> method?.getContainingClass() }
|
||||
)
|
||||
|
||||
for (method in LightClassUtil.getLightClassPropertyMethods(property)) {
|
||||
if (!overriddenInClassesProcessor.isOverflow()) {
|
||||
OverridingMethodsSearch.search(method, true).forEach(consumer)
|
||||
}
|
||||
}
|
||||
|
||||
val isImplemented = JetLineMarkerProvider.isImplemented(property)
|
||||
if (overriddenInClassesProcessor.isOverflow()) {
|
||||
return if (isImplemented)
|
||||
JetBundle.message("property.is.implemented.too.many")
|
||||
else
|
||||
JetBundle.message("property.is.overridden.too.many")
|
||||
}
|
||||
|
||||
val collectedClasses = overriddenInClassesProcessor.getCollection()
|
||||
if (collectedClasses.isEmpty()) return null
|
||||
|
||||
val start = if (isImplemented)
|
||||
JetBundle.message("property.is.implemented.header")
|
||||
else
|
||||
JetBundle.message("property.is.overridden.header")
|
||||
|
||||
val pattern = " {0}"
|
||||
return GutterIconTooltipHelper.composeText(collectedClasses.sortBy(PsiClassListCellRenderer().getComparator()), start, pattern)
|
||||
}
|
||||
|
||||
fun navigateToPropertyOverriddenDeclarations(e: MouseEvent?, property: JetProperty) {
|
||||
val project = property.getProject()
|
||||
|
||||
if (DumbService.isDumb(project)) {
|
||||
DumbService.getInstance(project)?.showDumbModeNotification("Navigation to overriding classes is not possible during index update")
|
||||
return
|
||||
}
|
||||
|
||||
val psiPropertyMethods = LightClassUtil.getLightClassPropertyMethods(property)
|
||||
|
||||
val elementProcessor = CommonProcessors.CollectUniquesProcessor<PsiElement>()
|
||||
val jetPsiMethodProcessor = Runnable {
|
||||
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(
|
||||
psiPropertyMethods,
|
||||
GlobalSearchScope.allScope(project),
|
||||
elementProcessor)
|
||||
}
|
||||
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
/* runnable */ jetPsiMethodProcessor,
|
||||
MarkerType.SEARCHING_FOR_OVERRIDING_METHODS,
|
||||
/* can be canceled */ true,
|
||||
project,
|
||||
e?.getComponent() as JComponent?)) {
|
||||
return
|
||||
}
|
||||
|
||||
val renderer = DefaultPsiElementCellRenderer()
|
||||
val navigatingOverrides = elementProcessor.getResults()
|
||||
.sortBy(renderer.getComparator())
|
||||
.filterIsInstance(javaClass<NavigatablePsiElement>())
|
||||
|
||||
PsiElementListNavigator.openTargets(e,
|
||||
navigatingOverrides.copyToArray(),
|
||||
JetBundle.message("navigation.title.overriding.property", property.getName()),
|
||||
JetBundle.message("navigation.findUsages.title.overriding.property", property.getName()), renderer)
|
||||
}
|
||||
Reference in New Issue
Block a user