Skip to content

Commit b589ced

Browse files
committed
Fix for #668 - using Java reflection in ScalaDsl
The previous implementation was using Scala 2.9 reflection via Manifest[T] to extract the function parameter types using the erasure method (renamed to runtimeClass in Scala 2.10). The problem with this approach is that Manifest.erasure provides the runtime java.lang.reflect.Type, which means the type has been erased of paramterized type info. The ParameterInfo class relies on the ParamaterizedType information to determine how to auto populate Step arguments of type java.util.List<T>. When using java Lists from the Scala DSL, this logic would fail. As ParameterInfo's implementation is entirely based on the Java reflection API, it makes more sense to use Java reflection in the implementation of Scala DSL as it will be compatible with the logic in core. This change uses Java reflection on the Scala Function objects to extract the ParameterizedType information, which also simplifies the code. The manifest is no longer used by the register method, but seems to still be required on the function definitions by another part of the code so these have been left in place. The functionParams method has to filter out JVM bridge methods to ensure the correct version of the apply() method (with type parameter information) is captured. Function objects only have one defined method named apply() so taking the head of the list should always be safe.
1 parent 63dca60 commit b589ced

File tree

5 files changed

+58
-31
lines changed

5 files changed

+58
-31
lines changed

scala/src/main/scala/cucumber/api/scala/ScalaDsl.scala

+28-26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import _root_.cucumber.runtime.scala.ScalaStepDefinition
66
import _root_.cucumber.runtime.HookDefinition
77
import _root_.cucumber.runtime.StepDefinition
88
import collection.mutable.ArrayBuffer
9+
import java.lang.reflect.Type
910

1011
/**
1112
* Base trait for a scala step definition implementation.
@@ -57,7 +58,7 @@ trait ScalaDsl { self =>
5758
def apply(f: => Unit){ apply(f _) }
5859

5960
def apply(fun: Fun0) {
60-
register(Nil) {case Nil => fun.f()}
61+
register(Array[Type]()) {case Nil => fun.f()}
6162
}
6263

6364
/**
@@ -91,22 +92,22 @@ trait ScalaDsl { self =>
9192
*/
9293

