Skip to content

Commit ee7e95b

Browse files
authored
Merge pull request #182 from cucumber/scala3prep
refactor: 💡 Split ScalaDsl in multiple files
2 parents a85dc66 + 2fb66b8 commit ee7e95b

10 files changed

+2664
-2646
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.cucumber.scala
2+
3+
private[scala] trait BaseScalaDsl {
4+
5+
val NO_REPLACEMENT = Seq[String]()
6+
val EMPTY_TAG_EXPRESSION = ""
7+
val DEFAULT_BEFORE_ORDER = 1000
8+
val DEFAULT_AFTER_ORDER = 1000
9+
10+
private[scala] val registry: ScalaDslRegistry = new ScalaDslRegistry()
11+
12+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package io.cucumber.scala
2+
3+
import scala.reflect.ClassTag
4+
5+
private[scala] trait DataTableTypeDsl extends BaseScalaDsl {
6+
7+
/** Register a data table type.
8+
*/
9+
def DataTableType: DataTableTypeBody = DataTableType(NO_REPLACEMENT)
10+
11+
/** Register a data table type with a replacement.
12+
* <p>
13+
* A data table can only represent absent and non-empty strings. By replacing
14+
* a known value (for example [empty]) a data table can also represent
15+
* empty strings.
16+
*
17+
* @param replaceWithEmptyString a string that will be replaced with an empty string.
18+
*/
19+
def DataTableType(replaceWithEmptyString: String): DataTableTypeBody =
20+
DataTableType(Seq(replaceWithEmptyString))
21+
22+
private def DataTableType(replaceWithEmptyString: Seq[String]) =
23+
new DataTableTypeBody(replaceWithEmptyString)
24+
25+
final class DataTableTypeBody(replaceWithEmptyString: Seq[String]) {
26+
27+
def apply[T](
28+
body: DataTableEntryDefinitionBody[T]
29+
)(implicit ev: ClassTag[T]): Unit = {
30+
registry.registerDataTableType(
31+
ScalaDataTableEntryTypeDetails[T](replaceWithEmptyString, body, ev)
32+
)
33+
}
34+
35+
def apply[T](
36+
body: DataTableOptionalEntryDefinitionBody[T]
37+
)(implicit ev: ClassTag[T]): Unit = {
38+
registry.registerDataTableType(
39+
ScalaDataTableOptionalEntryTypeDetails[T](
40+
replaceWithEmptyString,
41+
body,
42+
ev
43+
)
44+
)
45+
}
46+
47+
def apply[T](
48+
body: DataTableRowDefinitionBody[T]
49+
)(implicit ev: ClassTag[T]): Unit = {
50+
registry.registerDataTableType(
51+
ScalaDataTableRowTypeDetails[T](replaceWithEmptyString, body, ev)
52+
)
53+
}
54+
55+
def apply[T](
56+
body: DataTableOptionalRowDefinitionBody[T]
57+
)(implicit ev: ClassTag[T]): Unit = {
58+
registry.registerDataTableType(
59+
ScalaDataTableOptionalRowTypeDetails[T](
60+
replaceWithEmptyString,
61+
body,
62+
ev
63+
)
64+
)
65+
}
66+
67+
def apply[T](
68+
body: DataTableCellDefinitionBody[T]
69+
)(implicit ev: ClassTag[T]): Unit = {
70+
registry.registerDataTableType(
71+
ScalaDataTableCellTypeDetails[T](replaceWithEmptyString, body, ev)
72+
)
73+
}
74+
75+
def apply[T](
76+
body: DataTableOptionalCellDefinitionBody[T]
77+
)(implicit ev: ClassTag[T]): Unit = {
78+
registry.registerDataTableType(
79+
ScalaDataTableOptionalCellTypeDetails[T](
80+
replaceWithEmptyString,
81+
body,
82+
ev
83+
)
84+
)
85+
}
86+
87+
def apply[T](
88+
body: DataTableDefinitionBody[T]
89+
)(implicit ev: ClassTag[T]): Unit = {
90+
registry.registerDataTableType(
91+
ScalaDataTableTableTypeDetails[T](replaceWithEmptyString, body, ev)
92+
)
93+
}
94+
95+
}
96+
97+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package io.cucumber.scala
2+
3+
import io.cucumber.scala.Aliases.{
4+
DefaultDataTableCellTransformerBody,
5+
DefaultDataTableEntryTransformerBody,
6+
DefaultParameterTransformerBody
7+
}
8+
9+
private[scala] trait DefaultTransformerDsl extends BaseScalaDsl {
10+
11+
/** Register default parameter type transformer.
12+
*
13+
* @param body converts `String` argument to an instance of the `Type` argument
14+
*/
15+
def DefaultParameterTransformer(
16+
body: DefaultParameterTransformerBody
17+
): Unit = {
18+
registry.registerDefaultParameterTransformer(
19+
ScalaDefaultParameterTransformerDetails(body)
20+
)
21+
}
22+
23+
/** Register default data table cell transformer.
24+
*
25+
* @param body converts `String` argument to an instance of the `Type` argument
26+
*/
27+
def DefaultDataTableCellTransformer(
28+
body: DefaultDataTableCellTransformerBody
29+
): Unit = {
30+
DefaultDataTableCellTransformer(NO_REPLACEMENT)(body)
31+
}
32+
33+
/** Register default data table cell transformer with a replacement.
34+
* <p>
35+
* A data table can only represent absent and non-empty strings. By replacing
36+
* a known value (for example [empty]) a data table can also represent
37+
* empty strings.
38+
* *
39+
*
40+
* @param replaceWithEmptyString a string that will be replaced with an empty string.
41+
* @param body converts `String` argument to an instance of the `Type` argument
42+
*/
43+
def DefaultDataTableCellTransformer(
44+
replaceWithEmptyString: String
45+
)(body: DefaultDataTableCellTransformerBody): Unit = {
46+
DefaultDataTableCellTransformer(Seq(replaceWithEmptyString))(body)
47+
}
48+
49+
private def DefaultDataTableCellTransformer(
50+
replaceWithEmptyString: Seq[String]
51+
)(body: DefaultDataTableCellTransformerBody): Unit = {
52+
registry.registerDefaultDataTableCellTransformer(
53+
ScalaDefaultDataTableCellTransformerDetails(replaceWithEmptyString, body)
54+
)
55+
}
56+
57+
/** Register default data table entry transformer.
58+
*
59+
* @param body converts `Map[String,String]` argument to an instance of the `Type` argument
60+
*/
61+
def DefaultDataTableEntryTransformer(
62+
body: DefaultDataTableEntryTransformerBody
63+
): Unit = {
64+
DefaultDataTableEntryTransformer(NO_REPLACEMENT)(body)
65+
}
66+
67+
/** Register default data table cell transformer with a replacement.
68+
* <p>
69+
* A data table can only represent absent and non-empty strings. By replacing
70+
* a known value (for example [empty]) a data table can also represent
71+
* empty strings.
72+
*
73+
* @param replaceWithEmptyString a string that will be replaced with an empty string.
74+
* @param body converts `Map[String,String]` argument to an instance of the `Type` argument
75+
*/
76+
def DefaultDataTableEntryTransformer(
77+
replaceWithEmptyString: String
78+
)(body: DefaultDataTableEntryTransformerBody): Unit = {
79+
DefaultDataTableEntryTransformer(Seq(replaceWithEmptyString))(body)
80+
}
81+
82+
private def DefaultDataTableEntryTransformer(
83+
replaceWithEmptyString: Seq[String]
84+
)(body: DefaultDataTableEntryTransformerBody): Unit = {
85+
registry.registerDefaultDataTableEntryTransformer(
86+
ScalaDefaultDataTableEntryTransformerDetails(replaceWithEmptyString, body)
87+
)
88+
}
89+
90+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.cucumber.scala
2+
3+
import io.cucumber.scala.Aliases.DocStringDefinitionBody
4+
5+
import scala.reflect.ClassTag
6+
7+
private[scala] trait DocStringTypeDsl extends BaseScalaDsl {
8+
9+
/** Register doc string type.
10+
*
11+
* @param contentType Name of the content type.
12+
* @param body a function that creates an instance of <code>T</code>
13+
* from the doc string
14+
* @tparam T type to convert to
15+
*/
16+
def DocStringType[T](
17+
contentType: String
18+
)(body: DocStringDefinitionBody[T])(implicit ev: ClassTag[T]): Unit = {
19+
registry.registerDocStringType(
20+
ScalaDocStringTypeDetails[T](contentType, body, ev)
21+
)
22+
}
23+
24+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package io.cucumber.scala
2+
3+
private[scala] trait HookDsl extends BaseScalaDsl {
4+
self =>
5+
6+
/** Defines an before hook.
7+
*/
8+
def Before: HookBody = Before(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)
9+
10+
/** Defines an before hook.
11+
*
12+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
13+
*/
14+
def Before(tagExpression: String): HookBody =
15+
Before(tagExpression, DEFAULT_BEFORE_ORDER)
16+
17+
/** Defines an before hook.
18+
*
19+
* @param order the order in which this hook should run. Higher numbers are run first
20+
*/
21+
def Before(order: Int): HookBody = Before(EMPTY_TAG_EXPRESSION, order)
22+
23+
/** Defines an before hook.
24+
*
25+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
26+
* @param order the order in which this hook should run. Higher numbers are run first
27+
*/
28+
def Before(tagExpression: String, order: Int) =
29+
new HookBody(HookType.BEFORE, tagExpression, order, Utils.frame(self))
30+
31+
/** Defines an before step hook.
32+
*/
33+
def BeforeStep: HookBody =
34+
BeforeStep(EMPTY_TAG_EXPRESSION, DEFAULT_BEFORE_ORDER)
35+
36+
/** Defines an before step hook.
37+
*
38+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
39+
*/
40+
def BeforeStep(tagExpression: String): HookBody =
41+
BeforeStep(tagExpression, DEFAULT_BEFORE_ORDER)
42+
43+
/** Defines an before step hook.
44+
*
45+
* @param order the order in which this hook should run. Higher numbers are run first
46+
*/
47+
def BeforeStep(order: Int): HookBody = BeforeStep(EMPTY_TAG_EXPRESSION, order)
48+
49+
/** Defines an before step hook.
50+
*
51+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
52+
* @param order the order in which this hook should run. Higher numbers are run first
53+
*/
54+
def BeforeStep(tagExpression: String, order: Int) =
55+
new HookBody(HookType.BEFORE_STEP, tagExpression, order, Utils.frame(self))
56+
57+
/** Defines and after hook.
58+
*/
59+
def After: HookBody = After(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)
60+
61+
/** Defines and after hook.
62+
*
63+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
64+
*/
65+
def After(tagExpression: String): HookBody =
66+
After(tagExpression, DEFAULT_AFTER_ORDER)
67+
68+
/** Defines and after hook.
69+
*
70+
* @param order the order in which this hook should run. Higher numbers are run first
71+
*/
72+
def After(order: Int): HookBody = After(EMPTY_TAG_EXPRESSION, order)
73+
74+
/** Defines and after hook.
75+
*
76+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
77+
* @param order the order in which this hook should run. Higher numbers are run first
78+
*/
79+
def After(tagExpression: String, order: Int) =
80+
new HookBody(HookType.AFTER, tagExpression, order, Utils.frame(self))
81+
82+
/** Defines and after step hook.
83+
*/
84+
def AfterStep: HookBody = AfterStep(EMPTY_TAG_EXPRESSION, DEFAULT_AFTER_ORDER)
85+
86+
/** Defines and after step hook.
87+
*
88+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
89+
*/
90+
def AfterStep(tagExpression: String): HookBody =
91+
AfterStep(tagExpression, DEFAULT_AFTER_ORDER)
92+
93+
/** Defines and after step hook.
94+
*
95+
* @param order the order in which this hook should run. Higher numbers are run first
96+
*/
97+
def AfterStep(order: Int): HookBody = AfterStep(EMPTY_TAG_EXPRESSION, order)
98+
99+
/** Defines and after step hook.
100+
*
101+
* @param tagExpression a tag expression, if the expression applies to the current scenario this hook will be executed
102+
* @param order the order in which this hook should run. Higher numbers are run first
103+
*/
104+
def AfterStep(tagExpression: String, order: Int) =
105+
new HookBody(HookType.AFTER_STEP, tagExpression, order, Utils.frame(self))
106+
107+
final class HookBody(
108+
hookType: HookType,
109+
tagExpression: String,
110+
order: Int,
111+
frame: StackTraceElement
112+
) {
113+
114+
// When a HookBody is created, we want to ensure that the apply method is called
115+
// To be able to check this, we notice the registry to expect a hook
116+
registry.expectHook(hookType, frame)
117+
118+
def apply(body: => Unit): Unit = {
119+
apply(_ => body)
120+
}
121+
122+
def apply(body: Scenario => Unit): Unit = {
123+
val details = ScalaHookDetails(tagExpression, order, body)
124+
registry.registerHook(hookType, details, frame)
125+
}
126+
127+
}
128+
129+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.cucumber.scala
2+
3+
sealed trait HookType
4+
5+
object HookType {
6+
7+
case object BEFORE extends HookType
8+
9+
case object BEFORE_STEP extends HookType
10+
11+
case object AFTER extends HookType
12+
13+
case object AFTER_STEP extends HookType
14+
15+
}

0 commit comments

Comments
 (0)