From 47d44545905bdaed1e791438566fac0fcf805c30 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 18 Aug 2016 18:55:00 +0300 Subject: [PATCH] Type Hierarchy: Support Type Hierarchy on references inside of super type call entries #KT-9125 Fixed --- ChangeLog.md | 6 ++ idea/src/META-INF/plugin.xml | 2 + ...peHierarchyProviderBySuperTypeCallEntry.kt | 55 +++++++++++++++++++ .../type/CaretAtSuperTypeCallEntry/1_A.java | 5 ++ .../type/CaretAtSuperTypeCallEntry/2_B.kt | 3 + ...CaretAtSuperTypeCallEntry_verification.xml | 7 +++ .../quickDoc/QuickDocInHierarchyTest.kt | 5 +- .../idea/hierarchy/AbstractHierarchyTest.java | 29 +++++----- .../hierarchy/HierarchyTestGenerated.java | 6 ++ 9 files changed, 101 insertions(+), 17 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/hierarchy/KotlinTypeHierarchyProviderBySuperTypeCallEntry.kt create mode 100644 idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/1_A.java create mode 100644 idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/2_B.kt create mode 100644 idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/CaretAtSuperTypeCallEntry_verification.xml diff --git a/ChangeLog.md b/ChangeLog.md index ad44f205ba0..10c4a8ecbc2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -91,6 +91,12 @@ These artifacts include extensions for the types available in the latter JDKs, s + [`KT-12389`](https://youtrack.jetbrains.com/issue/KT-12389) Do not exit from REPL when toString() of user class throws an exception + [`KT-12129`](https://youtrack.jetbrains.com/issue/KT-12129) Fixed link on api reference page in KDoc +## 1.0.5 + +### IDE + +- [`KT-9125`](https://youtrack.jetbrains.com/issue/KT-9125) Support Type Hierarchy on references inside of super type call entries + ## 1.0.4 ### Compiler diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index a59d2bfc8fa..d95b99f4f54 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -585,7 +585,9 @@ + + diff --git a/idea/src/org/jetbrains/kotlin/idea/hierarchy/KotlinTypeHierarchyProviderBySuperTypeCallEntry.kt b/idea/src/org/jetbrains/kotlin/idea/hierarchy/KotlinTypeHierarchyProviderBySuperTypeCallEntry.kt new file mode 100644 index 00000000000..223885b8bc0 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/hierarchy/KotlinTypeHierarchyProviderBySuperTypeCallEntry.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2016 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.kotlin.idea.hierarchy + +import com.intellij.ide.hierarchy.type.JavaTypeHierarchyProvider +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtConstructor +import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry +import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch + +class KotlinTypeHierarchyProviderBySuperTypeCallEntry : JavaTypeHierarchyProvider() { + override fun getTarget(dataContext: DataContext): PsiElement? { + val project = PlatformDataKeys.PROJECT.getData(dataContext) ?: return null + val editor = PlatformDataKeys.EDITOR.getData(dataContext) ?: return null + + val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return null + + val offset = editor.caretModel.offset + val elementAtCaret = file.findElementAt(offset) ?: return null + if (elementAtCaret.getParentOfTypeAndBranch { calleeExpression } == null) return null + + val targetElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext)?.unwrapped + return when { + targetElement is KtConstructor<*> -> targetElement.containingClassOrObject?.toLightClass() + targetElement is PsiMethod && targetElement.isConstructor -> targetElement.containingClass + targetElement is KtClassOrObject -> targetElement.toLightClass() + targetElement is PsiClass -> targetElement + else -> null + } + } +} diff --git a/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/1_A.java b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/1_A.java new file mode 100644 index 00000000000..3d06eb018fb --- /dev/null +++ b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/1_A.java @@ -0,0 +1,5 @@ +class A { + A(int i) { + + } +} \ No newline at end of file diff --git a/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/2_B.kt b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/2_B.kt new file mode 100644 index 00000000000..5614d1a38fa --- /dev/null +++ b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/2_B.kt @@ -0,0 +1,3 @@ +open class B : A(1) + +class C : B() \ No newline at end of file diff --git a/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/CaretAtSuperTypeCallEntry_verification.xml b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/CaretAtSuperTypeCallEntry_verification.xml new file mode 100644 index 00000000000..20f98b5e9f7 --- /dev/null +++ b/idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/CaretAtSuperTypeCallEntry_verification.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt index 983e9c03b33..c6926fa038e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocInHierarchyTest.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.editor.quickDoc import com.intellij.codeInsight.CodeInsightTestCase import com.intellij.ide.hierarchy.HierarchyBrowserBaseEx import com.intellij.ide.hierarchy.LanguageTypeHierarchy +import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase import com.intellij.ide.hierarchy.type.TypeHierarchyNodeDescriptor import com.intellij.ide.hierarchy.type.TypeHierarchyTreeStructure import com.intellij.openapi.actionSystem.CommonDataKeys @@ -30,6 +31,7 @@ import com.intellij.testFramework.MapDataContext import junit.framework.TestCase import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinQuickDocumentationProvider +import org.jetbrains.kotlin.idea.hierarchy.KotlinTypeHierarchyProvider import org.jetbrains.kotlin.idea.test.PluginTestCaseBase class QuickDocInHierarchyTest() : CodeInsightTestCase() { @@ -44,9 +46,10 @@ class QuickDocInHierarchyTest() : CodeInsightTestCase() { context.put(CommonDataKeys.PROJECT, project) context.put(CommonDataKeys.EDITOR, editor) + val provider = BrowseHierarchyActionBase.findProvider(LanguageTypeHierarchy.INSTANCE, file, file, context)!! val hierarchyTreeStructure = TypeHierarchyTreeStructure( project, - LanguageTypeHierarchy.INSTANCE.forLanguage(KotlinLanguage.INSTANCE).getTarget(context) as PsiClass?, + provider.getTarget(context) as PsiClass?, HierarchyBrowserBaseEx.SCOPE_PROJECT ) val hierarchyNodeDescriptor = hierarchyTreeStructure.baseDescriptor as TypeHierarchyNodeDescriptor diff --git a/idea/tests/org/jetbrains/kotlin/idea/hierarchy/AbstractHierarchyTest.java b/idea/tests/org/jetbrains/kotlin/idea/hierarchy/AbstractHierarchyTest.java index bb799943f08..e725adc6dbc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/hierarchy/AbstractHierarchyTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/hierarchy/AbstractHierarchyTest.java @@ -17,10 +17,11 @@ package org.jetbrains.kotlin.idea.hierarchy; import com.intellij.ide.hierarchy.*; +import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase; import com.intellij.ide.hierarchy.type.SubtypesHierarchyTreeStructure; import com.intellij.ide.hierarchy.type.SupertypesHierarchyTreeStructure; import com.intellij.ide.hierarchy.type.TypeHierarchyTreeStructure; -import com.intellij.lang.Language; +import com.intellij.lang.LanguageExtension; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.projectRoots.Sdk; @@ -36,10 +37,10 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase; -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeMethodsTreeStructure; import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerMethodsTreeStructure; import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure; +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import java.io.File; import java.util.ArrayList; @@ -91,7 +92,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new SupertypesHierarchyTreeStructure( getProject(), - (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE.forLanguage(getLanguage())) + (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE) ); } }; @@ -103,7 +104,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new SubtypesHierarchyTreeStructure( getProject(), - (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE.forLanguage(getLanguage())), + (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE), HierarchyBrowserBaseEx.SCOPE_PROJECT ); } @@ -116,7 +117,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new TypeHierarchyTreeStructure( getProject(), - (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE.forLanguage(getLanguage())), + (PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE), HierarchyBrowserBaseEx.SCOPE_PROJECT ); } @@ -129,7 +130,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new KotlinCallerMethodsTreeStructure( getProject(), - getElementAtCaret(LanguageCallHierarchy.INSTANCE.forLanguage(getLanguage())), + getElementAtCaret(LanguageCallHierarchy.INSTANCE), HierarchyBrowserBaseEx.SCOPE_PROJECT ); } @@ -142,7 +143,7 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new KotlinCalleeMethodsTreeStructure( getProject(), - getElementAtCaret(LanguageCallHierarchy.INSTANCE.forLanguage(getLanguage())), + getElementAtCaret(LanguageCallHierarchy.INSTANCE), HierarchyBrowserBaseEx.SCOPE_PROJECT ); } @@ -155,24 +156,20 @@ public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase public HierarchyTreeStructure compute() { return new KotlinOverrideTreeStructure( getProject(), - getElementAtCaret(LanguageCallHierarchy.INSTANCE.forLanguage(getLanguage())) + getElementAtCaret(LanguageCallHierarchy.INSTANCE) ); } }; } - private PsiElement getElementAtCaret(HierarchyProvider provider) { - PsiElement target = provider.getTarget(getDataContext()); + private PsiElement getElementAtCaret(LanguageExtension extension) { + PsiFile file = PsiDocumentManager.getInstance(getProject()).getPsiFile(getEditor().getDocument()); + HierarchyProvider provider = BrowseHierarchyActionBase.findProvider(extension, file, file, getDataContext()); + PsiElement target = provider != null ? provider.getTarget(getDataContext()) : null; if (target == null) throw new RefactoringErrorHintException("Cannot apply action for element at caret"); return target; } - private Language getLanguage() { - PsiFile file = PsiDocumentManager.getInstance(getProject()).getPsiFile(getEditor().getDocument()); - assert file != null : "Cannot find file in editor"; - return file.getLanguage(); - } - private DataContext getDataContext() { MapDataContext context = new MapDataContext(); context.put(CommonDataKeys.PROJECT, getProject()); diff --git a/idea/tests/org/jetbrains/kotlin/idea/hierarchy/HierarchyTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/hierarchy/HierarchyTestGenerated.java index 714be27f596..dbc22aecb85 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/hierarchy/HierarchyTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/hierarchy/HierarchyTestGenerated.java @@ -85,6 +85,12 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest { doTypeClassHierarchyTest(fileName); } + @TestMetadata("CaretAtSuperTypeCallEntry") + public void testCaretAtSuperTypeCallEntry() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/type/CaretAtSuperTypeCallEntry/"); + doTypeClassHierarchyTest(fileName); + } + @TestMetadata("CaretAtSupertypesList") public void testCaretAtSupertypesList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/type/CaretAtSupertypesList/");