9394
def apply[T1](f: (T1) => Any)(implicit m1:Manifest[T1]) {
94-
register(List(m1)) {
95+
register(functionParams(f)) {
9596
case List(a1:AnyRef) =>
9697
f(a1.asInstanceOf[T1])
9798
}
9899
}
99100

100101
def apply[T1, T2](f: (T1, T2) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2]) {
101-
register(List(m1, m2)) {
102+
register(functionParams(f)) {
102103
case List(a1:AnyRef, a2:AnyRef) =>
103104
f(a1.asInstanceOf[T1],
104105
a2.asInstanceOf[T2])
105106
}
106107
}
107108

108109
def apply[T1, T2, T3](f: (T1, T2, T3) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3]) {
109-
register(List(m1, m2, m3)) {
110+
register(functionParams(f)) {
110111
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef) =>
111112
f(a1.asInstanceOf[T1],
112113
a2.asInstanceOf[T2],
@@ -115,7 +116,7 @@ trait ScalaDsl { self =>
115116
}
116117

117118
def apply[T1, T2, T3, T4](f: (T1, T2, T3, T4) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4]) {
118-
register(List(m1, m2, m3, m4)) {
119+
register(functionParams(f)) {
119120
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef) =>
120121
f(a1.asInstanceOf[T1],
121122
a2.asInstanceOf[T2],
@@ -125,7 +126,7 @@ trait ScalaDsl { self =>
125126
}
126127

127128
def apply[T1, T2, T3, T4, T5](f: (T1, T2, T3, T4, T5) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5]) {
128-
register(List(m1, m2, m3, m4, m5)) {
129+
register(functionParams(f)) {
129130
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef) =>
130131
f(a1.asInstanceOf[T1],
131132
a2.asInstanceOf[T2],
@@ -136,7 +137,7 @@ trait ScalaDsl { self =>
136137
}
137138

138139
def apply[T1, T2, T3, T4, T5, T6](f: (T1, T2, T3, T4, T5, T6) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6]) {
139-
register(List(m1, m2, m3, m4, m5, m6)) {
140+
register(functionParams(f)) {
140141
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef) =>
141142
f(a1.asInstanceOf[T1],
142143
a2.asInstanceOf[T2],
@@ -148,7 +149,7 @@ trait ScalaDsl { self =>
148149
}
149150

150151
def apply[T1, T2, T3, T4, T5, T6, T7](f: (T1, T2, T3, T4, T5, T6, T7) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7]) {
151-
register(List(m1, m2, m3, m4, m5, m6, m7)) {
152+
register(functionParams(f)) {
152153
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef) =>
153154
f(a1.asInstanceOf[T1],
154155
a2.asInstanceOf[T2],
@@ -161,7 +162,7 @@ trait ScalaDsl { self =>
161162
}
162163

163164
def apply[T1, T2, T3, T4, T5, T6, T7, T8](f: (T1, T2, T3, T4, T5, T6, T7, T8) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8]) {
164-
register(List(m1, m2, m3, m4, m5, m6, m7, m8)) {
165+
register(functionParams(f)) {
165166
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef) =>
166167
f(a1.asInstanceOf[T1],
167168
a2.asInstanceOf[T2],
@@ -175,7 +176,7 @@ trait ScalaDsl { self =>
175176
}
176177

177178
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9]) {
178-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9)) {
179+
register(functionParams(f)) {
179180
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef) =>
180181
f(a1.asInstanceOf[T1],
181182
a2.asInstanceOf[T2],
@@ -190,7 +191,7 @@ trait ScalaDsl { self =>
190191
}
191192

192193
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10]) {
193-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10)) {
194+
register(functionParams(f)) {
194195
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef) =>
195196
f(a1.asInstanceOf[T1],
196197
a2.asInstanceOf[T2],
@@ -206,7 +207,7 @@ trait ScalaDsl { self =>
206207
}
207208

208209
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11]) {
209-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11)) {
210+
register(functionParams(f)) {
210211
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef) =>
211212
f(a1.asInstanceOf[T1],
212213
a2.asInstanceOf[T2],
@@ -223,7 +224,7 @@ trait ScalaDsl { self =>
223224
}
224225

225226
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12]) {
226-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12)) {
227+
register(functionParams(f)) {
227228
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef) =>
228229
f(a1.asInstanceOf[T1],
229230
a2.asInstanceOf[T2],
@@ -241,7 +242,7 @@ trait ScalaDsl { self =>
241242
}
242243

243244
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13]) {
244-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13)) {
245+
register(functionParams(f)) {
245246
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef) =>
246247
f(a1.asInstanceOf[T1],
247248
a2.asInstanceOf[T2],
@@ -260,7 +261,7 @@ trait ScalaDsl { self =>
260261
}
261262

262263
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14]) {
263-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14)) {
264+
register(functionParams(f)) {
264265
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef) =>
265266
f(a1.asInstanceOf[T1],
266267
a2.asInstanceOf[T2],
@@ -280,7 +281,7 @@ trait ScalaDsl { self =>
280281
}
281282

282283
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15]) {
283-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15)) {
284+
register(functionParams(f)) {
284285
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef) =>
285286
f(a1.asInstanceOf[T1],
286287
a2.asInstanceOf[T2],
@@ -301,7 +302,7 @@ trait ScalaDsl { self =>
301302
}
302303

303304
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16]) {
304-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16)) {
305+
register(functionParams(f)) {
305306
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef) =>
306307
f(a1.asInstanceOf[T1],
307308
a2.asInstanceOf[T2],
@@ -323,7 +324,7 @@ trait ScalaDsl { self =>
323324
}
324325

325326
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17]) {
326-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17)) {
327+
register(functionParams(f)) {
327328
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef) =>
328329
f(a1.asInstanceOf[T1],
329330
a2.asInstanceOf[T2],
@@ -346,7 +347,7 @@ trait ScalaDsl { self =>
346347
}
347348

348349
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17], m18:Manifest[T18]) {
349-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18)) {
350+
register(functionParams(f)) {
350351
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef, a18:AnyRef) =>
351352
f(a1.asInstanceOf[T1],
352353
a2.asInstanceOf[T2],
@@ -370,7 +371,7 @@ trait ScalaDsl { self =>
370371
}
371372

372373
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17], m18:Manifest[T18], m19:Manifest[T19]) {
373-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19)) {
374+
register(functionParams(f)) {
374375
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef, a18:AnyRef, a19:AnyRef) =>
375376
f(a1.asInstanceOf[T1],
376377
a2.asInstanceOf[T2],
@@ -395,7 +396,7 @@ trait ScalaDsl { self =>
395396
}
396397

397398
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17], m18:Manifest[T18], m19:Manifest[T19], m20:Manifest[T20]) {
398-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)) {
399+
register(functionParams(f)) {
399400
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef, a18:AnyRef, a19:AnyRef, a20:AnyRef) =>
400401
f(a1.asInstanceOf[T1],
401402
a2.asInstanceOf[T2],
@@ -421,7 +422,7 @@ trait ScalaDsl { self =>
421422
}
422423

423424
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17], m18:Manifest[T18], m19:Manifest[T19], m20:Manifest[T20], m21:Manifest[T21]) {
424-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21)) {
425+
register(functionParams(f)) {
425426
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef, a18:AnyRef, a19:AnyRef, a20:AnyRef, a21:AnyRef) =>
426427
f(a1.asInstanceOf[T1],
427428
a2.asInstanceOf[T2],
@@ -448,7 +449,7 @@ trait ScalaDsl { self =>
448449
}
449450

450451
def apply[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) => Any)(implicit m1:Manifest[T1], m2:Manifest[T2], m3:Manifest[T3], m4:Manifest[T4], m5:Manifest[T5], m6:Manifest[T6], m7:Manifest[T7], m8:Manifest[T8], m9:Manifest[T9], m10:Manifest[T10], m11:Manifest[T11], m12:Manifest[T12], m13:Manifest[T13], m14:Manifest[T14], m15:Manifest[T15], m16:Manifest[T16], m17:Manifest[T17], m18:Manifest[T18], m19:Manifest[T19], m20:Manifest[T20], m21:Manifest[T21], m22:Manifest[T22]) {
451-
register(List(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22)) {
452+
register(functionParams(f)) {
452453
case List(a1:AnyRef, a2:AnyRef, a3:AnyRef, a4:AnyRef, a5:AnyRef, a6:AnyRef, a7:AnyRef, a8:AnyRef, a9:AnyRef, a10:AnyRef, a11:AnyRef, a12:AnyRef, a13:AnyRef, a14:AnyRef, a15:AnyRef, a16:AnyRef, a17:AnyRef, a18:AnyRef, a19:AnyRef, a20:AnyRef, a21:AnyRef, a22:AnyRef) =>
453454
f(a1.asInstanceOf[T1],
454455
a2.asInstanceOf[T2],
@@ -475,9 +476,9 @@ trait ScalaDsl { self =>
475476
}
476477
}
477478

478-
private def register(manifests: List[Manifest[_]])(pf: PartialFunction[List[Any], Any]){
479+
private def register(types: Array[Type])(pf: PartialFunction[List[Any], Any]) = {
479480
val frame: StackTraceElement = obtainFrame
480-
stepDefinitions += new ScalaStepDefinition(frame, name, regex, manifests.map(_.erasure), pf)
481+
stepDefinitions += new ScalaStepDefinition(frame, name, regex, types, pf)
481482
}
482483

483484
/**
@@ -490,6 +491,7 @@ trait ScalaDsl { self =>
490491
frames.find(_.getClassName == currentClass).get
491492
}
492493

494+
private def functionParams(f: Any) =
495+
f.getClass.getDeclaredMethods.filterNot(_.isBridge).head.getGenericParameterTypes
493496
}
494-
495497
}

scala/src/main/scala/cucumber/runtime/scala/ScalaStepDefinition.scala

+3-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import cucumber.api.Transform
2727
class ScalaStepDefinition(frame:StackTraceElement,
2828
name:String,
2929
pattern:String,
30-
parameterInfos:List[Class[_]],
30+
parameterInfos:Array[Type],
3131
f:List[Any] => Any) extends StepDefinition {
3232

3333
/**
@@ -53,15 +53,15 @@ class ScalaStepDefinition(frame:StackTraceElement,
5353
/**
5454
* How many declared parameters this stepdefinition has. Returns null if unknown.
5555
*/
56-
def getParameterCount() = parameterInfos.size()
56+
def getParameterCount() = parameterInfos.size
5757

5858
/**
5959
* The parameter type at index n. A hint about the raw parameter type is passed to make
6060
* it easier for the implementation to make a guess based on runtime information.
6161
* As Scala is a statically typed language, the javaType parameter is ignored
6262
*/
6363
def getParameterType(index: Int, javaType: Type) = {
64-
new ParameterInfo(parameterInfos.get(index), null, null, null)
64+
new ParameterInfo(parameterInfos(index), null, null, null)
6565
}
6666

6767
/**
@@ -80,5 +80,4 @@ class ScalaStepDefinition(frame:StackTraceElement,
8080
* @return the pattern associated with this instance. Used for error reporting only.
8181
*/
8282
def getPattern = pattern
83-
8483
}

scala/src/test/resources/cucumber/runtime/scala/test/cukes.feature

+9
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,12 @@ Feature: Cukes
7373
Scenario: Custom object with string constructor
7474
Given I have a person Bob
7575
Then he should say "Hello, I'm Bob!"
76+
77+
Scenario: Custom objects in the belly
78+
Given I have eaten the following cukes
79+
| Color | Number |
80+
| Green | 1 |
81+
| Red | 3 |
82+
| Blue | 2 |
83+
Then I should have eaten 6 cukes
84+
And they should have been Green, Red, Blue
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package cucumber.runtime.scala.model
2+
3+
case class Cukes(number: Int, color: String)

scala/src/test/scala/cucumber/runtime/scala/test/StepDefs.scala

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import _root_.cucumber.api.scala._
55
import cucumber.api.DataTable
66
import junit.framework.Assert._
77
import scala.collection.JavaConversions._
8-
import cucumber.runtime.scala.model.{Snake, Person}
8+
import cucumber.runtime.scala.model.{Cukes, Person, Snake}
9+
import java.util.{List => JList}
910

1011
/**
1112
* Test step definitions to exercise Scala cucumber
@@ -148,6 +149,19 @@ class CukesStepDefinitions extends ScalaDsl with EN {
148149
assertEquals(person.hello, s)
149150
}
150151

152+
var cukes: JList[Cukes] = null
153+
154+
Given("^I have eaten the following cukes$") { cs: JList[Cukes] =>
155+
cukes = cs
156+
}
157+
158+
Then("""^I should have eaten (\d) cukes$""") { total: Int =>
159+
assertEquals(total, cukes.map(_.number).sum)
160+
}
161+
162+
And("^they should have been (.*)$") { colors: String =>
163+
assertEquals(colors, cukes.map(_.color).mkString(", "))
164+
}
151165
}
152166

153167
class ThenDefs extends ScalaDsl with EN {

0 commit comments

Comments
 (0)