Override/Implement: Implement JavaDoc/KDoc copying
#KT-8682 Fixed #KT-12735 Fixed (cherry picked from commit f4486be)
This commit is contained in:
@@ -349,11 +349,13 @@
|
|||||||
- [`KT-11704`](https://youtrack.jetbrains.com/issue/KT-11704) Support file path references inside of Kotlin string literals
|
- [`KT-11704`](https://youtrack.jetbrains.com/issue/KT-11704) Support file path references inside of Kotlin string literals
|
||||||
- [`KT-12076`](https://youtrack.jetbrains.com/issue/KT-12076) Kotlin Plugin update check: alwats display installed version number
|
- [`KT-12076`](https://youtrack.jetbrains.com/issue/KT-12076) Kotlin Plugin update check: alwats display installed version number
|
||||||
- [`KT-11814`](https://youtrack.jetbrains.com/issue/KT-11814) New icon for kotlin annotation classes
|
- [`KT-11814`](https://youtrack.jetbrains.com/issue/KT-11814) New icon for kotlin annotation classes
|
||||||
|
- [`KT-12735`](https://youtrack.jetbrains.com/issue/KT-12735) Convert JavaDoc to KDoc when overriding Java class member in Kotlin
|
||||||
|
|
||||||
###### Issues fixed
|
###### Issues fixed
|
||||||
|
|
||||||
- [`KT-5960`](https://youtrack.jetbrains.com/issue/KT-5960) Can't find usages for Java methods used from Kotlin by call convention
|
- [`KT-5960`](https://youtrack.jetbrains.com/issue/KT-5960) Can't find usages for Java methods used from Kotlin by call convention
|
||||||
- [`KT-8362`](https://youtrack.jetbrains.com/issue/KT-8362) "New Kotlin file": Keywords should be escaped in package name
|
- [`KT-8362`](https://youtrack.jetbrains.com/issue/KT-8362) "New Kotlin file": Keywords should be escaped in package name
|
||||||
|
- [`KT-8682`](https://youtrack.jetbrains.com/issue/KT-8682) Respect "Copy JavaDoc" option in the "Override/Implement Members..." dialog
|
||||||
- [`KT-8817`](https://youtrack.jetbrains.com/issue/KT-8817) Fixed rename of Java getters/setters through synthetic property references in Kotlin
|
- [`KT-8817`](https://youtrack.jetbrains.com/issue/KT-8817) Fixed rename of Java getters/setters through synthetic property references in Kotlin
|
||||||
- [`KT-9399`](https://youtrack.jetbrains.com/issue/KT-9399) Find Usages omits Kotlin annotation parameter usage in Java source
|
- [`KT-9399`](https://youtrack.jetbrains.com/issue/KT-9399) Find Usages omits Kotlin annotation parameter usage in Java source
|
||||||
- [`KT-9797`](https://youtrack.jetbrains.com/issue/KT-9797) "Kotlin Bytecode" toolwindow breaks after closing
|
- [`KT-9797`](https://youtrack.jetbrains.com/issue/KT-9797) "Kotlin Bytecode" toolwindow breaks after closing
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ class OverridesCompletion(
|
|||||||
// keep original modifiers
|
// keep original modifiers
|
||||||
val modifierList = KtPsiFactory(context.project).createModifierList(dummyMember.modifierList!!.text)
|
val modifierList = KtPsiFactory(context.project).createModifierList(dummyMember.modifierList!!.text)
|
||||||
|
|
||||||
val prototype = memberObject.generateMember(context.project)
|
val prototype = memberObject.generateMember(context.project, false)
|
||||||
prototype.modifierList!!.replace(modifierList)
|
prototype.modifierList!!.replace(modifierList)
|
||||||
val insertedMember = dummyMember.replaced(prototype)
|
val insertedMember = dummyMember.replaced(prototype)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<orderEntry type="module" module-name="light-classes" />
|
<orderEntry type="module" module-name="light-classes" />
|
||||||
<orderEntry type="module" module-name="frontend.java" />
|
<orderEntry type="module" module-name="frontend.java" />
|
||||||
<orderEntry type="module" module-name="util" />
|
<orderEntry type="module" module-name="util" />
|
||||||
|
<orderEntry type="module" module-name="j2k" />
|
||||||
<orderEntry type="library" scope="PROVIDED" name="gradle-and-groovy-plugin" level="project" />
|
<orderEntry type="library" scope="PROVIDED" name="gradle-and-groovy-plugin" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
+15
-6
@@ -72,18 +72,22 @@ abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandle
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedElements = if (implementAll) {
|
val copyDoc: Boolean
|
||||||
members
|
val selectedElements: Collection<OverrideMemberChooserObject>
|
||||||
|
if (implementAll) {
|
||||||
|
selectedElements = members
|
||||||
|
copyDoc = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val chooser = showOverrideImplementChooser(project, members.toTypedArray()) ?: return
|
val chooser = showOverrideImplementChooser(project, members.toTypedArray()) ?: return
|
||||||
chooser.selectedElements ?: return
|
selectedElements = chooser.selectedElements ?: return
|
||||||
|
copyDoc = chooser.isCopyJavadoc
|
||||||
}
|
}
|
||||||
if (selectedElements.isEmpty()) return
|
if (selectedElements.isEmpty()) return
|
||||||
|
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
|
|
||||||
generateMembers(editor, classOrObject, selectedElements)
|
generateMembers(editor, classOrObject, selectedElements, copyDoc)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||||
@@ -93,9 +97,14 @@ abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandle
|
|||||||
override fun startInWriteAction(): Boolean = false
|
override fun startInWriteAction(): Boolean = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun generateMembers(editor: Editor?, classOrObject: KtClassOrObject, selectedElements: Collection<OverrideMemberChooserObject>) {
|
fun generateMembers(
|
||||||
|
editor: Editor?,
|
||||||
|
classOrObject: KtClassOrObject,
|
||||||
|
selectedElements: Collection<OverrideMemberChooserObject>,
|
||||||
|
copyDoc: Boolean
|
||||||
|
) {
|
||||||
val project = classOrObject.project
|
val project = classOrObject.project
|
||||||
insertMembersAfter(editor, classOrObject, selectedElements.map { it.generateMember(project) })
|
insertMembersAfter(editor, classOrObject, selectedElements.map { it.generateMember(project, copyDoc) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-2
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.generation.ClassMember
|
|||||||
import com.intellij.codeInsight.generation.MemberChooserObject
|
import com.intellij.codeInsight.generation.MemberChooserObject
|
||||||
import com.intellij.codeInsight.generation.MemberChooserObjectBase
|
import com.intellij.codeInsight.generation.MemberChooserObjectBase
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiDocCommentOwner
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -27,8 +28,11 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
|||||||
import org.jetbrains.kotlin.idea.core.TemplateKind
|
import org.jetbrains.kotlin.idea.core.TemplateKind
|
||||||
import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate
|
import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate
|
||||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||||
|
import org.jetbrains.kotlin.idea.j2k.IdeaDocCommentConverter
|
||||||
|
import org.jetbrains.kotlin.idea.kdoc.KDocElementFactory
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.findDocComment.findDocComment
|
||||||
import org.jetbrains.kotlin.renderer.*
|
import org.jetbrains.kotlin.renderer.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
||||||
|
|
||||||
@@ -88,15 +92,33 @@ interface OverrideMemberChooserObject : ClassMember {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun OverrideMemberChooserObject.generateMember(project: Project): KtCallableDeclaration {
|
fun OverrideMemberChooserObject.generateMember(project: Project, copyDoc: Boolean): KtCallableDeclaration {
|
||||||
val descriptor = immediateSuper
|
val descriptor = immediateSuper
|
||||||
if (preferConstructorParameter && descriptor is PropertyDescriptor) return generateConstructorParameter(project, descriptor)
|
if (preferConstructorParameter && descriptor is PropertyDescriptor) return generateConstructorParameter(project, descriptor)
|
||||||
|
|
||||||
return when (descriptor) {
|
val newMember: KtCallableDeclaration = when (descriptor) {
|
||||||
is SimpleFunctionDescriptor -> generateFunction(project, descriptor, bodyType)
|
is SimpleFunctionDescriptor -> generateFunction(project, descriptor, bodyType)
|
||||||
is PropertyDescriptor -> generateProperty(project, descriptor, bodyType)
|
is PropertyDescriptor -> generateProperty(project, descriptor, bodyType)
|
||||||
else -> error("Unknown member to override: $descriptor")
|
else -> error("Unknown member to override: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (copyDoc) {
|
||||||
|
val superDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor)
|
||||||
|
val kDoc = when (superDeclaration) {
|
||||||
|
is KtDeclaration ->
|
||||||
|
findDocComment(superDeclaration)
|
||||||
|
is PsiDocCommentOwner -> {
|
||||||
|
val kDocText = superDeclaration.docComment?.let { IdeaDocCommentConverter.convertDocComment(it) }
|
||||||
|
if (kDocText.isNullOrEmpty()) null else KDocElementFactory(project).createKDocFromText(kDocText!!)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
if (kDoc != null) {
|
||||||
|
newMember.addAfter(kDoc, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMember
|
||||||
}
|
}
|
||||||
|
|
||||||
private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
|
private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
|
||||||
|
|||||||
@@ -78,5 +78,5 @@ fun confirmMemberRewrite(targetClass: KtClass, vararg descriptors: FunctionDescr
|
|||||||
fun generateFunctionSkeleton(descriptor: FunctionDescriptor, project: Project): KtNamedFunction {
|
fun generateFunctionSkeleton(descriptor: FunctionDescriptor, project: Project): KtNamedFunction {
|
||||||
return OverrideMemberChooserObject
|
return OverrideMemberChooserObject
|
||||||
.create(project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY)
|
.create(project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY)
|
||||||
.generateMember(project) as KtNamedFunction
|
.generateMember(project, false) as KtNamedFunction
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ abstract class ImplementAbstractMemberIntentionBase :
|
|||||||
descriptorToImplement,
|
descriptorToImplement,
|
||||||
OverrideMemberChooserObject.BodyType.EMPTY,
|
OverrideMemberChooserObject.BodyType.EMPTY,
|
||||||
preferConstructorParameters)
|
preferConstructorParameters)
|
||||||
OverrideImplementMembersHandler.generateMembers(null, targetClass, chooserObject.singletonList())
|
OverrideImplementMembersHandler.generateMembers(null, targetClass, chooserObject.singletonList(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun implementInJavaClass(member: KtNamedDeclaration, targetClass: PsiClass) {
|
private fun implementInJavaClass(member: KtNamedDeclaration, targetClass: PsiClass) {
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package foo;
|
||||||
|
|
||||||
|
public class A {
|
||||||
|
/**
|
||||||
|
* @return TEST
|
||||||
|
*/
|
||||||
|
public int foo() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// COPY_DOC
|
||||||
|
|
||||||
|
import foo.A
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// COPY_DOC
|
||||||
|
|
||||||
|
import foo.A
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
/**
|
||||||
|
* @return TEST
|
||||||
|
*/
|
||||||
|
override fun foo(): Int {
|
||||||
|
<selection><caret>return super.foo()</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// COPY_DOC
|
||||||
|
abstract class A {
|
||||||
|
/**
|
||||||
|
* @see TEST
|
||||||
|
*/
|
||||||
|
abstract fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// COPY_DOC
|
||||||
|
abstract class A {
|
||||||
|
/**
|
||||||
|
* @see TEST
|
||||||
|
*/
|
||||||
|
abstract fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
/**
|
||||||
|
* @see TEST
|
||||||
|
*/
|
||||||
|
override fun foo() {
|
||||||
|
<selection><caret>throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.</selection>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.idea.test.dumpTextWithErrors
|
|||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.TagsTestDataUtil
|
import org.jetbrains.kotlin.test.TagsTestDataUtil
|
||||||
import org.jetbrains.kotlin.utils.rethrow
|
import org.jetbrains.kotlin.utils.rethrow
|
||||||
@@ -171,8 +172,9 @@ abstract class AbstractOverrideImplementTest : KotlinLightCodeInsightFixtureTest
|
|||||||
classOrObject: KtClassOrObject,
|
classOrObject: KtClassOrObject,
|
||||||
selectedElements: List<OverrideMemberChooserObject>) {
|
selectedElements: List<OverrideMemberChooserObject>) {
|
||||||
try {
|
try {
|
||||||
|
val copyDoc = InTextDirectivesUtils.isDirectiveDefined(classOrObject.containingFile.text, "// COPY_DOC")
|
||||||
myFixture.project.executeWriteCommand("") {
|
myFixture.project.executeWriteCommand("") {
|
||||||
OverrideImplementMembersHandler.generateMembers(myFixture.editor, classOrObject, selectedElements)
|
OverrideImplementMembersHandler.generateMembers(myFixture.editor, classOrObject, selectedElements, copyDoc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (throwable: Throwable) {
|
catch (throwable: Throwable) {
|
||||||
|
|||||||
@@ -235,4 +235,12 @@ class OverrideImplementTest : AbstractOverrideImplementTest() {
|
|||||||
fun testEqualsInInterface() {
|
fun testEqualsInInterface() {
|
||||||
doOverrideFileTest("equals")
|
doOverrideFileTest("equals")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testCopyKDoc() {
|
||||||
|
doOverrideFileTest("foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testConvertJavaDoc() {
|
||||||
|
doOverrideDirectoryTest("foo")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user