GotoSuperActionHandler: convert to .kt
This commit is contained in:
@@ -1,144 +1,98 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
*
|
* that can be found in the license/LICENSE.txt file.
|
||||||
* 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.kotlin.idea.codeInsight;
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
import com.intellij.codeInsight.CodeInsightActionHandler;
|
import com.intellij.codeInsight.CodeInsightActionHandler
|
||||||
import com.intellij.codeInsight.navigation.NavigationUtil;
|
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||||
import com.intellij.codeInsight.navigation.actions.GotoSuperAction;
|
import com.intellij.codeInsight.navigation.actions.GotoSuperAction
|
||||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
import com.intellij.featureStatistics.FeatureUsageTracker
|
||||||
import com.intellij.ide.util.EditSourceUtil;
|
import com.intellij.ide.util.EditSourceUtil
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.popup.JBPopup;
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.pom.Navigatable;
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.util.PsiUtilCore
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import com.intellij.psi.util.PsiUtilCore;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny
|
||||||
import com.intellij.util.Function;
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.idea.core.DescriptorUtilsKt;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
class GotoSuperActionHandler : CodeInsightActionHandler {
|
||||||
import java.util.List;
|
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||||
|
FeatureUsageTracker.getInstance().triggerFeatureUsed(GotoSuperAction.FEATURE_ID)
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny;
|
val element = file.findElementAt(editor.caretModel.offset) ?: return
|
||||||
|
val declaration =
|
||||||
|
PsiTreeUtil.getParentOfType<KtDeclaration>(
|
||||||
|
element,
|
||||||
|
KtNamedFunction::class.java,
|
||||||
|
KtClass::class.java,
|
||||||
|
KtProperty::class.java,
|
||||||
|
KtObjectDeclaration::class.java
|
||||||
|
) ?: return
|
||||||
|
|
||||||
public class GotoSuperActionHandler implements CodeInsightActionHandler {
|
val descriptor = declaration.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL)
|
||||||
@Override
|
|
||||||
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
|
||||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(GotoSuperAction.FEATURE_ID);
|
|
||||||
|
|
||||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
val superDeclarations = findSuperDeclarations(descriptor)
|
||||||
if (element == null) return;
|
|
||||||
@SuppressWarnings("unchecked") KtDeclaration declaration =
|
|
||||||
PsiTreeUtil.getParentOfType(element,
|
|
||||||
KtNamedFunction.class,
|
|
||||||
KtClass.class,
|
|
||||||
KtProperty.class,
|
|
||||||
KtObjectDeclaration.class);
|
|
||||||
if (declaration == null) return;
|
|
||||||
|
|
||||||
DeclarationDescriptor descriptor = ResolutionUtils.unsafeResolveToDescriptor(declaration, BodyResolveMode.PARTIAL);
|
if (superDeclarations == null || superDeclarations.isEmpty()) return
|
||||||
|
if (superDeclarations.size == 1) {
|
||||||
List<PsiElement> superDeclarations = findSuperDeclarations(descriptor);
|
val navigatable = EditSourceUtil.getDescriptor(superDeclarations[0])
|
||||||
|
|
||||||
if (superDeclarations == null || superDeclarations.isEmpty()) return;
|
|
||||||
if (superDeclarations.size() == 1) {
|
|
||||||
Navigatable navigatable = EditSourceUtil.getDescriptor(superDeclarations.get(0));
|
|
||||||
if (navigatable != null && navigatable.canNavigate()) {
|
if (navigatable != null && navigatable.canNavigate()) {
|
||||||
navigatable.navigate(true);
|
navigatable.navigate(true)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
val message = getTitle(descriptor)
|
||||||
String message = getTitle(descriptor);
|
val superDeclarationsArray = PsiUtilCore.toPsiElementArray(superDeclarations)
|
||||||
PsiElement[] superDeclarationsArray = PsiUtilCore.toPsiElementArray(superDeclarations);
|
val popup = if (descriptor is ClassDescriptor)
|
||||||
JBPopup popup = descriptor instanceof ClassDescriptor
|
NavigationUtil.getPsiElementPopup(superDeclarationsArray, message)
|
||||||
? NavigationUtil.getPsiElementPopup(superDeclarationsArray, message)
|
else
|
||||||
: NavigationUtil.getPsiElementPopup(superDeclarationsArray,
|
NavigationUtil.getPsiElementPopup(
|
||||||
new KtFunctionPsiElementCellRenderer(), message);
|
superDeclarationsArray,
|
||||||
popup.showInBestPositionFor(editor);
|
KtFunctionPsiElementCellRenderer(), message
|
||||||
|
)
|
||||||
|
popup.showInBestPositionFor(editor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private fun getTitle(descriptor: DeclarationDescriptor): String? =
|
||||||
private static String getTitle(DeclarationDescriptor descriptor) {
|
when(descriptor) {
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
is ClassDescriptor -> KotlinBundle.message("goto.super.class.chooser.title")
|
||||||
return KotlinBundle.message("goto.super.class.chooser.title");
|
is PropertyDescriptor -> KotlinBundle.message("goto.super.property.chooser.title")
|
||||||
|
is SimpleFunctionDescriptor -> KotlinBundle.message("goto.super.function.chooser.title")
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
private fun findSuperDeclarations(descriptor: DeclarationDescriptor): List<PsiElement>? {
|
||||||
return KotlinBundle.message("goto.super.property.chooser.title");
|
val superDescriptors: Collection<DeclarationDescriptor> = when (descriptor) {
|
||||||
}
|
is ClassDescriptor -> {
|
||||||
|
val supertypes = descriptor.typeConstructor.supertypes
|
||||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
val superclasses = supertypes.mapNotNull { type ->
|
||||||
return KotlinBundle.message("goto.super.function.chooser.title");
|
type.constructor.declarationDescriptor as? ClassDescriptor
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static List<PsiElement> findSuperDeclarations(DeclarationDescriptor descriptor) {
|
|
||||||
Collection<? extends DeclarationDescriptor> superDescriptors;
|
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
|
||||||
Collection<KotlinType> supertypes = ((ClassDescriptor) descriptor).getTypeConstructor().getSupertypes();
|
|
||||||
List<ClassDescriptor> superclasses = ContainerUtil.mapNotNull(supertypes, new Function<KotlinType, ClassDescriptor>() {
|
|
||||||
@Override
|
|
||||||
public ClassDescriptor fun(KotlinType type) {
|
|
||||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
|
||||||
return (ClassDescriptor) descriptor;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
ContainerUtil.removeDuplicates(superclasses)
|
||||||
ContainerUtil.removeDuplicates(superclasses);
|
superclasses
|
||||||
superDescriptors = superclasses;
|
|
||||||
}
|
|
||||||
else if (descriptor instanceof CallableMemberDescriptor) {
|
|
||||||
superDescriptors = DescriptorUtilsKt.getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ContainerUtil.mapNotNull(superDescriptors, new Function<DeclarationDescriptor, PsiElement>() {
|
|
||||||
@Override
|
|
||||||
public PsiElement fun(DeclarationDescriptor descriptor) {
|
|
||||||
if (descriptor instanceof ClassDescriptor && isAny((ClassDescriptor) descriptor)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
|
|
||||||
}
|
}
|
||||||
});
|
is CallableMemberDescriptor -> descriptor.getDirectlyOverriddenDeclarations()
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return superDescriptors.mapNotNull { descriptor ->
|
||||||
|
if (descriptor is ClassDescriptor && isAny(descriptor)) {
|
||||||
|
null
|
||||||
|
} else
|
||||||
|
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun startInWriteAction() = false
|
||||||
public boolean startInWriteAction() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user