25

Is it possible to define a Kotlin extension function on a annotated type like this?

@ColorInt
fun @ColorInt Int.darken(): Int {
    return ColorUtils.blendARGB(this, Color.BLACK, 0.2f)
}

Alternative form:

@ColorInt
fun (@ColorInt Int).darken(): Int {
    return ColorUtils.blendARGB(this, Color.BLACK, 0.2f)
}

That would correspond to the following static funtion:

@ColorInt
fun darken(@ColorInt color: Int): Int {
    return ColorUtils.blendARGB(color, Color.BLACK, 0.2f)
}

I don't think that's possible yet using Kotlin, but would it be possible to add that feature in later Kotlin versions?

On a side note: The same question applies to @IntDef, @StringDef, @[resource type]Res as well.

  • zsmb13 had a good point explaining that this could cause some issues with doubled methods with the same signature. Anyway that could be solved by annotating a different JVM method name for that function. – Jan Heinrich Reimer May 29 '17 at 08:22

1 Answers1

52

Yes you can. Use the following syntax:

@ColorInt
fun @receiver:ColorInt Int.darken(): Int {
    return ColorUtils.blendARGB(this, Color.BLACK, 0.2f)
}

More about annotation use-site targets: http://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets

Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
  • That's brilliant! I guess IntelliJ would then automatically hide that extension function for methods that are not annotated `@ColorInt`, right? – Jan Heinrich Reimer May 29 '17 at 08:17
  • 3
    No, `@ColorInt` is an android-specific annotation which is evaluated by Lint. Lint supports Kotlin code and you should get a warning when you call the method on an int which is not annotated, but you will still be able to call the method. – Kirill Rakhman May 29 '17 at 08:38
  • That would be as expected. – Jan Heinrich Reimer May 29 '17 at 08:50
  • 1
    @Heinrich if that answer was helpful to you, please consider accepting it. – Kirill Rakhman Jun 19 '17 at 12:02
  • This method seems to be deprecated now; I get this lint warning: `Use of this annotation with target 'type' and use site target '@receiver' is deprecated.` Any alternatives? – aksh1618 Mar 25 '18 at 21:27
  • 2
    @A.K.S.H. this seems to be a bug and should be fixed in 1.2.40: https://youtrack.jetbrains.com/issue/KT-21696 – Kirill Rakhman Mar 26 '18 at 07:58
  • What about `@DrawableRes`? that the function will return Drawable? Android studio will complain: `This annotation does not apply for type android.graphics.drawable.Drawable; expected int or long` – HendraWD Sep 06 '18 at 05:28
  • @HendraWD, `@DrawableRes` denotes a resource ID that holds a drawable ressource, not a `Drawable` itself. – Jan Heinrich Reimer Apr 16 '19 at 16:37
  • 5
    Is this still working? I am doing this, but using layout res, string res, even with a negative number, there is no warning. – Deneb Chorny Apr 02 '20 at 18:59