Show members from supertypes in file structure view (KT-4448)
#KT-4448 Fixed
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
<root>
|
||||||
|
<item
|
||||||
|
name='com.intellij.ide.util.treeView.smartTree.NodeProvider java.util.Collection<T> provideNodes(com.intellij.ide.util.treeView.smartTree.TreeElement)'>
|
||||||
|
<annotation name='kotlin.jvm.KotlinSignature'>
|
||||||
|
<val name="value" val=""fun provideNodes(node: TreeElement): Collection<T>""/>
|
||||||
|
</annotation>
|
||||||
|
</item>
|
||||||
|
</root>
|
||||||
@@ -573,7 +573,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testClass(javaClass<AbstractKotlinFileStructureTest>()) {
|
testClass(javaClass<AbstractKotlinFileStructureTest>()) {
|
||||||
model("structureView/fileStructure")
|
model("structureView/fileStructure", pattern = """^([^\.]+)\.kt$""")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass(javaClass<AbstractExpressionSelectionTest>()) {
|
testClass(javaClass<AbstractExpressionSelectionTest>()) {
|
||||||
|
|||||||
@@ -47,13 +47,27 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
|||||||
|
|
||||||
private String elementText;
|
private String elementText;
|
||||||
private Icon icon;
|
private Icon icon;
|
||||||
|
private final boolean isInherited;
|
||||||
|
|
||||||
public JetStructureViewElement(@NotNull NavigatablePsiElement element) {
|
public JetStructureViewElement(@NotNull NavigatablePsiElement element, @NotNull DeclarationDescriptor descriptor, boolean isInherited) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
|
this.isInherited = isInherited;
|
||||||
|
|
||||||
|
if (!(element instanceof JetElement)) {
|
||||||
|
// Avoid storing descriptor in fields
|
||||||
|
elementText = getElementText(element, descriptor);
|
||||||
|
icon = getElementIcon(element, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetStructureViewElement(@NotNull NavigatablePsiElement element, boolean isInherited) {
|
||||||
|
this.element = element;
|
||||||
|
this.isInherited = isInherited;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JetStructureViewElement(@NotNull JetFile fileElement) {
|
public JetStructureViewElement(@NotNull JetFile fileElement) {
|
||||||
element = fileElement;
|
element = fileElement;
|
||||||
|
isInherited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -94,7 +108,7 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
|||||||
return ArrayUtil.toObjectArray(ContainerUtil.map(childrenDeclarations, new Function<JetDeclaration, TreeElement>() {
|
return ArrayUtil.toObjectArray(ContainerUtil.map(childrenDeclarations, new Function<JetDeclaration, TreeElement>() {
|
||||||
@Override
|
@Override
|
||||||
public TreeElement fun(JetDeclaration declaration) {
|
public TreeElement fun(JetDeclaration declaration) {
|
||||||
return new JetStructureViewElement(declaration);
|
return new JetStructureViewElement(declaration, false);
|
||||||
}
|
}
|
||||||
}), TreeElement.class);
|
}), TreeElement.class);
|
||||||
}
|
}
|
||||||
@@ -102,9 +116,15 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public TextAttributesKey getTextAttributesKey() {
|
public TextAttributesKey getTextAttributesKey() {
|
||||||
|
if (isInherited()) {
|
||||||
|
return CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (element instanceof JetModifierListOwner && JetPsiUtil.isDeprecated((JetModifierListOwner) element)) {
|
if (element instanceof JetModifierListOwner && JetPsiUtil.isDeprecated((JetModifierListOwner) element)) {
|
||||||
return CodeInsightColors.DEPRECATED_ATTRIBUTES;
|
return CodeInsightColors.DEPRECATED_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +154,10 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInherited() {
|
||||||
|
return isInherited;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private DeclarationDescriptor getDescriptor() {
|
private DeclarationDescriptor getDescriptor() {
|
||||||
if (!(element.isValid() && element instanceof JetDeclaration)) {
|
if (!(element.isValid() && element instanceof JetDeclaration)) {
|
||||||
@@ -175,6 +199,7 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Icon getElementIcon(@NotNull NavigatablePsiElement navigatablePsiElement, @Nullable DeclarationDescriptor descriptor) {
|
private static Icon getElementIcon(@NotNull NavigatablePsiElement navigatablePsiElement, @Nullable DeclarationDescriptor descriptor) {
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
return JetDescriptorIconProvider.getIcon(descriptor, navigatablePsiElement, Iconable.ICON_FLAG_VISIBILITY);
|
return JetDescriptorIconProvider.getIcon(descriptor, navigatablePsiElement, Iconable.ICON_FLAG_VISIBILITY);
|
||||||
|
|||||||
@@ -17,12 +17,19 @@
|
|||||||
package org.jetbrains.jet.plugin.structureView;
|
package org.jetbrains.jet.plugin.structureView;
|
||||||
|
|
||||||
import com.intellij.ide.structureView.StructureViewModelBase;
|
import com.intellij.ide.structureView.StructureViewModelBase;
|
||||||
|
import com.intellij.ide.util.treeView.smartTree.NodeProvider;
|
||||||
import com.intellij.ide.util.treeView.smartTree.Sorter;
|
import com.intellij.ide.util.treeView.smartTree.Sorter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
public class JetStructureViewModel extends StructureViewModelBase {
|
public class JetStructureViewModel extends StructureViewModelBase {
|
||||||
|
private static final Collection<NodeProvider> NODE_PROVIDERS = Arrays.<NodeProvider>asList(
|
||||||
|
new KotlinInheritedMembersNodeProvider());
|
||||||
|
|
||||||
private static final Sorter[] sorters = new Sorter[] {Sorter.ALPHA_SORTER};
|
private static final Sorter[] sorters = new Sorter[] {Sorter.ALPHA_SORTER};
|
||||||
|
|
||||||
public JetStructureViewModel(@NotNull JetFile jetFile) {
|
public JetStructureViewModel(@NotNull JetFile jetFile) {
|
||||||
@@ -30,6 +37,12 @@ public class JetStructureViewModel extends StructureViewModelBase {
|
|||||||
withSuitableClasses(JetDeclaration.class);
|
withSuitableClasses(JetDeclaration.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<NodeProvider> getNodeProviders() {
|
||||||
|
return NODE_PROVIDERS;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Sorter[] getSorters() {
|
public Sorter[] getSorters() {
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.structureView
|
||||||
|
|
||||||
|
import com.intellij.ide.util.treeView.smartTree.TreeElement
|
||||||
|
import com.intellij.ide.util.InheritedMembersNodeProvider
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||||
|
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
|
||||||
|
import com.intellij.psi.NavigatablePsiElement
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassOrObject
|
||||||
|
|
||||||
|
public class KotlinInheritedMembersNodeProvider: InheritedMembersNodeProvider<TreeElement>() {
|
||||||
|
override fun provideNodes(node: TreeElement): Collection<TreeElement> {
|
||||||
|
if (node !is JetStructureViewElement) return listOf()
|
||||||
|
|
||||||
|
val element = node.getElement()
|
||||||
|
if (element !is JetClassOrObject) return listOf()
|
||||||
|
|
||||||
|
[suppress("USELESS_CAST")] // KT-3996 Workaround
|
||||||
|
val project = (element as NavigatablePsiElement).getProject()
|
||||||
|
|
||||||
|
val context = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||||
|
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element]
|
||||||
|
|
||||||
|
if (descriptor !is ClassifierDescriptor) return listOf()
|
||||||
|
|
||||||
|
val children = ArrayList<TreeElement>()
|
||||||
|
|
||||||
|
val defaultType = descriptor.getDefaultType()
|
||||||
|
for (memberDescriptor in defaultType.getMemberScope().getAllDescriptors()) {
|
||||||
|
if (memberDescriptor !is CallableMemberDescriptor) continue
|
||||||
|
if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue
|
||||||
|
|
||||||
|
val superTypeMember = DescriptorToDeclarationUtil.getDeclaration(project, memberDescriptor, context)
|
||||||
|
if (superTypeMember is NavigatablePsiElement) {
|
||||||
|
children.add(JetStructureViewElement(superTypeMember, memberDescriptor, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
open class A {
|
||||||
|
class I1
|
||||||
|
inner class I2
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
-InheritedInnerClasses.kt
|
||||||
|
-B : A
|
||||||
|
equals(Any?): Boolean
|
||||||
|
foo(): Unit
|
||||||
|
hashCode(): Int
|
||||||
|
toString(): String
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class B: A()
|
||||||
|
|
||||||
|
// Inner classes are not shown, same to Java
|
||||||
|
|
||||||
|
// WITH_INHERITED
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
-InheritedJavaMembers.kt
|
||||||
|
-InheritedJavaMembers : Callable<String>
|
||||||
|
call(): String?
|
||||||
|
clone(): Any
|
||||||
|
equals(Any?): Boolean
|
||||||
|
finalize(): Unit
|
||||||
|
getClass(): Class<out Any?>
|
||||||
|
hashCode(): Int
|
||||||
|
notify(): Unit
|
||||||
|
notifyAll(): Unit
|
||||||
|
test(): Unit
|
||||||
|
toString(): String
|
||||||
|
wait(): Unit
|
||||||
|
wait(Long): Unit
|
||||||
|
wait(Long, Int): Unit
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
public abstract class InheritedJavaMembers() : Callable<String> {
|
||||||
|
fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WITH_INHERITED
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
-InheritedLocalKotlin.kt
|
||||||
|
-A : TA
|
||||||
|
equals(Any?): Boolean
|
||||||
|
hashCode(): Int
|
||||||
|
some(): Unit
|
||||||
|
toString(): String
|
||||||
|
-B : TA
|
||||||
|
some(): Unit
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
trait TA {
|
||||||
|
fun some()
|
||||||
|
}
|
||||||
|
|
||||||
|
class A : TA {
|
||||||
|
override fun some() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class B : TA
|
||||||
|
|
||||||
|
// WITH_INHERITED
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
-InheritedMembers.kt
|
-InheritedMembers.kt
|
||||||
Test
|
-Test
|
||||||
|
equals(Any?): Boolean
|
||||||
|
hashCode(): Int
|
||||||
|
test(): Unit
|
||||||
|
toString(): String
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
class Test {
|
class Test: Runable {
|
||||||
|
fun test() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WITH_INHERITED
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
trait First<T> {
|
||||||
|
fun foo(a: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Second<U> : First<Int> {
|
||||||
|
val a: U
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
-InheritedMembersWithSubstitutedTypes.kt
|
||||||
|
-Third : Second<String>
|
||||||
|
a: U
|
||||||
|
equals(Any?): Boolean
|
||||||
|
foo(T): Unit
|
||||||
|
hashCode(): Int
|
||||||
|
toString(): String
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
trait Third: Second<String>
|
||||||
|
|
||||||
|
// Original type names are shown in members, behaviour is same to Java.
|
||||||
|
|
||||||
|
// WITH_INHERITED
|
||||||
+12
-1
@@ -27,12 +27,14 @@ import com.intellij.ide.util.FileStructurePopup
|
|||||||
import com.intellij.ide.actions.ViewStructureAction
|
import com.intellij.ide.actions.ViewStructureAction
|
||||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||||
import org.jetbrains.jet.JetTestUtils
|
import org.jetbrains.jet.JetTestUtils
|
||||||
|
import org.jetbrains.jet.InTextDirectivesUtils
|
||||||
|
import org.jetbrains.jet.test.util.configureWithExtraFile
|
||||||
|
|
||||||
public abstract class AbstractKotlinFileStructureTest : JetLightCodeInsightFixtureTestCase() {
|
public abstract class AbstractKotlinFileStructureTest : JetLightCodeInsightFixtureTestCase() {
|
||||||
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure"
|
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure"
|
||||||
|
|
||||||
public fun doTest(path: String) {
|
public fun doTest(path: String) {
|
||||||
myFixture.configureByFile(path)
|
myFixture.configureWithExtraFile(path)
|
||||||
|
|
||||||
val textEditor = TextEditorProvider.getInstance()!!.getTextEditor(myFixture.getEditor())
|
val textEditor = TextEditorProvider.getInstance()!!.getTextEditor(myFixture.getEditor())
|
||||||
val popup = ViewStructureAction.createPopup(myFixture.getProject(), textEditor)
|
val popup = ViewStructureAction.createPopup(myFixture.getProject(), textEditor)
|
||||||
@@ -43,10 +45,19 @@ public abstract class AbstractKotlinFileStructureTest : JetLightCodeInsightFixtu
|
|||||||
popup.getTreeBuilder().getUi()!!.getUpdater()!!.setPassThroughMode(true)
|
popup.getTreeBuilder().getUi()!!.getUpdater()!!.setPassThroughMode(true)
|
||||||
popup.update()
|
popup.update()
|
||||||
|
|
||||||
|
popup.setup()
|
||||||
|
|
||||||
val popupText = PlatformTestUtil.print(popup.getTree(), false)
|
val popupText = PlatformTestUtil.print(popup.getTree(), false)
|
||||||
JetTestUtils.assertEqualsToFile(File("${FileUtil.getNameWithoutExtension(path)}.after"), popupText)
|
JetTestUtils.assertEqualsToFile(File("${FileUtil.getNameWithoutExtension(path)}.after"), popupText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun FileStructurePopup.setup() {
|
||||||
|
val fileText = FileUtil.loadFile(File(getTestDataPath(), fileName()!!), true)
|
||||||
|
|
||||||
|
val withInherited = InTextDirectivesUtils.isDirectiveDefined(fileText, "WITH_INHERITED")
|
||||||
|
setTreeActionState(javaClass<KotlinInheritedMembersNodeProvider>(), withInherited)
|
||||||
|
}
|
||||||
|
|
||||||
public fun FileStructurePopup.update() {
|
public fun FileStructurePopup.update() {
|
||||||
getTreeBuilder().refilter()!!.doWhenProcessed {
|
getTreeBuilder().refilter()!!.doWhenProcessed {
|
||||||
getStructure().rebuild()
|
getStructure().rebuild()
|
||||||
|
|||||||
+23
-1
@@ -33,7 +33,9 @@ import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest;
|
|||||||
@TestMetadata("idea/testData/structureView/fileStructure")
|
@TestMetadata("idea/testData/structureView/fileStructure")
|
||||||
public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructureTest {
|
public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructureTest {
|
||||||
public void testAllFilesPresentInFileStructure() throws Exception {
|
public void testAllFilesPresentInFileStructure() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/structureView/fileStructure"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage",
|
||||||
|
new File("idea/testData/structureView/fileStructure"),
|
||||||
|
Pattern.compile("^([^\\.]+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("EmptyFile.kt")
|
@TestMetadata("EmptyFile.kt")
|
||||||
@@ -41,11 +43,31 @@ public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructur
|
|||||||
doTest("idea/testData/structureView/fileStructure/EmptyFile.kt");
|
doTest("idea/testData/structureView/fileStructure/EmptyFile.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritedInnerClasses.kt")
|
||||||
|
public void testInheritedInnerClasses() throws Exception {
|
||||||
|
doTest("idea/testData/structureView/fileStructure/InheritedInnerClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritedJavaMembers.kt")
|
||||||
|
public void testInheritedJavaMembers() throws Exception {
|
||||||
|
doTest("idea/testData/structureView/fileStructure/InheritedJavaMembers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritedLocalKotlin.kt")
|
||||||
|
public void testInheritedLocalKotlin() throws Exception {
|
||||||
|
doTest("idea/testData/structureView/fileStructure/InheritedLocalKotlin.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InheritedMembers.kt")
|
@TestMetadata("InheritedMembers.kt")
|
||||||
public void testInheritedMembers() throws Exception {
|
public void testInheritedMembers() throws Exception {
|
||||||
doTest("idea/testData/structureView/fileStructure/InheritedMembers.kt");
|
doTest("idea/testData/structureView/fileStructure/InheritedMembers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritedMembersWithSubstitutedTypes.kt")
|
||||||
|
public void testInheritedMembersWithSubstitutedTypes() throws Exception {
|
||||||
|
doTest("idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Render.kt")
|
@TestMetadata("Render.kt")
|
||||||
public void testRender() throws Exception {
|
public void testRender() throws Exception {
|
||||||
doTest("idea/testData/structureView/fileStructure/Render.kt");
|
doTest("idea/testData/structureView/fileStructure/Render.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user