@@ -3,26 +3,18 @@ package misk.web.actions
33import java.lang.reflect.Method
44import java.util.ArrayDeque
55import kotlin.reflect.KFunction
6+ import kotlin.reflect.KParameter
7+ import kotlin.reflect.full.callSuspendBy
68import kotlin.reflect.jvm.javaMethod
79
8- /* * Returns an instance of [T] annotating this method or a method it overrides. */
9- internal inline fun <reified T : Annotation > KFunction <* >.findAnnotationWithOverrides (): T ? {
10- return javaMethod!! .findAnnotationWithOverrides(T ::class .java)
11- }
12-
1310/* *
14- * Returns an instance of [T] annotating this method or a method it overrides. If multiple
15- * overridden methods have the annotation, one is chosen arbitrarily.
11+ * Returns a function that delegates everything to this. It promotes all annotations from overridden
12+ * functions to the returned function, and all annotations from overridden parameters to the
13+ * returned function.
14+ *
15+ * Use this to make it easy to get annotations on overridden functions 'for free'.
1616 */
17- internal fun <T : Annotation > Method.findAnnotationWithOverrides (annotationClass : Class <T >): T ? {
18- for (method in overrides()) {
19- val annotation = method.getAnnotation(annotationClass)
20- if (annotation != null ) {
21- return annotation
22- }
23- }
24- return null
25- }
17+ internal fun <R > KFunction<R>.withOverrides (): KFunction <R > = FunctionWithOverrides (this )
2618
2719/* * Returns the overrides of this method with overriding methods preceding overridden methods. */
2820internal fun Method.overrides (): Set <Method > {
@@ -32,7 +24,7 @@ internal fun Method.overrides(): Set<Method> {
3224}
3325
3426/* * Returns the method that [override] overrides. */
35- internal fun Class <* >.getOverriddenMethod (override : Method ): Method ? {
27+ private fun Class <* >.getOverriddenMethod (override : Method ): Method ? {
3628 return try {
3729 check(this .isAssignableFrom(override .declaringClass))
3830 val overridden = getDeclaredMethod(override .name, * override .parameterTypes)
@@ -105,3 +97,51 @@ internal fun Method.preferNonSynthetic(): Method {
10597
10698 return this
10799}
100+
101+ internal val KFunction <* >.javaMethod: Method ?
102+ get() = (this as ? FunctionWithOverrides )?.function?.javaMethod ? : this .javaMethod
103+
104+ internal class FunctionWithOverrides <out R >(
105+ val function : KFunction <R >
106+ ) : KFunction<R> by function {
107+ private val methodOverrides = function.javaMethod!! .overrides()
108+
109+ override val annotations: List <Annotation > =
110+ methodOverrides.flatMap { it.annotations.toList() }
111+
112+ override val parameters: List <KParameter > =
113+ function.parameters.mapIndexed { index, parameter ->
114+ ParameterWithOverrides (
115+ parameter,
116+ methodOverrides.flatMap { override ->
117+ when (index) {
118+ 0 -> listOf ()
119+ else -> override .parameters[index - 1 ].annotations.toList()
120+ }
121+ }
122+ )
123+ }
124+
125+ override fun callBy (args : Map <KParameter , Any ?>): R {
126+ val parameters = args.mapKeys { (key, _) ->
127+ function.parameters[key.index]
128+ }
129+ return function.callBy(parameters)
130+ }
131+
132+ suspend fun callSuspendBy (args : Map <KParameter , Any ?>): R {
133+ val parameters = args.mapKeys { (key, _) ->
134+ function.parameters[key.index]
135+ }
136+ return function.callSuspendBy(parameters)
137+ }
138+
139+ override fun toString (): String {
140+ return function.toString()
141+ }
142+ }
143+
144+ private class ParameterWithOverrides (
145+ val parameter : KParameter ,
146+ override val annotations : List <Annotation >,
147+ ) : KParameter by parameter
0 commit comments