201: Update hierarchy to new API (fix bugs introduced by the platform)

193 plugins with old API are affected while being binary compatible.
This commit is contained in:
Nikolay Krasko
2020-01-28 21:55:09 +03:00
committed by Nikolay Krasko
parent 5e58a66c58
commit 78385d5f63
18 changed files with 154 additions and 566 deletions
@@ -15,9 +15,6 @@
*/
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.CallHierarchyBrowserBase
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.ide.hierarchy.JavaHierarchyUtil
import com.intellij.ide.util.treeView.NodeDescriptor
import com.intellij.openapi.actionSystem.ActionGroup
@@ -33,7 +30,7 @@ import javax.swing.JTree
class KotlinCallHierarchyBrowser(element: PsiElement) :
CallHierarchyBrowserBase(element.project, element) {
override fun createTrees(type2TreeMap: MutableMap<String, JTree>) {
override fun createTrees(trees: MutableMap<HierarchyScopeType, JTree>) {
val group = ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP) as ActionGroup
val baseOnThisMethodAction = BaseOnThisMethodAction()
@@ -48,7 +45,7 @@ class KotlinCallHierarchyBrowser(element: PsiElement) :
ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).shortcutSet,
tree1
)
type2TreeMap[CALLEE_TYPE] = tree1
trees[getCalleeTypeCompat()] = tree1
val tree2 = createTree(false)
PopupHandler.installPopupHandler(
@@ -61,7 +58,7 @@ class KotlinCallHierarchyBrowser(element: PsiElement) :
ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).shortcutSet,
tree2
)
type2TreeMap[CALLER_TYPE] = tree2
trees[getCallerTypeCompat()] = tree2
}
override fun getElementFromDescriptor(descriptor: HierarchyNodeDescriptor): PsiElement? {
@@ -73,13 +70,13 @@ class KotlinCallHierarchyBrowser(element: PsiElement) :
}
override fun createHierarchyTreeStructure(
typeName: String,
type: HierarchyScopeType,
psiElement: PsiElement
): HierarchyTreeStructure? {
if (psiElement !is KtElement) return null
return when (typeName) {
CALLER_TYPE -> KotlinCallerTreeStructure(psiElement, currentScopeType)
CALLEE_TYPE -> KotlinCalleeTreeStructure(psiElement, currentScopeType)
return when (type) {
getCallerTypeCompat() -> KotlinCallerTreeStructure(psiElement, currentScopeType)
getCalleeTypeCompat() -> KotlinCalleeTreeStructure(psiElement, currentScopeType)
else -> null
}
}
@@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.icons.AllIcons
import com.intellij.ide.IdeBundle
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.roots.ui.util.CompositeAppearance
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.CallHierarchyBrowserBase
import com.intellij.ide.hierarchy.HierarchyBrowser
import com.intellij.ide.hierarchy.HierarchyProvider
import com.intellij.openapi.actionSystem.DataContext
@@ -35,6 +34,6 @@ class KotlinCallHierarchyProvider : HierarchyProvider {
override fun createHierarchyBrowser(target: PsiElement) = KotlinCallHierarchyBrowser(target)
override fun browserActivated(hierarchyBrowser: HierarchyBrowser) {
(hierarchyBrowser as KotlinCallHierarchyBrowser).changeView(CallHierarchyBrowserBase.CALLER_TYPE)
(hierarchyBrowser as KotlinCallHierarchyBrowser).changeView(getCallerTypeCompat())
}
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.call.CallReferenceProcessor
import com.intellij.ide.hierarchy.call.JavaCallHierarchyData
import com.intellij.ide.util.treeView.NodeDescriptor
@@ -5,12 +5,10 @@
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor
import com.intellij.ide.hierarchy.call.CalleeMethodsTreeStructure
import com.intellij.ide.util.treeView.NodeDescriptor
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.caches.resolve.analyze
@@ -39,9 +37,8 @@ class KotlinCalleeTreeStructure(
override fun buildChildren(nodeDescriptor: HierarchyNodeDescriptor): Array<Any> {
if (nodeDescriptor is CallHierarchyNodeDescriptor) {
val member /* : PsiMember in 193, : PsiMethod in 192 */ =
extractMemberFromDescriptor(nodeDescriptor) ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
return CalleeMethodsTreeStructure(myProject, member, scopeType).getChildElements(nodeDescriptor)
val psiMethod = nodeDescriptor.enclosingElement as? PsiMethod ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
return createCalleeMethodsTreeStructure(myProject, psiMethod, scopeType).getChildElements(nodeDescriptor)
}
val element = nodeDescriptor.psiElement as? KtElement ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.find.findUsages.JavaFindUsagesOptions
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure
import com.intellij.ide.util.treeView.NodeDescriptor
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMember
@@ -65,9 +62,8 @@ class KotlinCallerTreeStructure(
callerToDescriptorMap: MutableMap<PsiElement, NodeDescriptor<*>>
): Collection<Any> {
if (nodeDescriptor is CallHierarchyNodeDescriptor) {
val member /* : PsiMember in 193, : PsiMethod in 192 */ =
extractMemberFromDescriptor(nodeDescriptor) ?: return emptyList()
return CallerMethodsTreeStructure(myProject, member, scopeType).getChildElements(nodeDescriptor).toList()
val psiMethod = nodeDescriptor.enclosingElement as? PsiMethod ?: return emptyList()
return createCallerMethodsTreeStructure(myProject, psiMethod, scopeType).getChildElements(nodeDescriptor).toList()
}
if (element !is KtDeclaration) return emptyList()
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.call.CallHierarchyNodeDescriptor
import com.intellij.ide.util.treeView.NodeDescriptor
import com.intellij.psi.PsiElement
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("TYPEALIAS_EXPANSION_DEPRECATION", "DEPRECATION", "UnstableApiUsage")
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.call.CalleeMethodsTreeStructure
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMethod
// BUNCH: 193
typealias HierarchyNodeDescriptor = com.intellij.ide.hierarchy.HierarchyNodeDescriptor
typealias HierarchyTreeStructure = com.intellij.ide.hierarchy.HierarchyTreeStructure
typealias CallHierarchyBrowserBase = com.intellij.ide.hierarchy.CallHierarchyBrowserBase
typealias HierarchyScopeType = String
typealias HierarchyBrowserBaseEx = com.intellij.ide.hierarchy.HierarchyBrowserBaseEx
typealias MethodHierarchyBrowserBase = com.intellij.ide.hierarchy.MethodHierarchyBrowserBase
fun getCallerTypeCompat(): String = CallHierarchyBrowserBase.CALLER_TYPE
fun getCalleeTypeCompat(): String = CallHierarchyBrowserBase.CALLEE_TYPE
fun getMethodTypeCompat(): String = MethodHierarchyBrowserBase.METHOD_TYPE
fun createCallerMethodsTreeStructure(project: Project, method: PsiMethod, scopeType: String): CallerMethodsTreeStructure {
return CallerMethodsTreeStructure(project, method, scopeType)
}
fun createCalleeMethodsTreeStructure(project: Project, method: PsiMethod, scopeType: String): CalleeMethodsTreeStructure {
return CalleeMethodsTreeStructure(project, method, scopeType)
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("TYPEALIAS_EXPANSION_DEPRECATION", "DEPRECATION")
package org.jetbrains.kotlin.idea.hierarchy.calls
import com.intellij.ide.hierarchy.call.CalleeMethodsTreeStructure
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
// BUNCH: 193
typealias HierarchyNodeDescriptor = com.intellij.ide.hierarchy.newAPI.HierarchyNodeDescriptor
typealias HierarchyTreeStructure = com.intellij.ide.hierarchy.newAPI.HierarchyTreeStructure
typealias CallHierarchyBrowserBase = com.intellij.ide.hierarchy.newAPI.CallHierarchyBrowserBase
typealias HierarchyScopeType = com.intellij.ide.hierarchy.newAPI.HierarchyScopeType
typealias HierarchyBrowserBaseEx = com.intellij.ide.hierarchy.newAPI.HierarchyBrowserBaseEx
typealias MethodHierarchyBrowserBase = com.intellij.ide.hierarchy.newAPI.MethodHierarchyBrowserBase
fun getCallerTypeCompat() = CallHierarchyBrowserBase.getCallerType()
fun getCalleeTypeCompat() = CallHierarchyBrowserBase.getCalleeType()
fun getMethodTypeCompat() = MethodHierarchyBrowserBase.getMethodType()
fun createCallerMethodsTreeStructure(project: Project, method: PsiMethod, scopeType: String): CallerMethodsTreeStructure {
return CallerMethodsTreeStructure(project, method as PsiMember, scopeType)
}
fun createCalleeMethodsTreeStructure(project: Project, method: PsiMethod, scopeType: String): CalleeMethodsTreeStructure {
return CalleeMethodsTreeStructure(project, method as PsiMember, scopeType)
}
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.idea.hierarchy.overrides
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.ide.hierarchy.JavaHierarchyUtil
import com.intellij.ide.hierarchy.MethodHierarchyBrowserBase
import com.intellij.openapi.actionSystem.ActionGroup
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionPlaces
@@ -31,6 +28,7 @@ import com.intellij.ui.PopupHandler
import com.intellij.usageView.UsageViewLongNameLocation
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.hierarchy.calls.*
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import javax.swing.JPanel
@@ -39,7 +37,7 @@ import javax.swing.JTree
class KotlinOverrideHierarchyBrowser(
project: Project, baseElement: PsiElement
) : MethodHierarchyBrowserBase(project, baseElement) {
override fun createTrees(trees: MutableMap<String, JTree>) {
override fun createTrees(trees: MutableMap<HierarchyScopeType, JTree>) {
val actionManager = ActionManager.getInstance()
val tree = createTree(false)
@@ -49,7 +47,7 @@ class KotlinOverrideHierarchyBrowser(
BaseOnThisMethodAction().registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_METHOD_HIERARCHY).shortcutSet, tree)
trees[METHOD_TYPE] = tree
trees[getMethodTypeCompat()] = tree
}
override fun createLegendPanel(): JPanel? =
@@ -64,8 +62,8 @@ class KotlinOverrideHierarchyBrowser(
override fun isApplicableElement(psiElement: PsiElement): Boolean =
psiElement.isOverrideHierarchyElement()
override fun createHierarchyTreeStructure(typeName: String, psiElement: PsiElement): HierarchyTreeStructure? =
if (typeName == METHOD_TYPE) KotlinOverrideTreeStructure(myProject, psiElement as KtCallableDeclaration) else null
override fun createHierarchyTreeStructure(typeName: HierarchyScopeType, psiElement: PsiElement): HierarchyTreeStructure? =
if (typeName == getMethodTypeCompat()) KotlinOverrideTreeStructure(myProject, psiElement as KtCallableDeclaration) else null
override fun getComparator() = JavaHierarchyUtil.getComparator(myProject)
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.hierarchy.overrides
import com.intellij.icons.AllIcons
import com.intellij.ide.IdeBundle
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.roots.ui.util.CompositeAppearance
import com.intellij.openapi.util.Comparing
@@ -30,6 +29,7 @@ import com.intellij.ui.RowIcon
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyNodeDescriptor
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.idea.hierarchy.overrides
import com.intellij.icons.AllIcons
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.openapi.project.Project
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyNodeDescriptor
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyTreeStructure
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
import org.jetbrains.kotlin.psi.KtCallableDeclaration
@@ -4,10 +4,10 @@
*/
package org.jetbrains.kotlin.idea
import com.intellij.ide.hierarchy.HierarchyTreeStructure
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyTreeStructure
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.junit.runner.RunWith
@@ -20,16 +20,12 @@ abstract class KotlinHierarchyViewTestBase : KotlinLightCodeInsightFixtureTestCa
@Throws(Exception::class)
protected open fun doHierarchyTest(
treeStructureComputable: Computable<out HierarchyTreeStructure?>,
treeStructureComputable: Computable<out HierarchyTreeStructure>,
vararg fileNames: String
) {
configure(fileNames)
val expectedStructure = loadExpectedStructure()
hierarchyFixture.doHierarchyTest(treeStructureComputable.compute(), expectedStructure)
}
private fun configure(fileNames: Array<String>) {
myFixture.configureByFiles(*fileNames)
val expectedStructure = loadExpectedStructure()
doHierarchyTestCompat(hierarchyFixture, treeStructureComputable, expectedStructure)
}
@Throws(IOException::class)
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea
import com.intellij.openapi.util.Computable
import com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyTreeStructure
// BUNCH: 193
@Suppress("UNUSED_PARAMETER")
fun doHierarchyTestCompat(
hierarchyFixture: HierarchyViewTestFixture,
treeStructureComputable: Computable<out HierarchyTreeStructure>,
expectedStructure: String,
) {
HierarchyViewTestFixture.doHierarchyTest(treeStructureComputable.compute(), expectedStructure)
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea
import com.intellij.openapi.util.Computable
import com.intellij.testFramework.codeInsight.hierarchy.HierarchyViewTestFixture
import org.jetbrains.kotlin.idea.hierarchy.calls.HierarchyTreeStructure
// BUNCH: 193
@Suppress("UNUSED_PARAMETER")
fun doHierarchyTestCompat(
hierarchyFixture: HierarchyViewTestFixture,
treeStructureComputable: Computable<out HierarchyTreeStructure>,
expectedStructure: String,
) {
hierarchyFixture.doHierarchyTest(treeStructureComputable.compute(), expectedStructure)
}
@@ -1,252 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.hierarchy;
import com.intellij.ide.hierarchy.*;
import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase;
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure;
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.LanguageExtension;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*;
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException;
import com.intellij.rt.execution.junit.ComparisonDetailsExtractor;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.MapDataContext;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import junit.framework.ComparisonFailure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
import org.jetbrains.kotlin.psi.KtCallableDeclaration;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
Test Hierarchy view
Format: test build hierarchy for element at caret, file with caret should be the first in the sorted list of files.
Test accept more than one file, file extension should be .java or .kt
*/
public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase {
protected String folderName;
protected void doTypeClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getTypeHierarchyStructure(), getFilesToConfigure());
}
protected void doSuperClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSuperTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doSubClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSubTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerJavaHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerJavaHierarchyStructure(), getFilesToConfigure());
}
protected void doCalleeHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCalleeHierarchyStructure(), getFilesToConfigure());
}
protected void doOverrideHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getOverrideHierarchyStructure(), getFilesToConfigure());
}
private Computable<HierarchyTreeStructure> getSuperTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SupertypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE)
);
}
};
}
private Computable<HierarchyTreeStructure> getSubTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SubtypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getTypeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new TypeHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCallerTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerJavaHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new CallerMethodsTreeStructure(
getProject(),
(PsiMethod) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCalleeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCalleeTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getOverrideHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinOverrideTreeStructure(
getProject(),
(KtCallableDeclaration) getElementAtCaret(LanguageMethodHierarchy.INSTANCE)
);
}
};
}
private PsiElement getElementAtCaret(LanguageExtension<HierarchyProvider> 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 DataContext getDataContext() {
Editor editor = getEditor();
MapDataContext context = new MapDataContext();
context.put(CommonDataKeys.PROJECT, getProject());
context.put(CommonDataKeys.EDITOR, editor);
PsiElement targetElement = (PsiElement) new TextEditorPsiDataProvider().getData(
CommonDataKeys.PSI_ELEMENT.getName(),
editor,
editor.getCaretModel().getCurrentCaret()
);
context.put(CommonDataKeys.PSI_ELEMENT, targetElement);
return context;
}
protected String[] getFilesToConfigure() {
final List<String> files = new ArrayList<String>(2);
FileUtil.processFilesRecursively(new File(folderName), new Processor<File>() {
@Override
public boolean process(File file) {
String fileName = file.getName();
if (fileName.endsWith(".kt") || fileName.endsWith(".java")) {
files.add(fileName);
}
return true;
}
});
Collections.sort(files);
return ArrayUtil.toStringArray(files);
}
@Override
protected void doHierarchyTest(
@NotNull Computable<? extends HierarchyTreeStructure> treeStructureComputable, @NotNull String... fileNames
) throws Exception {
try {
super.doHierarchyTest(treeStructureComputable, fileNames);
}
catch (RefactoringErrorHintException e) {
File file = new File(folderName, "messages.txt");
if (file.exists()) {
String expectedMessage = FileUtil.loadFile(file, true);
assertEquals(expectedMessage, e.getLocalizedMessage());
}
else {
fail("Unexpected error: " + e.getLocalizedMessage());
}
}
catch (ComparisonFailure failure) {
String actual = ComparisonDetailsExtractor.getActual(failure);
String verificationFilePath =
getTestDataPath() + "/" + getTestName(false) + "_verification.xml";
KotlinTestUtils.assertEqualsToFile(new File(verificationFilePath), actual);
}
}
@Override
@NotNull
protected LightProjectDescriptor getProjectDescriptor() {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE;
}
@NotNull
@Override
protected String getTestDataPath() {
String testRoot = super.getTestDataPath();
String testDir = KotlinTestUtils.getTestDataFileName(this.getClass(), getName());
return testRoot + "/" + testDir;
}
}
@@ -1,252 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.hierarchy;
import com.intellij.ide.hierarchy.*;
import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase;
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure;
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.LanguageExtension;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*;
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException;
import com.intellij.rt.execution.junit.ComparisonDetailsExtractor;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.MapDataContext;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import junit.framework.ComparisonFailure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure;
import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
import org.jetbrains.kotlin.psi.KtCallableDeclaration;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
Test Hierarchy view
Format: test build hierarchy for element at caret, file with caret should be the first in the sorted list of files.
Test accept more than one file, file extension should be .java or .kt
*/
public abstract class AbstractHierarchyTest extends KotlinHierarchyViewTestBase {
protected String folderName;
protected void doTypeClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getTypeHierarchyStructure(), getFilesToConfigure());
}
protected void doSuperClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSuperTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doSubClassHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getSubTypesHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerHierarchyStructure(), getFilesToConfigure());
}
protected void doCallerJavaHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCallerJavaHierarchyStructure(), getFilesToConfigure());
}
protected void doCalleeHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getCalleeHierarchyStructure(), getFilesToConfigure());
}
protected void doOverrideHierarchyTest(@NotNull String folderName) throws Exception {
this.folderName = folderName;
doHierarchyTest(getOverrideHierarchyStructure(), getFilesToConfigure());
}
private Computable<HierarchyTreeStructure> getSuperTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SupertypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE)
);
}
};
}
private Computable<HierarchyTreeStructure> getSubTypesHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new SubtypesHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getTypeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new TypeHierarchyTreeStructure(
getProject(),
(PsiClass) getElementAtCaret(LanguageTypeHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCallerTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCallerJavaHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new CallerMethodsTreeStructure(
getProject(),
(PsiMethod) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getCalleeHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinCalleeTreeStructure(
(KtElement) getElementAtCaret(LanguageCallHierarchy.INSTANCE),
HierarchyBrowserBaseEx.SCOPE_PROJECT
);
}
};
}
private Computable<HierarchyTreeStructure> getOverrideHierarchyStructure() {
return new Computable<HierarchyTreeStructure>() {
@Override
public HierarchyTreeStructure compute() {
return new KotlinOverrideTreeStructure(
getProject(),
(KtCallableDeclaration) getElementAtCaret(LanguageMethodHierarchy.INSTANCE)
);
}
};
}
private PsiElement getElementAtCaret(LanguageExtension<HierarchyProvider> 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 DataContext getDataContext() {
Editor editor = getEditor();
MapDataContext context = new MapDataContext();
context.put(CommonDataKeys.PROJECT, getProject());
context.put(CommonDataKeys.EDITOR, editor);
PsiElement targetElement = (PsiElement) new TextEditorPsiDataProvider().getData(
CommonDataKeys.PSI_ELEMENT.getName(),
editor,
editor.getCaretModel().getCurrentCaret()
);
context.put(CommonDataKeys.PSI_ELEMENT, targetElement);
return context;
}
protected String[] getFilesToConfigure() {
final List<String> files = new ArrayList<String>(2);
FileUtil.processFilesRecursively(new File(folderName), new Processor<File>() {
@Override
public boolean process(File file) {
String fileName = file.getName();
if (fileName.endsWith(".kt") || fileName.endsWith(".java")) {
files.add(fileName);
}
return true;
}
});
Collections.sort(files);
return ArrayUtil.toStringArray(files);
}
@Override
protected void doHierarchyTest(
@NotNull Computable<? extends HierarchyTreeStructure> treeStructureComputable, @NotNull String... fileNames
) throws Exception {
try {
super.doHierarchyTest(treeStructureComputable, fileNames);
}
catch (RefactoringErrorHintException e) {
File file = new File(folderName, "messages.txt");
if (file.exists()) {
String expectedMessage = FileUtil.loadFile(file, true);
assertEquals(expectedMessage, e.getLocalizedMessage());
}
else {
fail("Unexpected error: " + e.getLocalizedMessage());
}
}
catch (ComparisonFailure failure) {
String actual = ComparisonDetailsExtractor.getActual(failure);
String verificationFilePath =
getTestDataPath() + "/" + getTestName(false) + "_verification.xml";
KotlinTestUtils.assertEqualsToFile(new File(verificationFilePath), actual);
}
}
@Override
@NotNull
protected LightProjectDescriptor getProjectDescriptor() {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE;
}
@NotNull
@Override
protected String getTestDataPath() {
String testRoot = super.getTestDataPath();
String testDir = KotlinTestUtils.getTestDataFileName(this.getClass(), getName());
return testRoot + "/" + testDir;
}
}
@@ -4,9 +4,11 @@
*/
package org.jetbrains.kotlin.idea.hierarchy
import com.intellij.ide.hierarchy.*
import com.intellij.ide.hierarchy.HierarchyProvider
import com.intellij.ide.hierarchy.LanguageCallHierarchy
import com.intellij.ide.hierarchy.LanguageMethodHierarchy
import com.intellij.ide.hierarchy.LanguageTypeHierarchy
import com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase
import com.intellij.ide.hierarchy.call.CallerMethodsTreeStructure
import com.intellij.ide.hierarchy.type.SubtypesHierarchyTreeStructure
import com.intellij.ide.hierarchy.type.SupertypesHierarchyTreeStructure
import com.intellij.ide.hierarchy.type.TypeHierarchyTreeStructure
@@ -16,7 +18,10 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.*
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException
import com.intellij.rt.execution.junit.ComparisonDetailsExtractor
import com.intellij.testFramework.LightProjectDescriptor
@@ -25,8 +30,7 @@ import com.intellij.util.ArrayUtil
import junit.framework.ComparisonFailure
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.KotlinHierarchyViewTestBase
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCalleeTreeStructure
import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallerTreeStructure
import org.jetbrains.kotlin.idea.hierarchy.calls.*
import org.jetbrains.kotlin.idea.hierarchy.overrides.KotlinOverrideTreeStructure
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.psi.KtCallableDeclaration
@@ -86,7 +90,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val superTypesHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
SupertypesHierarchyTreeStructure(
project,
getElementAtCaret(LanguageTypeHierarchy.INSTANCE) as PsiClass
@@ -94,7 +98,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val subTypesHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
SubtypesHierarchyTreeStructure(
project,
getElementAtCaret(LanguageTypeHierarchy.INSTANCE) as PsiClass,
@@ -103,7 +107,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val typeHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
TypeHierarchyTreeStructure(
project,
getElementAtCaret(LanguageTypeHierarchy.INSTANCE) as PsiClass,
@@ -112,7 +116,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val callerHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
KotlinCallerTreeStructure(
(getElementAtCaret(LanguageCallHierarchy.INSTANCE) as KtElement),
HierarchyBrowserBaseEx.SCOPE_PROJECT
@@ -120,16 +124,16 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val callerJavaHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
CallerMethodsTreeStructure(
get() = Computable {
createCallerMethodsTreeStructure(
project,
(getElementAtCaret(LanguageCallHierarchy.INSTANCE) as PsiMember),
(getElementAtCaret(LanguageCallHierarchy.INSTANCE) as PsiMethod),
HierarchyBrowserBaseEx.SCOPE_PROJECT
)
}
private val calleeHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
KotlinCalleeTreeStructure(
(getElementAtCaret(LanguageCallHierarchy.INSTANCE) as KtElement),
HierarchyBrowserBaseEx.SCOPE_PROJECT
@@ -137,7 +141,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val overrideHierarchyStructure: Computable<HierarchyTreeStructure>
private get() = Computable {
get() = Computable {
KotlinOverrideTreeStructure(
project,
(getElementAtCaret(LanguageMethodHierarchy.INSTANCE) as KtCallableDeclaration)
@@ -154,7 +158,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
private val dataContext: DataContext
private get() {
get() {
val editor = editor
val context = MapDataContext()
context.put(CommonDataKeys.PROJECT, project)
@@ -169,7 +173,8 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
protected val filesToConfigure: Array<String>
protected get() {
get() {
val folderName = folderName ?: error("folderName should be initialized")
val files: MutableList<String> = ArrayList(2)
FileUtil.processFilesRecursively(
File(folderName)
@@ -180,7 +185,7 @@ abstract class AbstractHierarchyTest : KotlinHierarchyViewTestBase() {
}
true
}
Collections.sort(files)
files.sort()
return ArrayUtil.toStringArray(files)
}