From b92a228fb3abd833240766a51396aeb5a6df2b5c Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 28 Jan 2020 21:55:08 +0300 Subject: [PATCH] 201: Convert KotlinCallHierarchyBrowser and KotlinCallHierarchyBrowser Need convert to use Kotlin typealias feature. --- .../calls/KotlinCallHierarchyBrowser.kt | 141 ++++---- .../KotlinCallHierarchyNodeDescriptor.kt | 332 ++++++++---------- 2 files changed, 220 insertions(+), 253 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyBrowser.kt b/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyBrowser.kt index eb2b62688ef..4e6e0c6e603 100644 --- a/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyBrowser.kt +++ b/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyBrowser.kt @@ -13,88 +13,85 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package org.jetbrains.kotlin.idea.hierarchy.calls -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 +import com.intellij.openapi.actionSystem.ActionManager +import com.intellij.openapi.actionSystem.ActionPlaces +import com.intellij.openapi.actionSystem.IdeActions +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.ui.PopupHandler +import org.jetbrains.kotlin.psi.KtElement +import java.util.* +import javax.swing.JTree -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; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.ui.PopupHandler; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.psi.KtElement; - -import javax.swing.*; -import java.util.Comparator; -import java.util.Map; - -public class KotlinCallHierarchyBrowser extends CallHierarchyBrowserBase { - public KotlinCallHierarchyBrowser(@NotNull PsiElement element) { - super(element.getProject(), element); - } - - @Override - protected void createTrees(@NotNull Map type2TreeMap) { - ActionGroup group = (ActionGroup) ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP); - - JTree tree1 = createTree(false); - PopupHandler.installPopupHandler(tree1, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); - BaseOnThisMethodAction baseOnThisMethodAction = new BaseOnThisMethodAction(); +class KotlinCallHierarchyBrowser(element: PsiElement) : + CallHierarchyBrowserBase(element.project, element) { + override fun createTrees(type2TreeMap: MutableMap) { + val group = + ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP) as ActionGroup + val tree1 = createTree(false) + PopupHandler.installPopupHandler( + tree1, + group, + ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, + ActionManager.getInstance() + ) + val baseOnThisMethodAction = + BaseOnThisMethodAction() baseOnThisMethodAction.registerCustomShortcutSet( - ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree1 - ); - type2TreeMap.put(CALLEE_TYPE, tree1); - - JTree tree2 = createTree(false); - PopupHandler.installPopupHandler(tree2, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, ActionManager.getInstance()); + ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).shortcutSet, + tree1 + ) + type2TreeMap[CALLEE_TYPE] = tree1 + val tree2 = createTree(false) + PopupHandler.installPopupHandler( + tree2, + group, + ActionPlaces.CALL_HIERARCHY_VIEW_POPUP, + ActionManager.getInstance() + ) baseOnThisMethodAction.registerCustomShortcutSet( - ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).getShortcutSet(), tree2 - ); - type2TreeMap.put(CALLER_TYPE, tree2); + ActionManager.getInstance().getAction(IdeActions.ACTION_CALL_HIERARCHY).shortcutSet, + tree2 + ) + type2TreeMap[CALLER_TYPE] = tree2 } - private static PsiElement getTargetElement(@NotNull HierarchyNodeDescriptor descriptor) { - if (descriptor instanceof KotlinCallHierarchyNodeDescriptor) { - return descriptor.getPsiElement(); + override fun getElementFromDescriptor(descriptor: HierarchyNodeDescriptor): PsiElement? { + return getTargetElement(descriptor) + } + + override fun isApplicableElement(element: PsiElement): Boolean { + return if (element is PsiClass) false else isCallHierarchyElement(element) // PsiClass is not allowed at the hierarchy root + } + + override fun createHierarchyTreeStructure( + typeName: String, + psiElement: PsiElement + ): HierarchyTreeStructure? { + if (psiElement !is KtElement) return null + if (typeName == CALLER_TYPE) { + return KotlinCallerTreeStructure(psiElement, currentScopeType) } - return null; + return if (typeName == CALLEE_TYPE) { + KotlinCalleeTreeStructure(psiElement, currentScopeType) + } else null } - @Override - protected PsiElement getElementFromDescriptor(@NotNull HierarchyNodeDescriptor descriptor) { - return getTargetElement(descriptor); + override fun getComparator(): Comparator> { + return JavaHierarchyUtil.getComparator(myProject) } - @Override - protected boolean isApplicableElement(@NotNull PsiElement element) { - if (element instanceof PsiClass) return false; // PsiClass is not allowed at the hierarchy root - return CallHierarchyUtilsKt.isCallHierarchyElement(element); - } - - @Override - protected HierarchyTreeStructure createHierarchyTreeStructure(@NotNull String typeName, @NotNull PsiElement psiElement) { - if (!(psiElement instanceof KtElement)) return null; - - if (typeName.equals(CALLER_TYPE)) { - return new KotlinCallerTreeStructure((KtElement) psiElement, getCurrentScopeType()); + companion object { + private fun getTargetElement(descriptor: HierarchyNodeDescriptor): PsiElement? { + return (descriptor as? KotlinCallHierarchyNodeDescriptor)?.psiElement } - - if (typeName.equals(CALLEE_TYPE)) { - return new KotlinCalleeTreeStructure((KtElement) psiElement, getCurrentScopeType()); - } - - return null; } - - @Override - protected Comparator getComparator() { - return JavaHierarchyUtil.getComparator(myProject); - } -} +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.kt b/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.kt index 1d149b12133..b1b61c38d0f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/hierarchy/calls/KotlinCallHierarchyNodeDescriptor.kt @@ -13,221 +13,191 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package org.jetbrains.kotlin.idea.hierarchy.calls -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 +import com.intellij.openapi.util.Comparing +import com.intellij.openapi.util.Iconable +import com.intellij.openapi.util.text.StringUtil +import com.intellij.pom.Navigatable +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReference +import com.intellij.ui.LayeredIcon +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import java.awt.Font +import java.util.* -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; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.pom.Navigatable; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.ui.LayeredIcon; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.renderer.DescriptorRenderer; -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; - -import javax.swing.*; -import java.awt.*; -import java.util.HashSet; -import java.util.Set; - -public class KotlinCallHierarchyNodeDescriptor extends HierarchyNodeDescriptor implements Navigatable { - private int usageCount = 1; - private final Set references = new HashSet<>(); - private final CallHierarchyNodeDescriptor javaDelegate; - - public KotlinCallHierarchyNodeDescriptor( - @Nullable HierarchyNodeDescriptor parentDescriptor, - @NotNull KtElement element, - boolean isBase, - boolean navigateToReference) { - super(element.getProject(), parentDescriptor, element, isBase); - this.javaDelegate = new CallHierarchyNodeDescriptor(myProject, null, element, isBase, navigateToReference); +class KotlinCallHierarchyNodeDescriptor( + parentDescriptor: HierarchyNodeDescriptor?, + element: KtElement, + isBase: Boolean, + navigateToReference: Boolean +) : HierarchyNodeDescriptor(element.project, parentDescriptor, element, isBase), + Navigatable { + private var usageCount = 1 + private val references: MutableSet = + HashSet() + private val javaDelegate: CallHierarchyNodeDescriptor + fun incrementUsageCount() { + usageCount++ + javaDelegate.incrementUsageCount() } - public final void incrementUsageCount() { - usageCount++; - javaDelegate.incrementUsageCount(); + fun addReference(reference: PsiReference) { + references.add(reference) + javaDelegate.addReference(reference) } - public final void addReference(PsiReference reference) { - references.add(reference); - javaDelegate.addReference(reference); + override fun isValid(): Boolean { + val myElement = psiElement + return myElement != null && myElement.isValid } - @Override - public final boolean isValid(){ - //noinspection ConstantConditions - PsiElement myElement = getPsiElement(); - return myElement != null && myElement.isValid(); - } - - @Override - public final boolean update(){ - CompositeAppearance oldText = myHighlightedText; - Icon oldIcon = getIcon(); - - int flags = Iconable.ICON_FLAG_VISIBILITY; - if (isMarkReadOnly()) { - flags |= Iconable.ICON_FLAG_READ_STATUS; + override fun update(): Boolean { + val oldText = myHighlightedText + val oldIcon = icon + var flags = Iconable.ICON_FLAG_VISIBILITY + if (isMarkReadOnly) { + flags = flags or Iconable.ICON_FLAG_READ_STATUS } - - boolean changes = super.update(); - - PsiElement targetElement = getPsiElement(); - String elementText = renderElement(targetElement); - + var changes = super.update() + val targetElement = psiElement + val elementText = renderElement(targetElement) if (elementText == null) { - String invalidPrefix = IdeBundle.message("node.hierarchy.invalid"); - if (!myHighlightedText.getText().startsWith(invalidPrefix)) { - myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes()); + val invalidPrefix = IdeBundle.message("node.hierarchy.invalid") + if (!myHighlightedText.text.startsWith(invalidPrefix)) { + myHighlightedText.beginning + .addText(invalidPrefix, getInvalidPrefixAttributes()) } - return true; + return true } - - Icon newIcon = targetElement.getIcon(flags); + var newIcon = targetElement!!.getIcon(flags) if (changes && myIsBase) { - LayeredIcon icon = new LayeredIcon(2); - icon.setIcon(newIcon, 0); - icon.setIcon(AllIcons.General.Modified, 1, -AllIcons.General.Modified.getIconWidth() / 2, 0); - newIcon = icon; + val icon = LayeredIcon(2) + icon.setIcon(newIcon, 0) + icon.setIcon(AllIcons.General.Modified, 1, -AllIcons.General.Modified.iconWidth / 2, 0) + newIcon = icon } - setIcon(newIcon); - - myHighlightedText = new CompositeAppearance(); - TextAttributes mainTextAttributes = null; + icon = newIcon + myHighlightedText = CompositeAppearance() + var mainTextAttributes: TextAttributes? = null if (myColor != null) { - mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN); + mainTextAttributes = TextAttributes(myColor, null, null, null, Font.PLAIN) } - - String packageName = KtPsiUtil.getPackageName((KtElement) targetElement); - - myHighlightedText.getEnding().addText(elementText, mainTextAttributes); - + var packageName = + KtPsiUtil.getPackageName((targetElement as KtElement?)!!) + myHighlightedText.ending.addText(elementText, mainTextAttributes) if (usageCount > 1) { - myHighlightedText.getEnding().addText( - IdeBundle.message("node.call.hierarchy.N.usages", usageCount), - HierarchyNodeDescriptor.getUsageCountPrefixAttributes() - ); + myHighlightedText.ending.addText( + IdeBundle.message("node.call.hierarchy.N.usages", usageCount), + getUsageCountPrefixAttributes() + ) } - if (packageName == null) { - packageName = ""; + packageName = "" } - myHighlightedText.getEnding().addText(" (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes()); - - myName = myHighlightedText.getText(); - - if (!(Comparing.equal(myHighlightedText, oldText) && Comparing.equal(getIcon(), oldIcon))) { - changes = true; + myHighlightedText.ending + .addText(" ($packageName)", getPackageNameAttributes()) + myName = myHighlightedText.text + if (!(Comparing.equal(myHighlightedText, oldText) && Comparing.equal(icon, oldIcon)) + ) { + changes = true } - return changes; + return changes } - @Nullable - private static String renderElement(@Nullable PsiElement element) { - if (element instanceof KtFile) { - return ((KtFile) element).getName(); - } + override fun navigate(requestFocus: Boolean) { + javaDelegate.navigate(requestFocus) + } - if (!(element instanceof KtNamedDeclaration)) { - return null; - } + override fun canNavigate(): Boolean { + return javaDelegate.canNavigate() + } - DeclarationDescriptor descriptor = ResolutionUtils.resolveToDescriptorIfAny((KtNamedDeclaration) element, BodyResolveMode.PARTIAL); - if (descriptor == null) return null; + override fun canNavigateToSource(): Boolean { + return javaDelegate.canNavigateToSource() + } - String elementText; - if (element instanceof KtClassOrObject) { - if (element instanceof KtObjectDeclaration && ((KtObjectDeclaration) element).isCompanion()) { - descriptor = descriptor.getContainingDeclaration(); - if (!(descriptor instanceof ClassDescriptor)) return null; - - elementText = renderClassOrObject((ClassDescriptor) descriptor); + companion object { + private fun renderElement(element: PsiElement?): String? { + if (element is KtFile) { + return element.name } - else if (element instanceof KtEnumEntry) { - elementText = ((KtEnumEntry) element).getName(); + if (element !is KtNamedDeclaration) { + return null } - else { - if (((KtClassOrObject) element).getName() != null) { - elementText = renderClassOrObject((ClassDescriptor) descriptor); + var descriptor: DeclarationDescriptor? = + element as KtNamedDeclaration?. resolveToDescriptorIfAny BodyResolveMode.PARTIAL + ?: return null + val elementText: String? + if (element is KtClassOrObject) { + if (element is KtObjectDeclaration && element.isCompanion()) { + descriptor = descriptor.containingDeclaration + if (descriptor !is ClassDescriptor) return null + elementText = renderClassOrObject(descriptor) + } else if (element is KtEnumEntry) { + elementText = element.name + } else { + elementText = if (element.name != null) { + renderClassOrObject(descriptor as ClassDescriptor) + } else { + "[anonymous]" + } } - else { - elementText = "[anonymous]"; + } else if (element is KtNamedFunction || element is KtConstructor<*>) { + if (descriptor !is FunctionDescriptor) return null + elementText = renderNamedFunction(descriptor) + } else if (element is KtProperty) { + elementText = element.name + } else return null + if (elementText == null) return null + var containerText: String? = null + var containerDescriptor = descriptor.containingDeclaration + while (containerDescriptor != null) { + if (containerDescriptor is PackageFragmentDescriptor || containerDescriptor is ModuleDescriptor) { + break } + val name = containerDescriptor.name + if (!name.isSpecial) { + val identifier = name.identifier + containerText = if (containerText != null) "$identifier.$containerText" else identifier + } + containerDescriptor = containerDescriptor.containingDeclaration } - } - else if ((element instanceof KtNamedFunction || element instanceof KtConstructor)) { - if (!(descriptor instanceof FunctionDescriptor)) return null; - elementText = renderNamedFunction((FunctionDescriptor) descriptor); - } - else if (element instanceof KtProperty) { - elementText = ((KtProperty) element).getName(); - } - else return null; - - if (elementText == null) return null; - - String containerText = null; - DeclarationDescriptor containerDescriptor = descriptor.getContainingDeclaration(); - while (containerDescriptor != null) { - if (containerDescriptor instanceof PackageFragmentDescriptor || containerDescriptor instanceof ModuleDescriptor) { - break; - } - - Name name = containerDescriptor.getName(); - if (!name.isSpecial()) { - String identifier = name.getIdentifier(); - containerText = containerText != null ? identifier + "." + containerText : identifier; - } - - containerDescriptor = containerDescriptor.getContainingDeclaration(); + return if (containerText != null) "$containerText.$elementText" else elementText } - return containerText != null ? containerText + "." + elementText : elementText; -} + fun renderNamedFunction(descriptor: FunctionDescriptor): String { + val descriptorForName: DeclarationDescriptor = + (descriptor as? ConstructorDescriptor)?.containingDeclaration ?: descriptor + val name = descriptorForName.name.asString() + val paramTypes = + StringUtil.join( + descriptor.valueParameters, + { descriptor1: ValueParameterDescriptor -> + DescriptorRenderer + .SHORT_NAMES_IN_TYPES + .renderType(descriptor1.type) + }, + ", " + ) + return "$name($paramTypes)" + } - public static String renderNamedFunction(@NotNull FunctionDescriptor descriptor) { - DeclarationDescriptor descriptorForName = descriptor instanceof ConstructorDescriptor - ? descriptor.getContainingDeclaration() - : descriptor; - String name = descriptorForName.getName().asString(); - String paramTypes = StringUtil.join( - descriptor.getValueParameters(), - descriptor1 -> DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor1.getType()), - ", " - ); - return name + "(" + paramTypes + ")"; + private fun renderClassOrObject(descriptor: ClassDescriptor): String { + return descriptor.name.asString() + } } - private static String renderClassOrObject(ClassDescriptor descriptor) { - return descriptor.getName().asString(); + init { + javaDelegate = CallHierarchyNodeDescriptor(myProject, null, element, isBase, navigateToReference) } - - @Override - public void navigate(boolean requestFocus) { - javaDelegate.navigate(requestFocus); - } - - @Override - public boolean canNavigate() { - return javaDelegate.canNavigate(); - } - - @Override - public boolean canNavigateToSource() { - return javaDelegate.canNavigateToSource(); - } -} +} \ No newline at end of file