diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt index a778b911861..b17c9a20bb7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/JavaResolveExtension.kt @@ -29,6 +29,15 @@ import org.jetbrains.kotlin.resolve.jvm.resolveMethod import org.jetbrains.kotlin.load.java.structure.impl.JavaMethodImpl import org.jetbrains.kotlin.load.java.structure.impl.JavaConstructorImpl import org.jetbrains.kotlin.resolve.jvm.resolveConstructor +import com.intellij.psi.PsiClass +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl +import com.intellij.psi.PsiField +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.resolve.jvm.resolveField +import org.jetbrains.kotlin.load.java.structure.impl.JavaFieldImpl +import com.intellij.psi.PsiMember +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor public object JavaResolveExtension : CacheExtension<(PsiElement) -> Pair> { override val platform: TargetPlatform = TargetPlatform.JVM @@ -48,8 +57,6 @@ public object JavaResolveExtension : CacheExtension<(PsiElement) -> Pair resolver.resolveConstructor(JavaConstructorImpl(this)) @@ -59,3 +66,28 @@ fun PsiMethod.getJavaMethodDescriptor(): FunctionDescriptor { return methodDescriptor!! } + +fun PsiClass.getJavaClassDescriptor(): ClassDescriptor { + val resolver = JavaResolveExtension.getResolver(getProject(), this) + val classDescriptor = resolver.resolveClass(JavaClassImpl(this)) + assert(classDescriptor != null) { "No descriptor found for " + getText() } + + return classDescriptor!! +} + +fun PsiField.getJavaFieldDescriptor(): PropertyDescriptor { + val resolver = JavaResolveExtension.getResolver(getProject(), this) + val fieldDescriptor = resolver.resolveField(JavaFieldImpl(this)) + assert(fieldDescriptor != null) { "No descriptor found for " + getText() } + + return fieldDescriptor!! +} + +fun PsiMember.getJavaMemberDescriptor(): DeclarationDescriptor? { + return when (this) { + is PsiClass -> getJavaClassDescriptor() + is PsiMethod -> getJavaMethodDescriptor() + is PsiField -> getJavaFieldDescriptor() + else -> null + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt index 5c0f0ffe50b..0cc405bbd97 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt @@ -31,6 +31,8 @@ import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import java.util.HashSet import org.jetbrains.kotlin.psi.JetElement +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement public class CreateCallableFromUsageFix( originalExpression: JetExpression, @@ -71,11 +73,11 @@ public class CreateCallableFromUsageFix( val popupTitle = JetBundle.message("choose.target.class.or.trait.title") val receiverTypeCandidates = callableBuilder.computeTypeCandidates(callableInfo.receiverTypeInfo) if (receiverTypeCandidates.isNotEmpty()) { - // TODO: Support generation of Java class members val containers = receiverTypeCandidates .map { candidate -> val descriptor = candidate.theType.getConstructor().getDeclarationDescriptor() - (DescriptorToDeclarationUtil.getDeclaration(file, descriptor) as? JetClassOrObject)?.let { candidate to it } + val declaration = DescriptorToDeclarationUtil.getDeclaration(file, descriptor) + if (declaration is JetClassOrObject || declaration is PsiClass) candidate to declaration else null } .filterNotNull() diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt index 62d5d13cc34..7971059ddcf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/jetRefactoringUtil.kt @@ -73,6 +73,8 @@ import com.intellij.psi.PsiPackage import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.psiUtil.parents import com.intellij.refactoring.util.RefactoringUIUtil +import com.intellij.psi.PsiMember +import org.jetbrains.kotlin.idea.caches.resolve.getJavaMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind import org.jetbrains.kotlin.resolve.OverridingUtil @@ -299,13 +301,13 @@ public fun chooseContainerElement( editor: Editor, title: String, highlightSelection: Boolean, - toPsi: (T) -> JetElement, + toPsi: (T) -> PsiElement, onSelect: (T) -> Unit) { return getPsiElementPopup( editor, containers, - object : PsiElementListCellRenderer() { - private fun JetElement.renderName(): String { + object : PsiElementListCellRenderer() { + private fun PsiElement.renderName(): String { if (this is JetPropertyAccessor) { return (getParent() as JetProperty).renderName() + if (isGetter()) ".get" else ".set" } @@ -315,9 +317,13 @@ public fun chooseContainerElement( return (this as? PsiNamedElement)?.getName() ?: "" } - private fun JetElement.renderDeclaration(): String? { + private fun PsiElement.renderDeclaration(): String? { + val descriptor = when { + this is JetElement -> analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] + this is PsiMember -> getJavaMemberDescriptor() + else -> null + } ?: return null val name = renderName() - val descriptor = this.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] val params = (descriptor as? FunctionDescriptor)?.let { descriptor -> descriptor.getValueParameters() .map { DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(it.getType()) } @@ -326,11 +332,11 @@ public fun chooseContainerElement( return "$name$params" } - private fun JetElement.renderText(): String { + private fun PsiElement.renderText(): String { return StringUtil.shortenTextWithEllipsis(getText()!!.collapseSpaces(), 53, 0) } - private fun JetElement.getRepresentativeElement(): JetElement { + private fun PsiElement.getRepresentativeElement(): PsiElement { return when (this) { is JetBlockExpression -> (getParent() as? JetDeclarationWithBody) ?: this is JetClassBody -> getParent() as JetClassOrObject @@ -338,20 +344,17 @@ public fun chooseContainerElement( } } - override fun getElementText(element: JetElement): String? { + override fun getElementText(element: PsiElement): String? { val representativeElement = element.getRepresentativeElement() - return when (representativeElement) { - is JetFile, is JetDeclarationWithBody, is JetClassOrObject -> representativeElement.renderDeclaration() - else -> representativeElement.renderText() - } + return representativeElement.renderDeclaration() ?: representativeElement.renderText() } - override fun getContainerText(element: JetElement?, name: String?): String? = null + override fun getContainerText(element: PsiElement, name: String?): String? = null override fun getIconFlags(): Int = 0 - override fun getIcon(element: PsiElement?): Icon? = - super.getIcon((element as? JetElement)?.getRepresentativeElement()) + override fun getIcon(element: PsiElement): Icon? = + super.getIcon(element.getRepresentativeElement()) }, title, highlightSelection, @@ -368,7 +371,7 @@ public fun chooseContainerElementIfNecessary( editor: Editor, title: String, highlightSelection: Boolean, - toPsi: (T) -> JetElement, + toPsi: (T) -> PsiElement, onSelect: (T) -> Unit ) { when { diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt index e9f351e5688..a27b75fcf3d 100644 --- a/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt @@ -5,6 +5,6 @@ fun test(): Int { return A().foo(1, "2") } -fun Any.foo(i: Int, s: String): Int { +fun A.foo(i: Int, s: String): Int { throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. }