Skip to content

Latest commit

 

History

History
151 lines (116 loc) · 7.08 KB

jvm-meta-annotations-artifact.md

File metadata and controls

151 lines (116 loc) · 7.08 KB

Artifact with meta-annotations for Java types enhancement

Summary

Add a separate artifact containing meta-annotations covering use cases of ones from JSR-305.

Motivation

  • We need to put somewhere @ApplyToTypeArgumentsAnnotation meta-annotation (see the discussion).
  • There is a modules-related issue with JSR-305 and Java 9.
  • It's worth simplifying the way how JSR-305 nullability meta-annotations are being used and integrating them with Kotlin-specific meta annotations. Namely, @UnderMigration and @ApplyToTypeArguments.

Description

This section describes proposed semantics of the new annotations and partly the layout of resulting artifact.

Root package

Root package for this artifact will be kotlin.annotations.jvm. All classes/packages names are assumed to be placed in the package and only their relative names are mentioned below.

Built-in qualifiers

In JSR-305, there is @TypeQualifier annotation that allows to introduce custom qualifiers (like @Nonnull). But that kind of meta-meta level seems to be unnecessary to our needs (at least for now), the Kotlin compiler supports only nullability qualifier (and in the nearest future mutability might be supported as well).

So, there will only be fixed number of built-in qualifier annotations:

  • nullability.Nullable
  • nullability.NotNull
  • mutability.Mutable
  • mutability.ReadOnly

Their target set would be the following: ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE

NB: Having ElementType.TYPE_USE among their target is questionable since it's unknown how that would work with bytecode version 50.0 (JDK 1.6).

And semantics when being applied to types is just the same as for analogue from org.jetbrains.annotations (see more about types enhancement)

Alias annotation

This proposal suggests to introduce meta.Alias annotation which would affect the compiler in a similar way that @TypeQualifierNickname does.

In a basic version its declaration may look like

package kotlin.annotations.jvm.meta

@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class Alias(val qualifier: KClass<*>)

and its usages is supposed to look like:

@Alias(kotlin.annotations.jvm.nullability.Nullable::class)
annotation class MyNullable

Thus, applying @MyNullable should have the same effect as @Nullable itself has. Beside it, @MyNullable may have @UnderMigration annotation on it that would change its migration status.

Default qualifiers

This section describes the way how the concept similar to JSR-305 default qualifiers semantics can be introduced.

Using ApplicabilityKind instead of ElementType

We suggest to use a special enum class instead of ElementType that is used as a parameter type for JSR-305 @TypeQualifierDefault. It might look like:

enum class ApplicabilityKind {
    RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE, TYPE_ARGUMENT
}

All elements should work just the same as relevant entries from ElementType do for @TypeQualifierDefault, beside TYPE_ARGUMENT. The latter one should have the following effect: if a default qualifier is determined to be applied to some top-level type (using the same logic as for @TypeQualifierDefault) and the set of applicability kinds contain TYPE_ARGUMENT then this qualifier should also be applied to all of it's type arguments (recursively).

@ApplyByDefault

We suggest to introduce a separate annotation meta.ApplyByDefault with vararg-parameter of type ApplicabilityKind:

@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class ApplyByDefault(val qualifier: KClass<*>, vararg val elements: ApplicabilityKind)

Basically, it should work just the same as @TypeQualifierDefault, e.g. it might be used like:

@ApplyByDefault(MyNullable::class, ApplicabilityKind.PARAMETER)
annotation class MyAllParametersAreNullableByDefault

@ApplyByDefault(MyNonnull::class, ApplicabilityKind.PARAMETER)
annotation class MyAllParametersAreNonNullByDefault

@ApplyByDefault(MyNullable::class, ApplicabilityKind.PARAMETER)
annotation class MyAllParametersAreNullableByDefault

@ApplyByDefault(
    MyNonnull::class,
    ApplicabilityKind.RETURN_TYPE, ApplicabilityKind.VALUE_PARAMETER,
    ApplicabilityKind.FIELD, ApplicabilityKind.TYPE_ARGUMENT
)
annotation class MyApiNonNullByDefault

NB: When module-info classes are annotated with a default qualifiers it should work just like being applied to all classes in the modules.

@UnderMigration applicability

To simplify its semantics, we suggest to restrict applicability of @UnderMigration only to qualifier aliases (i.e. to annotations that are meta-annotated with meta.Alias).

Thus, when being applied to a default qualifier @UnderMigration should be effectively ignored.

Details on artifact

There is already an artifact called kotlin-annotations-jvm that might be the best candidate where the new meta annotations may be placed.

Probably, the annotations that are already there should be moved to a different packages:

  • kotlin.annotations.jvm.UnderMigration, kotlin.annotations.jvm.MigrationStatus -> kotlin.annotations.jvm.meta
  • kotlin.annotations.jvm.Mutable, kotlin.annotations.jvm.ReadOnly -> kotlin.annotations.jvm.collections

Remaining questions

  • Should aliasing JSR-305 qualifiers like javax.annotation.Nonnull be allowed?
  • What is the best name for ApplicabilityKind enum class? Would it be better to place it inside the ApplyByDefault annotation class (if it will be there)
  • What bytecode version should all those annotations have? On one side, we'd like to have compatibility with 1.6, on the other, we'd like them to have ElementType.TYPE_USE among their targets
  • Do we need to add built-in default qualifiers (like @AllParametersAreNotNullByDefault or @NotNullAPI)?