Fix Show implementation to show inheritance through type-aliases

Show implementation(Ctrl-Hover) now should show classes which inherit such class through type-alias
 #KT-15200 fixed
This commit is contained in:
Simon Ogorodnik
2017-02-10 15:42:11 +03:00
parent 593fbadc98
commit 6dd75f697a
11 changed files with 98 additions and 6 deletions
@@ -51,10 +51,16 @@ public class TargetPlatformDetector {
return contextFile instanceof KtFile ? getPlatform((KtFile) contextFile) : JvmPlatform.INSTANCE; return contextFile instanceof KtFile ? getPlatform((KtFile) contextFile) : JvmPlatform.INSTANCE;
} }
return getPlatform((PsiFile) file);
}
public static TargetPlatform getPlatform(@NotNull PsiFile file) {
VirtualFile virtualFile = file.getOriginalFile().getVirtualFile(); VirtualFile virtualFile = file.getOriginalFile().getVirtualFile();
if (virtualFile == null) { if (virtualFile == null) {
return getDefaultPlatform(file); return getDefaultPlatform(file);
} }
Module moduleForFile = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getModuleForFile(virtualFile); Module moduleForFile = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getModuleForFile(virtualFile);
if (moduleForFile == null) { if (moduleForFile == null) {
return getDefaultPlatform(file); return getDefaultPlatform(file);
@@ -69,7 +75,7 @@ public class TargetPlatformDetector {
} }
@NotNull @NotNull
private static TargetPlatform getDefaultPlatform(@NotNull KtFile file) { private static TargetPlatform getDefaultPlatform(@NotNull PsiFile file) {
LOG.info("Using default platform for file: " + file.getName()); LOG.info("Using default platform for file: " + file.getName());
return JvmPlatform.INSTANCE; return JvmPlatform.INSTANCE;
} }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.search.ideaExtensions package org.jetbrains.kotlin.idea.search.ideaExtensions
import com.intellij.openapi.application.QueryExecutorBase import com.intellij.openapi.application.QueryExecutorBase
import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.DirectClassInheritorsSearch import com.intellij.psi.search.searches.DirectClassInheritorsSearch
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper
import org.jetbrains.kotlin.idea.search.fileScope import org.jetbrains.kotlin.idea.search.fileScope
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.stubindex.KotlinSuperClassIndex import org.jetbrains.kotlin.idea.stubindex.KotlinSuperClassIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasByExpansionShortNameIndex
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
open class KotlinDirectInheritorsSearcher : QueryExecutorBase<PsiClass, DirectClassInheritorsSearch.SearchParameters>(true) { open class KotlinDirectInheritorsSearcher : QueryExecutorBase<PsiClass, DirectClassInheritorsSearch.SearchParameters>(true) {
@@ -36,13 +38,35 @@ open class KotlinDirectInheritorsSearcher : QueryExecutorBase<PsiClass, DirectCl
val originalScope = queryParameters.scope val originalScope = queryParameters.scope
val scope = originalScope as? GlobalSearchScope ?: baseClass.containingFile?.fileScope() ?: return val scope = originalScope as? GlobalSearchScope ?: baseClass.containingFile?.fileScope() ?: return
val file = baseClass.containingFile
val names = mutableSetOf(name)
val project = file.project
val typeAliasIndex = KotlinTypeAliasByExpansionShortNameIndex.getInstance()
fun searchForTypeAliasesRecursively(typeName: String) {
ProgressManager.checkCanceled()
typeAliasIndex[typeName, project, scope].asSequence()
.map { it.name }
.filterNotNull()
.filter { it !in names }
.onEach { names.add(it) }
.forEach(::searchForTypeAliasesRecursively)
}
searchForTypeAliasesRecursively(name)
runReadAction { runReadAction {
val noLibrarySourceScope = KotlinSourceFilterScope.projectSourceAndClassFiles(scope, baseClass.project) val noLibrarySourceScope = KotlinSourceFilterScope.projectSourceAndClassFiles(scope, baseClass.project)
KotlinSuperClassIndex.getInstance()
.get(name, baseClass.project, noLibrarySourceScope).asSequence() names.forEach { name ->
.mapNotNull { candidate -> SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(candidate) } KotlinSuperClassIndex.getInstance()
.filter { candidate -> candidate.isInheritor(baseClass, false) } .get(name, baseClass.project, noLibrarySourceScope).asSequence()
.forEach { candidate -> consumer.process(candidate) } .mapNotNull { candidate -> SourceNavigationHelper.getOriginalPsiClassOrCreateLightClass(candidate) }
.filter { candidate -> candidate.isInheritor(baseClass, false) }
.forEach { candidate -> consumer.process(candidate) }
}
} }
} }
} }
@@ -0,0 +1,3 @@
<node text="A ()" base="true">
<node text="B ()"/>
</node>
@@ -0,0 +1,6 @@
open class A<caret>
typealias TA = A
typealias TTA = A
class B : TTA()
@@ -0,0 +1,3 @@
<node text="A ()" base="true">
<node text="B ()"/>
</node>
+5
View File
@@ -0,0 +1,5 @@
open class A<caret>
typealias TA = A
class B : TA()
@@ -0,0 +1,5 @@
<node text="B ()" base="true">
<node text="A ()">
<node text="Object (java.lang)"/>
</node>
</node>
@@ -0,0 +1,6 @@
open class A
typealias TA = A
typealias TTA = A
class B<caret> : TTA()
@@ -0,0 +1,5 @@
<node text="B ()" base="true">
<node text="A ()">
<node text="Object (java.lang)"/>
</node>
</node>
+5
View File
@@ -0,0 +1,5 @@
open class A
typealias TA = A
class B<caret> : TA()
@@ -227,11 +227,23 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest {
doSuperClassHierarchyTest(fileName); doSuperClassHierarchyTest(fileName);
} }
@TestMetadata("MultiTypeAlias")
public void testMultiTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/super/MultiTypeAlias/");
doSuperClassHierarchyTest(fileName);
}
@TestMetadata("TwoTraits") @TestMetadata("TwoTraits")
public void testTwoTraits() throws Exception { public void testTwoTraits() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/super/TwoTraits/"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/super/TwoTraits/");
doSuperClassHierarchyTest(fileName); doSuperClassHierarchyTest(fileName);
} }
@TestMetadata("TypeAlias")
public void testTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/super/TypeAlias/");
doSuperClassHierarchyTest(fileName);
}
} }
@TestMetadata("idea/testData/hierarchy/class/sub") @TestMetadata("idea/testData/hierarchy/class/sub")
@@ -266,6 +278,12 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest {
doSubClassHierarchyTest(fileName); doSubClassHierarchyTest(fileName);
} }
@TestMetadata("MultiTypeAlias")
public void testMultiTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/MultiTypeAlias/");
doSubClassHierarchyTest(fileName);
}
@TestMetadata("ObjectFromClass") @TestMetadata("ObjectFromClass")
public void testObjectFromClass() throws Exception { public void testObjectFromClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/ObjectFromClass/"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/ObjectFromClass/");
@@ -289,6 +307,12 @@ public class HierarchyTestGenerated extends AbstractHierarchyTest {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/TraitFromTrait/"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/TraitFromTrait/");
doSubClassHierarchyTest(fileName); doSubClassHierarchyTest(fileName);
} }
@TestMetadata("TypeAlias")
public void testTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/hierarchy/class/sub/TypeAlias/");
doSubClassHierarchyTest(fileName);
}
} }
@TestMetadata("idea/testData/hierarchy/calls/callers") @TestMetadata("idea/testData/hierarchy/calls/callers")