diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.181 b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.181 new file mode 100644 index 00000000000..efffa97e036 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.181 @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2015 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.kotlin.idea.refactoring.changeSignature.ui + +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClassOwner +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiReference +import com.intellij.psi.search.searches.MethodReferencesSearch +import com.intellij.psi.search.searches.ReferencesSearch +import com.intellij.refactoring.changeSignature.CallerChooserBase +import com.intellij.refactoring.changeSignature.MethodNodeBase +import com.intellij.ui.ColoredTreeCellRenderer +import com.intellij.ui.JBColor +import com.intellij.ui.SimpleTextAttributes +import com.intellij.ui.treeStructure.Tree +import com.intellij.util.Consumer +import com.intellij.util.ui.UIUtil +import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod +import org.jetbrains.kotlin.asJava.namedUnwrappedElement +import org.jetbrains.kotlin.asJava.toLightMethods +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor +import org.jetbrains.kotlin.idea.hierarchy.calls.CalleeReferenceProcessor +import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallHierarchyNodeDescriptor +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import java.util.* + +class KotlinCallerChooser( + declaration: PsiElement, + project: Project, + title: String, + previousTree: Tree?, + callback: Consumer> +): CallerChooserBase(declaration, project, title, previousTree, "dummy." + KotlinFileType.EXTENSION, callback) { + + override fun findDeepestSuperMethods(method: PsiElement) = + method.toLightMethods().singleOrNull()?.findDeepestSuperMethods() + + override fun getEmptyCallerText() = + "Caller text \nwith highlighted callee call would be shown here" + + override fun getEmptyCalleeText() = + "Callee text would be shown here" +} + +class KotlinMethodNode( + method: PsiElement?, + called: HashSet, + project: Project, + cancelCallback: Runnable +): MethodNodeBase(method?.namedUnwrappedElement ?: method, called, project, cancelCallback) { + override fun createNode(caller: PsiElement, called: HashSet) = + KotlinMethodNode(caller, called, myProject, myCancelCallback) + + override fun customizeRendererText(renderer: ColoredTreeCellRenderer) { + val descriptor = when (myMethod) { + is KtFunction -> myMethod.unsafeResolveToDescriptor() as FunctionDescriptor + is KtClass -> (myMethod.unsafeResolveToDescriptor() as ClassDescriptor).unsubstitutedPrimaryConstructor ?: return + is PsiMethod -> myMethod.getJavaMethodDescriptor() ?: return + else -> throw AssertionError("Invalid declaration: ${myMethod.getElementTextWithContext()}") + } + val containerName = generateSequence(descriptor) { it.containingDeclaration } + .firstOrNull { it is ClassDescriptor } + ?.name + + val renderedFunction = KotlinCallHierarchyNodeDescriptor.renderNamedFunction(descriptor) + val renderedFunctionWithContainer = + containerName?.let { + "${if (it.isSpecial) "[Anonymous]" else it.asString()}.$renderedFunction" + } ?: renderedFunction + + val attributes = if (isEnabled) + SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getTreeForeground()) + else + SimpleTextAttributes.EXCLUDED_ATTRIBUTES + renderer.append(renderedFunctionWithContainer, attributes) + + val packageName = (myMethod.containingFile as? PsiClassOwner)?.packageName ?: "" + renderer.append(" ($packageName)", SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, JBColor.GRAY)) + } + + override fun computeCallers(): List { + if (myMethod == null) return emptyList() + + val callers = LinkedHashSet() + + val processor = object: CalleeReferenceProcessor(false) { + override fun onAccept(ref: PsiReference, element: PsiElement) { + if ((element is KtFunction || element is KtClass || element is PsiMethod) && element !in myCalled) { + callers.add(element) + } + } + } + val query = myMethod.getRepresentativeLightMethod()?.let { MethodReferencesSearch.search(it, it.useScope, true) } + ?: ReferencesSearch.search(myMethod, myMethod.useScope) + query.forEach { processor.process(it) } + return callers.toList() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.181 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.181 new file mode 100644 index 00000000000..16965b54536 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.181 @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 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.kotlin.idea.refactoring.move.moveClassesOrPackages + +import com.intellij.psi.PsiDirectory +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiPackage +import com.intellij.refactoring.MoveDestination +import com.intellij.refactoring.move.MoveCallback +import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesToNewDirectoryDialog + +class KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog( + directory: PsiDirectory, + elementsToMove: Array, + moveCallback: MoveCallback? +) : MoveClassesOrPackagesToNewDirectoryDialog(directory, elementsToMove, moveCallback) { + override fun createDestination(aPackage: PsiPackage, directory: PsiDirectory): MoveDestination? { + val delegate = super.createDestination(aPackage, directory) ?: return null + return KotlinAwareDelegatingMoveDestination(delegate, aPackage, directory) + } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 b/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 index 2043926a82c..04a17e99aff 100644 --- a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 +++ b/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.181 @@ -7,10 +7,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.utils.addToStdlib.assertedCast -import org.jetbrains.uast.JvmDeclarationUElement -import org.jetbrains.uast.UDeclaration -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UFile +import org.jetbrains.uast.* import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin import org.jetbrains.uast.test.common.RenderLogTestBase @@ -104,7 +101,7 @@ abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLog accept(object : UastVisitor { override fun visitElement(node: UElement): Boolean { - if (node is UDeclaration) {// visitDeclaration hasn't come yet + if (node is UAnchorOwner) { node.uastAnchor?.let { visitElement(it) } } diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 index 01425546af2..07db0b84610 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.181 @@ -219,9 +219,10 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { @Test fun testSimpleAnnotated() { doTest("SimpleAnnotated") { _, file -> - file.findElementByTextFromPsi("@SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field -> + file.findElementByTextFromPsi("@kotlin.SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field -> val annotation = field.annotations.assertedFind("kotlin.SinceKotlin") { it.qualifiedName } - Assert.assertEquals(annotation.findDeclaredAttributeValue("version")?.evaluateString(), "1.0") + Assert.assertEquals("1.0", annotation.findDeclaredAttributeValue("version")?.evaluateString()) + Assert.assertEquals("SinceKotlin", annotation.cast().uastAnchor?.sourcePsi?.text) } } }