Fix for KT-12892 J2K: Wrong placing of comments when constructor converted to primary constructor & init
This commit is contained in:
@@ -106,7 +106,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
}
|
||||
}
|
||||
|
||||
return ClassBody(null, null, convertedMembers.values.toList(), emptyList(), lBrace, rBrace, classKind)
|
||||
return ClassBody(null, null, null, convertedMembers.values.toList(), emptyList(), lBrace, rBrace, classKind)
|
||||
}
|
||||
|
||||
val useCompanionObject = shouldGenerateCompanionObject(convertedMembers)
|
||||
@@ -114,11 +114,13 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
val members = ArrayList<Member>()
|
||||
val companionObjectMembers = ArrayList<Member>()
|
||||
var primaryConstructorSignature: PrimaryConstructorSignature? = null
|
||||
var primaryConstructor: PrimaryConstructor? = null
|
||||
for ((psiMember, member) in convertedMembers) {
|
||||
if (member is PrimaryConstructor) {
|
||||
primaryConstructor = member
|
||||
assert(primaryConstructorSignature == null)
|
||||
primaryConstructorSignature = member.createSignature(converter)
|
||||
members.add(member.initializer())
|
||||
primaryConstructorSignature = primaryConstructor.createSignature(converter)
|
||||
members.add(primaryConstructor.initializer)
|
||||
}
|
||||
else if (useCompanionObject && member !is Class && psiMember !is PsiEnumConstant && psiMember.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
companionObjectMembers.add(member)
|
||||
@@ -131,7 +133,8 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryConstructorSignature != null
|
||||
if (primaryConstructor != null
|
||||
&& primaryConstructorSignature != null
|
||||
&& classKind != ClassKind.ANONYMOUS_OBJECT
|
||||
&& primaryConstructorSignature.annotations.isEmpty
|
||||
&& primaryConstructorSignature.accessModifier == null
|
||||
@@ -141,7 +144,7 @@ class ClassBodyConverter(private val psiClass: PsiClass,
|
||||
primaryConstructorSignature = null // no "()" after class name is needed in this case
|
||||
}
|
||||
|
||||
return ClassBody(primaryConstructorSignature, constructorConverter?.baseClassParams, members, companionObjectMembers, lBrace, rBrace, classKind)
|
||||
return ClassBody(primaryConstructor, primaryConstructorSignature, constructorConverter?.baseClassParams, members, companionObjectMembers, lBrace, rBrace, classKind)
|
||||
}
|
||||
|
||||
private fun convertMember(
|
||||
|
||||
@@ -175,7 +175,7 @@ class Converter private constructor(
|
||||
val implementsTypes = convertToNotNullableTypes(psiClass.implementsListTypes)
|
||||
val name = psiClass.declarationIdentifier()
|
||||
|
||||
return when {
|
||||
val converted = when {
|
||||
psiClass.isInterface -> {
|
||||
val classBody = ClassBodyConverter(psiClass, ClassKind.INTERFACE, this).convertBody()
|
||||
Interface(name, annotations, modifiers, typeParameters, extendsTypes, implementsTypes, classBody)
|
||||
@@ -208,6 +208,18 @@ class Converter private constructor(
|
||||
}
|
||||
}
|
||||
}.assignPrototype(psiClass)
|
||||
|
||||
if (converted.body.primaryConstructorSignature == null)
|
||||
addPostUnfoldDeferredElementsAction {
|
||||
val primaryConstructor = converted.body.primaryConstructor
|
||||
if (primaryConstructor != null) {
|
||||
if (primaryConstructor.initializer.isEmpty)
|
||||
converted.prototypes = converted.prototypes!! + primaryConstructor.prototypes!!
|
||||
else
|
||||
primaryConstructor.initializer.assignPrototypesFrom(primaryConstructor, CommentsAndSpacesInheritance.NO_SPACES)
|
||||
}
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
fun needOpenModifier(psiClass: PsiClass): Boolean {
|
||||
@@ -285,7 +297,7 @@ class Converter private constructor(
|
||||
|
||||
// to convert fields and nested types - they are not allowed in Kotlin but we convert them and let user refactor code
|
||||
var classBody = ClassBodyConverter(psiClass, ClassKind.ANNOTATION_CLASS, this).convertBody()
|
||||
classBody = ClassBody(constructorSignature, classBody.baseClassParams, classBody.members,
|
||||
classBody = ClassBody(null, constructorSignature, classBody.baseClassParams, classBody.members,
|
||||
classBody.companionObjectMembers, classBody.lBrace, classBody.rBrace, classBody.classKind)
|
||||
|
||||
return Class(psiClass.declarationIdentifier(),
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.j2k.append
|
||||
abstract class Member(var annotations: Annotations, val modifiers: Modifiers) : Element()
|
||||
|
||||
class ClassBody (
|
||||
val primaryConstructor: PrimaryConstructor?,
|
||||
val primaryConstructorSignature: PrimaryConstructorSignature?,
|
||||
val baseClassParams: List<DeferredElement<Expression>>?,
|
||||
val members: List<Member>,
|
||||
|
||||
@@ -39,10 +39,12 @@ class PrimaryConstructor(
|
||||
|
||||
override fun generateCode(builder: CodeBuilder) { throw IncorrectOperationException() }
|
||||
|
||||
fun initializer(): Initializer
|
||||
= Initializer(body!!, Modifiers.Empty).assignPrototypesFrom(this, CommentsAndSpacesInheritance(commentsBefore = false))
|
||||
// Should be lazy, to defer `assignPrototypesFrom(this,...)` a bit,
|
||||
// cause when `PrimaryConstructor` created prototypes not yet assigned
|
||||
val initializer: Initializer by
|
||||
lazy { Initializer(body, Modifiers.Empty).assignPrototypesFrom(this, CommentsAndSpacesInheritance(commentsBefore = false)) }
|
||||
|
||||
fun createSignature(converter: Converter): PrimaryConstructorSignature {
|
||||
fun createSignature(converter: Converter): PrimaryConstructorSignature? {
|
||||
val signature = PrimaryConstructorSignature(annotations, modifiers, parameterList)
|
||||
|
||||
// assign prototypes later because we don't know yet whether the body is empty or not
|
||||
|
||||
@@ -26,4 +26,24 @@ class B {
|
||||
} // end of constructor body
|
||||
|
||||
void foo(){}
|
||||
}
|
||||
|
||||
class CtorComment {
|
||||
public String myA;
|
||||
|
||||
/*
|
||||
* The magic of comments
|
||||
*/
|
||||
// single line magic comments
|
||||
public CtorComment() {
|
||||
myA = "a";
|
||||
}
|
||||
}
|
||||
|
||||
class CtorComment2 {
|
||||
/*
|
||||
* The magic of comments
|
||||
*/
|
||||
// single line magic comments
|
||||
public CtorComment() {}
|
||||
}
|
||||
@@ -18,4 +18,22 @@ internal class B// this constructor will disappear
|
||||
|
||||
fun foo() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class CtorComment {
|
||||
var myA: String
|
||||
|
||||
/*
|
||||
* The magic of comments
|
||||
*/
|
||||
// single line magic comments
|
||||
init {
|
||||
myA = "a"
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The magic of comments
|
||||
*/
|
||||
// single line magic comments
|
||||
internal class CtorComment2
|
||||
@@ -0,0 +1,18 @@
|
||||
class CtorComment {
|
||||
public String myA;
|
||||
|
||||
/**
|
||||
* This constructor is especially useful
|
||||
*/
|
||||
public CtorComment() {
|
||||
myA = "str";
|
||||
}
|
||||
}
|
||||
|
||||
class CtorComment2 {
|
||||
|
||||
/**
|
||||
* This constructor is especially useful
|
||||
*/
|
||||
public CtorComment() {}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
internal class CtorComment {
|
||||
var myA: String
|
||||
|
||||
/**
|
||||
* This constructor is especially useful
|
||||
*/
|
||||
init {
|
||||
myA = "str"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor is especially useful
|
||||
*/
|
||||
internal class CtorComment2
|
||||
@@ -1807,6 +1807,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorDoc.java")
|
||||
public void testPrimaryConstructorDoc() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/primaryConstructorDoc.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("quoted.java")
|
||||
public void testQuoted() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/quoted.java");
|
||||
|
||||
@@ -1807,6 +1807,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorDoc.java")
|
||||
public void testPrimaryConstructorDoc() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/primaryConstructorDoc.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("quoted.java")
|
||||
public void testQuoted() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/quoted.java");
|
||||
|
||||
Reference in New Issue
Block a user