Fix for KT-12892 J2K: Wrong placing of comments when constructor converted to primary constructor & init

This commit is contained in:
Simon Ogorodnik
2016-10-18 12:17:11 +03:00
parent b51f5c5bd9
commit 7c8fdc42b4
10 changed files with 112 additions and 11 deletions
@@ -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(
+14 -2
View File
@@ -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");