mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
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>()) {
|
||||
model("structureView/fileStructure")
|
||||
model("structureView/fileStructure", pattern = """^([^\.]+)\.kt$""")
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractExpressionSelectionTest>()) {
|
||||
|
||||
@@ -47,13 +47,27 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
||||
|
||||
private String elementText;
|
||||
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.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) {
|
||||
element = fileElement;
|
||||
isInherited = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -94,7 +108,7 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
||||
return ArrayUtil.toObjectArray(ContainerUtil.map(childrenDeclarations, new Function<JetDeclaration, TreeElement>() {
|
||||
@Override
|
||||
public TreeElement fun(JetDeclaration declaration) {
|
||||
return new JetStructureViewElement(declaration);
|
||||
return new JetStructureViewElement(declaration, false);
|
||||
}
|
||||
}), TreeElement.class);
|
||||
}
|
||||
@@ -102,9 +116,15 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
||||
@Nullable
|
||||
@Override
|
||||
public TextAttributesKey getTextAttributesKey() {
|
||||
if (isInherited()) {
|
||||
return CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES;
|
||||
}
|
||||
|
||||
|
||||
if (element instanceof JetModifierListOwner && JetPsiUtil.isDeprecated((JetModifierListOwner) element)) {
|
||||
return CodeInsightColors.DEPRECATED_ATTRIBUTES;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -134,6 +154,10 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
||||
return icon;
|
||||
}
|
||||
|
||||
public boolean isInherited() {
|
||||
return isInherited;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DeclarationDescriptor getDescriptor() {
|
||||
if (!(element.isValid() && element instanceof JetDeclaration)) {
|
||||
@@ -175,6 +199,7 @@ public class JetStructureViewElement implements StructureViewTreeElement, Colore
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Icon getElementIcon(@NotNull NavigatablePsiElement navigatablePsiElement, @Nullable DeclarationDescriptor descriptor) {
|
||||
if (descriptor != null) {
|
||||
return JetDescriptorIconProvider.getIcon(descriptor, navigatablePsiElement, Iconable.ICON_FLAG_VISIBILITY);
|
||||
|
||||
@@ -17,12 +17,19 @@
|
||||
package org.jetbrains.jet.plugin.structureView;
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewModelBase;
|
||||
import com.intellij.ide.util.treeView.smartTree.NodeProvider;
|
||||
import com.intellij.ide.util.treeView.smartTree.Sorter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
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};
|
||||
|
||||
public JetStructureViewModel(@NotNull JetFile jetFile) {
|
||||
@@ -30,6 +37,12 @@ public class JetStructureViewModel extends StructureViewModelBase {
|
||||
withSuitableClasses(JetDeclaration.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<NodeProvider> getNodeProviders() {
|
||||
return NODE_PROVIDERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
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
|
||||
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
|
||||
@@ -27,12 +27,14 @@ import com.intellij.ide.util.FileStructurePopup
|
||||
import com.intellij.ide.actions.ViewStructureAction
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import org.jetbrains.jet.JetTestUtils
|
||||
import org.jetbrains.jet.InTextDirectivesUtils
|
||||
import org.jetbrains.jet.test.util.configureWithExtraFile
|
||||
|
||||
public abstract class AbstractKotlinFileStructureTest : JetLightCodeInsightFixtureTestCase() {
|
||||
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/structureView/fileStructure"
|
||||
|
||||
public fun doTest(path: String) {
|
||||
myFixture.configureByFile(path)
|
||||
myFixture.configureWithExtraFile(path)
|
||||
|
||||
val textEditor = TextEditorProvider.getInstance()!!.getTextEditor(myFixture.getEditor())
|
||||
val popup = ViewStructureAction.createPopup(myFixture.getProject(), textEditor)
|
||||
@@ -43,10 +45,19 @@ public abstract class AbstractKotlinFileStructureTest : JetLightCodeInsightFixtu
|
||||
popup.getTreeBuilder().getUi()!!.getUpdater()!!.setPassThroughMode(true)
|
||||
popup.update()
|
||||
|
||||
popup.setup()
|
||||
|
||||
val popupText = PlatformTestUtil.print(popup.getTree(), false)
|
||||
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() {
|
||||
getTreeBuilder().refilter()!!.doWhenProcessed {
|
||||
getStructure().rebuild()
|
||||
|
||||
@@ -33,7 +33,9 @@ import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest;
|
||||
@TestMetadata("idea/testData/structureView/fileStructure")
|
||||
public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructureTest {
|
||||
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")
|
||||
@@ -41,11 +43,31 @@ public class KotlinFileStructureTestGenerated extends AbstractKotlinFileStructur
|
||||
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")
|
||||
public void testInheritedMembers() throws Exception {
|
||||
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")
|
||||
public void testRender() throws Exception {
|
||||
doTest("idea/testData/structureView/fileStructure/Render.kt");
|
||||
|
||||
Reference in New Issue
Block a user