diff --git a/annotations/com/intellij/ide/util/treeView/smartTree/annotations.xml b/annotations/com/intellij/ide/util/treeView/smartTree/annotations.xml
new file mode 100644
index 00000000000..1b85de98c44
--- /dev/null
+++ b/annotations/com/intellij/ide/util/treeView/smartTree/annotations.xml
@@ -0,0 +1,8 @@
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
index 41579691c04..b3eaa649ce1 100644
--- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
+++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
@@ -573,7 +573,7 @@ fun main(args: Array) {
}
testClass(javaClass()) {
- model("structureView/fileStructure")
+ model("structureView/fileStructure", pattern = """^([^\.]+)\.kt$""")
}
testClass(javaClass()) {
diff --git a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
index 2843e914cc9..16c307a8249 100644
--- a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
+++ b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java
@@ -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() {
@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);
diff --git a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewModel.java b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewModel.java
index 72a6fcd9dc8..827c1ce9dff 100644
--- a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewModel.java
+++ b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewModel.java
@@ -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 NODE_PROVIDERS = Arrays.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 getNodeProviders() {
+ return NODE_PROVIDERS;
+ }
+
@NotNull
@Override
public Sorter[] getSorters() {
diff --git a/idea/src/org/jetbrains/jet/plugin/structureView/KotlinInheritedMembersNodeProvider.kt b/idea/src/org/jetbrains/jet/plugin/structureView/KotlinInheritedMembersNodeProvider.kt
new file mode 100644
index 00000000000..55bffc226ec
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/structureView/KotlinInheritedMembersNodeProvider.kt
@@ -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() {
+ override fun provideNodes(node: TreeElement): Collection {
+ 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()
+
+ 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
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt b/idea/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt
new file mode 100644
index 00000000000..86c17c7db65
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedInnerClasses.Data.kt
@@ -0,0 +1,6 @@
+open class A {
+ class I1
+ inner class I2
+
+ fun foo() {}
+}
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedInnerClasses.after b/idea/testData/structureView/fileStructure/InheritedInnerClasses.after
new file mode 100644
index 00000000000..86c0e71bd92
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedInnerClasses.after
@@ -0,0 +1,6 @@
+-InheritedInnerClasses.kt
+ -B : A
+ equals(Any?): Boolean
+ foo(): Unit
+ hashCode(): Int
+ toString(): String
diff --git a/idea/testData/structureView/fileStructure/InheritedInnerClasses.kt b/idea/testData/structureView/fileStructure/InheritedInnerClasses.kt
new file mode 100644
index 00000000000..45a3b2d02d2
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedInnerClasses.kt
@@ -0,0 +1,5 @@
+class B: A()
+
+// Inner classes are not shown, same to Java
+
+// WITH_INHERITED
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedJavaMembers.after b/idea/testData/structureView/fileStructure/InheritedJavaMembers.after
new file mode 100644
index 00000000000..74b4f901f7e
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedJavaMembers.after
@@ -0,0 +1,15 @@
+-InheritedJavaMembers.kt
+ -InheritedJavaMembers : Callable
+ call(): String?
+ clone(): Any
+ equals(Any?): Boolean
+ finalize(): Unit
+ getClass(): Class
+ hashCode(): Int
+ notify(): Unit
+ notifyAll(): Unit
+ test(): Unit
+ toString(): String
+ wait(): Unit
+ wait(Long): Unit
+ wait(Long, Int): Unit
diff --git a/idea/testData/structureView/fileStructure/InheritedJavaMembers.kt b/idea/testData/structureView/fileStructure/InheritedJavaMembers.kt
new file mode 100644
index 00000000000..e36c9969a43
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedJavaMembers.kt
@@ -0,0 +1,8 @@
+import java.util.concurrent.Callable
+
+public abstract class InheritedJavaMembers() : Callable {
+ fun test() {
+ }
+}
+
+// WITH_INHERITED
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedLocalKotlin.after b/idea/testData/structureView/fileStructure/InheritedLocalKotlin.after
new file mode 100644
index 00000000000..5e3e2954d37
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedLocalKotlin.after
@@ -0,0 +1,8 @@
+-InheritedLocalKotlin.kt
+ -A : TA
+ equals(Any?): Boolean
+ hashCode(): Int
+ some(): Unit
+ toString(): String
+ -B : TA
+ some(): Unit
diff --git a/idea/testData/structureView/fileStructure/InheritedLocalKotlin.kt b/idea/testData/structureView/fileStructure/InheritedLocalKotlin.kt
new file mode 100644
index 00000000000..b1ac1b05ae6
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedLocalKotlin.kt
@@ -0,0 +1,12 @@
+trait TA {
+ fun some()
+}
+
+class A : TA {
+ override fun some() {
+ }
+}
+
+abstract class B : TA
+
+// WITH_INHERITED
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedMembers.after b/idea/testData/structureView/fileStructure/InheritedMembers.after
index 4f4301722d1..74d4879603e 100644
--- a/idea/testData/structureView/fileStructure/InheritedMembers.after
+++ b/idea/testData/structureView/fileStructure/InheritedMembers.after
@@ -1,2 +1,6 @@
-InheritedMembers.kt
- Test
+ -Test
+ equals(Any?): Boolean
+ hashCode(): Int
+ test(): Unit
+ toString(): String
diff --git a/idea/testData/structureView/fileStructure/InheritedMembers.kt b/idea/testData/structureView/fileStructure/InheritedMembers.kt
index 8fb2c8ad780..540c361d06a 100644
--- a/idea/testData/structureView/fileStructure/InheritedMembers.kt
+++ b/idea/testData/structureView/fileStructure/InheritedMembers.kt
@@ -1,3 +1,7 @@
-class Test {
+class Test: Runable {
+ fun test() {
-}
\ No newline at end of file
+ }
+}
+
+// WITH_INHERITED
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt
new file mode 100644
index 00000000000..8b6a1428f40
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.Data.kt
@@ -0,0 +1,7 @@
+trait First {
+ fun foo(a: T)
+}
+
+trait Second : First {
+ val a: U
+}
\ No newline at end of file
diff --git a/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after
new file mode 100644
index 00000000000..db9dad579ec
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.after
@@ -0,0 +1,7 @@
+-InheritedMembersWithSubstitutedTypes.kt
+ -Third : Second
+ a: U
+ equals(Any?): Boolean
+ foo(T): Unit
+ hashCode(): Int
+ toString(): String
diff --git a/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt
new file mode 100644
index 00000000000..2162d6de334
--- /dev/null
+++ b/idea/testData/structureView/fileStructure/InheritedMembersWithSubstitutedTypes.kt
@@ -0,0 +1,5 @@
+trait Third: Second
+
+// Original type names are shown in members, behaviour is same to Java.
+
+// WITH_INHERITED
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/structureView/AbstractKotlinFileStructureTest.kt b/idea/tests/org/jetbrains/jet/plugin/structureView/AbstractKotlinFileStructureTest.kt
index a4644f7ada1..43de5c30536 100644
--- a/idea/tests/org/jetbrains/jet/plugin/structureView/AbstractKotlinFileStructureTest.kt
+++ b/idea/tests/org/jetbrains/jet/plugin/structureView/AbstractKotlinFileStructureTest.kt
@@ -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(), withInherited)
+ }
+
public fun FileStructurePopup.update() {
getTreeBuilder().refilter()!!.doWhenProcessed {
getStructure().rebuild()
diff --git a/idea/tests/org/jetbrains/jet/plugin/structureView/KotlinFileStructureTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/structureView/KotlinFileStructureTestGenerated.java
index d283285b79b..931c54fd516 100644
--- a/idea/tests/org/jetbrains/jet/plugin/structureView/KotlinFileStructureTestGenerated.java
+++ b/idea/tests/org/jetbrains/jet/plugin/structureView/KotlinFileStructureTestGenerated.java
@@ -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");