Fix for KT-15027 J2K: Annotations are set on functions, but not on property accessors
#KT-15027 fixed
This commit is contained in:
committed by
Simon Ogorodnik
parent
5071baf970
commit
73ea0e8460
@@ -37,15 +37,15 @@ class AnnotationConverter(private val converter: Converter) {
|
||||
return nameAsString in annotationsToRemove || nameAsString == Target::class.java.name
|
||||
}
|
||||
|
||||
fun convertAnnotations(owner: PsiModifierListOwner): Annotations
|
||||
= convertAnnotationsOnly(owner) + convertModifiersToAnnotations(owner)
|
||||
fun convertAnnotations(owner: PsiModifierListOwner, target: AnnotationUseTarget? = null): Annotations
|
||||
= convertAnnotationsOnly(owner, target) + convertModifiersToAnnotations(owner, target)
|
||||
|
||||
private fun convertAnnotationsOnly(owner: PsiModifierListOwner): Annotations {
|
||||
private fun convertAnnotationsOnly(owner: PsiModifierListOwner, target: AnnotationUseTarget?): Annotations {
|
||||
val modifierList = owner.modifierList
|
||||
val annotations = modifierList?.annotations?.filter { it.qualifiedName !in annotationsToRemove }
|
||||
|
||||
var convertedAnnotations: List<Annotation> = if (annotations != null && annotations.isNotEmpty()) {
|
||||
val newLines = if (!modifierList!!.isInSingleLine()) {
|
||||
val newLines = if (!modifierList.isInSingleLine()) {
|
||||
true
|
||||
}
|
||||
else {
|
||||
@@ -57,14 +57,14 @@ class AnnotationConverter(private val converter: Converter) {
|
||||
if (child is PsiWhiteSpace) !child.isInSingleLine() else false
|
||||
}
|
||||
|
||||
annotations.mapNotNull { convertAnnotation(it, newLineAfter = newLines) }
|
||||
annotations.mapNotNull { convertAnnotation(it, newLineAfter = newLines, target = target) }
|
||||
}
|
||||
else {
|
||||
listOf()
|
||||
}
|
||||
|
||||
if (owner is PsiDocCommentOwner) {
|
||||
val deprecatedAnnotation = convertDeprecatedJavadocTag(owner)
|
||||
val deprecatedAnnotation = convertDeprecatedJavadocTag(owner, target)
|
||||
if (deprecatedAnnotation != null) {
|
||||
convertedAnnotations += deprecatedAnnotation
|
||||
}
|
||||
@@ -73,20 +73,29 @@ class AnnotationConverter(private val converter: Converter) {
|
||||
return Annotations(convertedAnnotations).assignNoPrototype()
|
||||
}
|
||||
|
||||
private fun convertDeprecatedJavadocTag(element: PsiDocCommentOwner): Annotation? {
|
||||
private fun convertDeprecatedJavadocTag(element: PsiDocCommentOwner, target: AnnotationUseTarget?): Annotation? {
|
||||
val deprecatedTag = element.docComment?.findTagByName("deprecated") ?: return null
|
||||
val deferredExpression = converter.deferredElement<Expression> {
|
||||
LiteralExpression("\"" + StringUtil.escapeStringCharacters(deprecatedTag.content()) + "\"").assignNoPrototype()
|
||||
}
|
||||
return Annotation(Identifier("Deprecated").assignPrototype(deprecatedTag.nameElement),
|
||||
listOf(null to deferredExpression), newLineAfter = true)
|
||||
val identifier = Identifier("Deprecated").assignPrototype(deprecatedTag.nameElement)
|
||||
return Annotation(identifier,
|
||||
listOf(null to deferredExpression),
|
||||
true,
|
||||
effectiveAnnotationUseTarget(identifier.name, target))
|
||||
.assignPrototype(deprecatedTag)
|
||||
}
|
||||
|
||||
private fun convertModifiersToAnnotations(owner: PsiModifierListOwner): Annotations {
|
||||
private fun convertModifiersToAnnotations(owner: PsiModifierListOwner, target: AnnotationUseTarget?): Annotations {
|
||||
val list = MODIFIER_TO_ANNOTATION
|
||||
.filter { owner.hasModifierProperty(it.first) }
|
||||
.map { Annotation(Identifier.withNoPrototype(it.second), listOf(), newLineAfter = false).assignNoPrototype() }
|
||||
.map {
|
||||
Annotation(Identifier.withNoPrototype(it.second),
|
||||
listOf(),
|
||||
newLineAfter = false,
|
||||
target = target
|
||||
).assignNoPrototype()
|
||||
}
|
||||
return Annotations(list).assignNoPrototype()
|
||||
}
|
||||
|
||||
@@ -101,9 +110,15 @@ class AnnotationConverter(private val converter: Converter) {
|
||||
return expr.referenceName?.let { JavaAnnotationTargetMapper.mapJavaTargetArgumentByName(it) } ?: emptySet()
|
||||
}
|
||||
|
||||
fun convertAnnotation(annotation: PsiAnnotation, newLineAfter: Boolean): Annotation? {
|
||||
private fun effectiveAnnotationUseTarget(name: String, target: AnnotationUseTarget?): AnnotationUseTarget? =
|
||||
when (name) {
|
||||
"Deprecated" -> if (target == AnnotationUseTarget.Param) null else target
|
||||
else -> target
|
||||
}
|
||||
|
||||
fun convertAnnotation(annotation: PsiAnnotation, newLineAfter: Boolean, target: AnnotationUseTarget? = null): Annotation? {
|
||||
val (name, arguments) = convertAnnotationValue(annotation) ?: return null
|
||||
return Annotation(name, arguments, newLineAfter).assignPrototype(annotation)
|
||||
return Annotation(name, arguments, newLineAfter, effectiveAnnotationUseTarget(name.name, target)).assignPrototype(annotation, CommentsAndSpacesInheritance.NO_SPACES)
|
||||
}
|
||||
|
||||
private fun convertAnnotationValue(annotation: PsiAnnotation): Pair<Identifier, List<Pair<Identifier?, DeferredElement<Expression>>>>? {
|
||||
|
||||
@@ -203,7 +203,7 @@ class ConstructorConverter(
|
||||
FunctionParameter(propertyInfo.identifier,
|
||||
type,
|
||||
if (propertyInfo.isVar) FunctionParameter.VarValModifier.Var else FunctionParameter.VarValModifier.Val,
|
||||
converter.convertAnnotations(parameter) + converter.convertAnnotations(field),
|
||||
converter.convertAnnotations(parameter, AnnotationUseTarget.Param) + converter.convertAnnotations(field),
|
||||
propertyInfo.modifiers,
|
||||
default)
|
||||
.assignPrototypes(
|
||||
|
||||
@@ -160,8 +160,8 @@ class Converter private constructor(
|
||||
return File(convertedChildren).assignPrototype(javaFile)
|
||||
}
|
||||
|
||||
fun convertAnnotations(owner: PsiModifierListOwner): Annotations
|
||||
= annotationConverter.convertAnnotations(owner)
|
||||
fun convertAnnotations(owner: PsiModifierListOwner, target: AnnotationUseTarget? = null): Annotations
|
||||
= annotationConverter.convertAnnotations(owner, target)
|
||||
|
||||
fun convertClass(psiClass: PsiClass): Class {
|
||||
if (psiClass.isAnnotationType) {
|
||||
@@ -320,10 +320,19 @@ class Converter private constructor(
|
||||
val getMethod = propertyInfo.getMethod
|
||||
val setMethod = propertyInfo.setMethod
|
||||
|
||||
//TODO: annotations from getter/setter?
|
||||
val annotations = field?.let { convertAnnotations(it) } ?: Annotations.Empty
|
||||
|
||||
val modifiers = (propertyInfo.modifiers + (field?.let{ specialModifiersCase(field) } ?: Modifiers.Empty))
|
||||
var annotations = Annotations.Empty
|
||||
|
||||
field?.let { annotations += convertAnnotations(it) }
|
||||
|
||||
if (!propertyInfo.needExplicitGetter)
|
||||
getMethod?.let { annotations += convertAnnotations(it, AnnotationUseTarget.Get) }
|
||||
|
||||
if (!propertyInfo.needExplicitSetter)
|
||||
setMethod?.let { annotations += convertAnnotations(it, AnnotationUseTarget.Set) }
|
||||
|
||||
|
||||
val modifiers = (propertyInfo.modifiers + (field?.let { specialModifiersCase(field) } ?: Modifiers.Empty))
|
||||
|
||||
val name = propertyInfo.identifier
|
||||
if (field is PsiEnumConstant) {
|
||||
|
||||
@@ -20,9 +20,20 @@ import org.jetbrains.kotlin.j2k.CodeBuilder
|
||||
import org.jetbrains.kotlin.j2k.append
|
||||
import org.jetbrains.kotlin.j2k.buildList
|
||||
|
||||
class Annotation(val name: Identifier, val arguments: List<Pair<Identifier?, DeferredElement<Expression>>>, val newLineAfter: Boolean) : Element() {
|
||||
enum class AnnotationUseTarget(val id: String) {
|
||||
File("file"), Param("param"), Get("get"), Set("set")
|
||||
}
|
||||
|
||||
class Annotation(val name: Identifier,
|
||||
val arguments: List<Pair<Identifier?, DeferredElement<Expression>>>,
|
||||
val newLineAfter: Boolean,
|
||||
val target: AnnotationUseTarget? = null) : Element() {
|
||||
|
||||
override fun generateCode(builder: CodeBuilder) {
|
||||
builder.append("@")
|
||||
target?.let {
|
||||
builder.append("${it.id}:")
|
||||
}
|
||||
if (arguments.isEmpty()) {
|
||||
builder.append(name)
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
@interface A {
|
||||
|
||||
}
|
||||
|
||||
@interface B {
|
||||
|
||||
}
|
||||
|
||||
public class U {
|
||||
@B
|
||||
public int i;
|
||||
|
||||
public U(@A int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
internal annotation class A
|
||||
|
||||
internal annotation class B
|
||||
|
||||
class U(@param:A @B
|
||||
var i: Int)
|
||||
@@ -0,0 +1,18 @@
|
||||
@interface An {
|
||||
String value();
|
||||
}
|
||||
|
||||
|
||||
public class Test {
|
||||
private int id;
|
||||
|
||||
@An(value = "get")
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@An(value = "set")
|
||||
public void setId(int id) {
|
||||
this.id = id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
internal annotation class An(val value: String)
|
||||
|
||||
|
||||
class Test {
|
||||
@get:An(value = "get")
|
||||
@set:An(value = "set")
|
||||
var id: Int = 0
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class WithModifiersOnAccessors {
|
||||
private synchronized void methSync() {}
|
||||
protected strictfp void methStrict() {}
|
||||
|
||||
private int sync = 0;
|
||||
public synchronized int getSync() { return sync; }
|
||||
public synchronized void setSync(int sync) { this.sync = sync; }
|
||||
|
||||
public double strict = 0.0;
|
||||
public strictfp double getStrict() { return strict; }
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class WithModifiersOnAccessors {
|
||||
@Synchronized private fun methSync() {
|
||||
}
|
||||
|
||||
@Strictfp protected fun methStrict() {
|
||||
}
|
||||
|
||||
@get:Synchronized @set:Synchronized var sync = 0
|
||||
|
||||
@get:Strictfp var strict = 0.0
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import javaApi.Anon5
|
||||
|
||||
internal class A
|
||||
@Anon5(10)
|
||||
internal class A @Anon5(10)
|
||||
constructor(private val a: Int, private val b: Int) {
|
||||
|
||||
@Deprecated("") // this constructor will not be replaced by default parameter value in primary because of this annotation
|
||||
|
||||
@@ -56,6 +56,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationFromConstructorParamToProperty.java")
|
||||
public void testAnnotationFromConstructorParamToProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationFromConstructorParamToProperty.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationInterface1.java")
|
||||
public void testAnnotationInterface1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationInterface1.java");
|
||||
@@ -86,6 +92,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsFromPropertyAccessors.java")
|
||||
public void testAnnotationsFromPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationsFromPropertyAccessors.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaClassArgument.java")
|
||||
public void testJavaClassArgument() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/javaClassArgument.java");
|
||||
@@ -116,6 +128,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("modifiersToAnnotationsFromPropertyAccessors.java")
|
||||
public void testModifiersToAnnotationsFromPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/modifiersToAnnotationsFromPropertyAccessors.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorAnnotation.java")
|
||||
public void testPrimaryConstructorAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/primaryConstructorAnnotation.java");
|
||||
|
||||
@@ -56,6 +56,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationFromConstructorParamToProperty.java")
|
||||
public void testAnnotationFromConstructorParamToProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationFromConstructorParamToProperty.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationInterface1.java")
|
||||
public void testAnnotationInterface1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationInterface1.java");
|
||||
@@ -86,6 +92,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotationsFromPropertyAccessors.java")
|
||||
public void testAnnotationsFromPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationsFromPropertyAccessors.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaClassArgument.java")
|
||||
public void testJavaClassArgument() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/javaClassArgument.java");
|
||||
@@ -116,6 +128,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("modifiersToAnnotationsFromPropertyAccessors.java")
|
||||
public void testModifiersToAnnotationsFromPropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/modifiersToAnnotationsFromPropertyAccessors.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primaryConstructorAnnotation.java")
|
||||
public void testPrimaryConstructorAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/primaryConstructorAnnotation.java");
|
||||
|
||||
Reference in New Issue
Block a user