diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 63d44934ab2..fefdb5730f5 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -91,6 +91,8 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 6079753e73c..14ae9e857cf 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -34,6 +34,10 @@ specify.type.explicitly.add.return.type.action.name=Specify Return Type Explicit specify.type.explicitly.add.action.name=Specify Type Explicitly specify.type.explicitly.remove.action.name=Remove Explicitly Specified Type +goto.super.function.chooser.title=Choose super function +goto.super.property.chooser.title=Choose super property +goto.super.class.chooser.title=Choose super class or interface + livetemplate.description.main=main() function livetemplate.description.soutp=Prints function parameter names and values to System.out livetemplate.description.iter=Iterate over elements of iterable diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/GotoSuperActionHandler.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/GotoSuperActionHandler.java new file mode 100644 index 00000000000..b6e1d69ad01 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/GotoSuperActionHandler.java @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2012 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.codeInsight; + +import com.intellij.codeInsight.CodeInsightActionHandler; +import com.intellij.codeInsight.navigation.NavigationUtil; +import com.intellij.codeInsight.navigation.actions.GotoSuperAction; +import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.ide.util.EditSourceUtil; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.pom.Navigatable; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; + +import java.util.Collection; +import java.util.List; + +/** + * @author Evgeny Gerashchenko + * @since 06.05.12 + */ +public class GotoSuperActionHandler implements CodeInsightActionHandler { + @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()); + if (element == null) return; + @SuppressWarnings("unchecked") JetNamedDeclaration funOrClass = + PsiTreeUtil.getParentOfType(element, JetNamedFunction.class, JetClass.class, JetProperty.class); + if (funOrClass == null) return; + + final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) file).getBindingContext(); + + final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, funOrClass); + + + Collection superDescriptors; + String message; + if (descriptor instanceof ClassDescriptor) { + Collection supertypes = ((ClassDescriptor) descriptor).getTypeConstructor().getSupertypes(); + List superclasses = ContainerUtil.mapNotNull(supertypes, new Function() { + @Override + public ClassDescriptor fun(JetType type) { + ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); + if (descriptor instanceof ClassDescriptor) { + return (ClassDescriptor) descriptor; + } + return null; + } + }); + ContainerUtil.removeDuplicates(superclasses); + superDescriptors = superclasses; + message = JetBundle.message("goto.super.class.chooser.title"); + } + else if (descriptor instanceof CallableMemberDescriptor) { + superDescriptors = ((CallableMemberDescriptor) descriptor).getOverriddenDescriptors(); + if (descriptor instanceof PropertyDescriptor) { + message = JetBundle.message("goto.super.property.chooser.title"); + } + else if (descriptor instanceof SimpleFunctionDescriptor) { + message = JetBundle.message("goto.super.function.chooser.title"); + } + else + throw new IllegalStateException("Unknown member type: " + descriptor.getClass().getName()); + } + else + return; + + List superDeclarations = ContainerUtil.mapNotNull(superDescriptors, new Function() { + @Override + public PsiElement fun(DeclarationDescriptor descriptor) { + if (JetStandardClasses.getAny() == descriptor) { + return null; + } + return BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); + } + }); + if (superDeclarations.isEmpty()) return; + if (superDeclarations.size() == 1) { + Navigatable navigatable = EditSourceUtil.getDescriptor(superDeclarations.get(0)); + if (navigatable != null && navigatable.canNavigate()) { + navigatable.navigate(true); + } + } + else { + PsiElement[] superDeclarationsArray = PsiUtilCore.toPsiElementArray(superDeclarations); + JBPopup popup = descriptor instanceof ClassDescriptor + ? NavigationUtil.getPsiElementPopup(superDeclarationsArray, message) + : NavigationUtil.getPsiElementPopup(superDeclarationsArray, + new JetFunctionPsiElementCellRenderer(bindingContext), message); + popup.showInBestPositionFor(editor); + } + } + + @Override + public boolean startInWriteAction() { + return false; + } +}