1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
# Annotation Arguments
**NOTE**: This document contains old language design notes and does not correspond to the current state of Kotlin. Please see http://kotlinlang.org/docs/reference/annotations.html for up-to-date documentation on this topic.
***
Goals:
* Sort out problems of positional parameters and varargs in annotations
* \[TBD later] Better syntax for array arguments to annotations
Related issues:
* [KT-6652 Prohibit using java annotations with positional arguments](https://youtrack.jetbrains.com/issue/KT-6652)
* [KT-6220 Annotations: handling of "value" members](https://youtrack.jetbrains.com/issue/KT-6220)
* [KT-6641 Annotations with multiple array values](https://youtrack.jetbrains.com/issue/KT-6641)
* [KT-2576 Shortcut notation for annotations with single-value array elements](https://youtrack.jetbrains.com/issue/KT-2576)
## Problem Statement
In Java annotation elements (this is the term java uses for "fields"/"attributes"/"properties" of an annotation) are defined as methods in the corresponding `@interface`, so there is no ordering rule that we can use when loading a fictitious primary constructor for a Java annotation.
Example:
Let's say there's a Java annotation with two elements:
``` java
@interface Ann {
int foo();
String bar();
}
```
When we use it in Kotlin, we can use positional arguments:
``` kotlin
[Ann(10, "asd")]
class Baz
```
Now, it's both source- and binary- compatible to reorder methods in a Java interface:
``` java
@interface Ann {
String bar();
int foo();
}
```
But the code above will break.
Also, we now load all array arguments as varargs, which may break for the same reason.
## Loading Java Annotations
Fictitious constructors for Java annotations could be built as follows:
* if there is an element named `value`, it is put first on the parameter list
* if all other elements have default values, and `value` has an array type, it is marked `vararg` and has the type of the elements of the array
* parameters corresponding to all elements but `value` can not be used positionally, only named arguments are allowed for them (this requires adding a platform-specific check to `frontend.java`)
* note that elements with default values should be transformed to parameters with default values
>**NOTE**: when `value` parameter is marked `vararg` and no arguments are passed, behavior will depend on presence of parameter's default value:
* if it has no default value, an empty array is emitted in the byte code
* if it has a default value, then no value is emitted in the byte code, so the default value will be used
> Thus, **behavior of the same code can change after adding a default value to parameter and recompiling kotlin
sources**
## \[TBD later] Array Syntax Examples
**NOTE**: Scala still uses `Array(...)` in annotations, no matter how ugly it is
Option 1: Use `[]` for array literal
``` kotlin
@User(
firstName = "John",
names = ["Marie", "Spencer"],
lastName = "Doe"
)
class JohnDoe
@Values([FOO, BAR]) // ugly, but it's the same in Java: @Ann({FOO, BAR})
class WithValues
```
Option 2: Use `@(...)`
``` kotlin
@User(
firstName = "John",
names = @("Marie", "Spencer"),
lastName = "Doe"
)
class JohnDoe
@Values(@(FOO, BAR)) // looks bad
class WithValues
```
|