Skip to content

Commit 0e62ef8

Browse files
committed
Merge branch '2020.1' into development
Conflicts: cucumber-scala/src/main/resources/META-INF/plugin.xml
2 parents 7fce2f7 + 4e2f14f commit 0e62ef8

File tree

8 files changed

+102
-84
lines changed

8 files changed

+102
-84
lines changed

.travis.yml

Lines changed: 0 additions & 12 deletions
This file was deleted.

build.gradle

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
ext.versions = [
22
scala: '2.12',
33
scalaFull: '2.12.11',
4-
cucumber: '193.6494.1',
5-
gherkin: '193.6911.14',
6-
idea: '2019.3.4',
7-
scalaPlugin: '2019.3.27',
4+
cucumber: '201.6668.60',
5+
gherkin: '201.6668.60',
6+
idea: '2020.1',
7+
scalaPlugin: '2020.1.27',
88
]
99

1010
ext.libs = [
1111
jUnit : 'junit:junit:4.13',
1212
scala : "org.scala-lang:scala-library:${versions.scalaFull}",
13-
cucumberScala : "info.cukes:cucumber-scala_${versions.scala}:1.2.6",
13+
cucumberScala : "io.cucumber:cucumber-scala_${versions.scala}:4.7.1",
1414
cucumberJUnit : 'io.cucumber:cucumber-junit:5.6.0'
1515
]
1616

1717
subprojects {
1818

1919
repositories {
2020
mavenCentral()
21-
maven {
22-
url "https://oss.sonatype.org/content/repositories/snapshots/"
23-
}
2421
maven {
2522
url 'https://dl.bintray.com/jetbrains/intellij-plugin-service'
2623
}

cucumber-scala/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ plugins {
55

66
group 'com.github.danielwegener'
77
version "${versions.idea}"
8-
sourceCompatibility = 1.8
98

109
dependencies {
1110
compileOnly libs.scala

cucumber-scala/src/main/resources/META-INF/plugin.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<idea-plugin>
44
<id>com.github.danielwegener.cucumber-scala</id>
55
<name>Cucumber for Scala</name>
6-
<version>2019.3.4</version>
7-
<vendor email="[email protected]" url="hhttps://github.com/vbmacher">Peter Jakubčo</vendor>
6+
<version>2020.1</version>
7+
<vendor email="[email protected]" url="https://github.com/vbmacher">Peter Jakubčo</vendor>
88

99
<description><![CDATA[
1010
Enables Reference tracking of glue code when using cucumber-scala DSL.
@@ -34,11 +34,12 @@
3434
<li>2017.3.1: Release for IntelliJ 2017.3.1 (scala-plugin 2017.3.11)</li>
3535
<li>2019.1.3: Release for IntelliJ 2019.1.3 (scala-plugin 2019.1.3)</li>
3636
<li>2019.3.4: Release for IntelliJ 2019.3.4 (scala-plugin 2019.3.27)</li>
37+
<li>2020.1: Release for IntelliJ 2020.1 (scala-plugin 2020.1.27)</li>
3738
</ul>
3839
]]>
3940
</change-notes>
4041

41-
<idea-version since-build="193" until-build="193.*" />
42+
<idea-version since-build="201" until-build="201.*" />
4243

4344
<depends>com.intellij.modules.java</depends>
4445
<depends>gherkin</depends>

cucumber-scala/src/main/scala/com/github/danielwegener/intellij/cucumber/scala/CucumberScalaExtension.scala

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package com.github.danielwegener.intellij.cucumber.scala
22

33
import java.util.{Collection => JavaCollection}
44

5+
import com.github.danielwegener.intellij.cucumber.scala.CucumberScalaExtension.JavaList
56
import com.github.danielwegener.intellij.cucumber.scala.steps.ScalaStepDefinition
67
import com.intellij.openapi.diagnostic.Logger
78
import com.intellij.openapi.module.{Module, ModuleUtilCore}
89
import com.intellij.openapi.project.Project
9-
import com.intellij.psi.search.GlobalSearchScope
1010
import com.intellij.psi.{JavaPsiFacade, PsiElement, PsiFile}
1111
import org.jetbrains.annotations.NotNull
1212
import org.jetbrains.plugins.cucumber.psi.GherkinFile
@@ -25,20 +25,21 @@ import scala.util.Try
2525

2626
object CucumberScalaExtension {
2727
val LOG: Logger = Logger.getInstance(classOf[CucumberScalaExtension])
28+
29+
type JavaList[T] = java.util.List[T]
2830
}
2931

3032
class CucumberScalaExtension extends AbstractCucumberExtension {
31-
32-
val CUCUMBER_RUNTIME_SCALA_STEP_DEF_TRAIT = "cucumber.api.scala.ScalaDsl"
33+
private final val CUCUMBER_RUNTIME_SCALA_STEP_DEF_TRAIT = "cucumber.api.scala.ScalaDsl"
3334

3435
override def isStepLikeFile(@NotNull child: PsiElement, @NotNull parent: PsiElement): Boolean = {
3536
child.isInstanceOf[ScalaFile]
3637
}
3738

3839
override def isWritableStepLikeFile(@NotNull child: PsiElement, @NotNull parent: PsiElement): Boolean = {
39-
4040
child match {
41-
case scalaFile: ScalaFile if Option(scalaFile.getContainingFile).map(_.getVirtualFile).exists(_.isWritable) => true
41+
case scalaFile: ScalaFile =>
42+
Option(scalaFile.getContainingFile).map(_.getVirtualFile).exists(_.isWritable)
4243
case _ => false
4344
}
4445
}
@@ -47,59 +48,69 @@ class CucumberScalaExtension extends AbstractCucumberExtension {
4748
override val getStepFileType: BDDFrameworkType = new BDDFrameworkType(ScalaFileType.INSTANCE)
4849

4950
@NotNull
50-
override def getStepDefinitionCreator: StepDefinitionCreator = throw new UnsupportedOperationException("You cannot automatically create Steps yet.")
51-
52-
override def loadStepsFor(featureFile: PsiFile, module: Module): java.util.List[AbstractStepDefinition] = {
51+
override def getStepDefinitionCreator: StepDefinitionCreator = {
52+
throw new UnsupportedOperationException("You cannot automatically create Steps yet.")
53+
}
5354

54-
val dependenciesScope: GlobalSearchScope = module.getModuleWithDependenciesAndLibrariesScope(true)
55+
override def loadStepsFor(featureFile: PsiFile, module: Module): JavaList[AbstractStepDefinition] = {
5556
val project: Project = featureFile.getProject
5657

57-
val stepDefs = for {
58-
cucumberDslClass <- JavaPsiFacade.getInstance(project).findClasses(CUCUMBER_RUNTIME_SCALA_STEP_DEF_TRAIT, dependenciesScope)
59-
scalaDslInheritingClass <- psi.stubs.util.ScalaInheritors.withStableScalaInheritors(cucumberDslClass).collect { case sc: ScClass => sc; case sct: ScTrait => sct }
60-
glueCodeClass <- classAndItsInheritors(scalaDslInheritingClass, dependenciesScope)
58+
val stepDefinitions = for {
59+
glueCodeClass <- findGlueCodeClass(module, project)
6160
scConstructorBody <- glueCodeClass.extendsBlock.templateBody.toSeq
6261
outerMethodCall <- scConstructorBody.getChildren.collect { case mc: ScMethodCall => mc }
63-
} yield new ScalaStepDefinition(outerMethodCall)
64-
65-
JavaConverters.seqAsJavaList(stepDefs)
66-
67-
}
68-
69-
def classAndItsInheritors(parentOfHierarchy: ScTypeDefinition, scope: GlobalSearchScope): Iterable[ScTypeDefinition] = {
70-
71-
@tailrec
72-
def rec(queue: List[ScTypeDefinition], akku: Set[ScTypeDefinition]): Set[ScTypeDefinition] = {
73-
queue match {
74-
case Nil => akku
75-
case a =>
76-
val newChildren = ScalaInheritors.findInheritorObjects(a.head)
77-
.collect { case sc: ScClass => sc; case sct: ScTrait => sct }
78-
.filterNot(akku.contains _)
79-
rec(a.tail ::: newChildren.toList, akku + a.head)
80-
81-
}
82-
83-
}
62+
} yield ScalaStepDefinition(outerMethodCall)
8463

85-
rec(List(parentOfHierarchy), Set.empty)
64+
JavaConverters.seqAsJavaList(stepDefinitions)
8665
}
8766

8867
override def getStepDefinitionContainers(featureFile: GherkinFile): JavaCollection[_ <: PsiFile] = {
8968
val project: Project = featureFile.getProject
9069
val maybeModule = Option(ModuleUtilCore.findModuleForPsiElement(featureFile))
9170

92-
val stepDefs = for {
71+
val stepFiles = for {
9372
module <- maybeModule.toSeq
94-
searchScope = module.getModuleContentScope
95-
globalSearchScope = module.getModuleWithDependenciesAndLibrariesScope(true)
96-
cucumberDslClass <- JavaPsiFacade.getInstance(project).findClasses(CUCUMBER_RUNTIME_SCALA_STEP_DEF_TRAIT, globalSearchScope).toSeq
97-
scalaDslInheritingClass@(some: ScClass) <- psi.stubs.util.ScalaInheritors.withStableScalaInheritors(cucumberDslClass)
98-
glueCodeClass <- classAndItsInheritors(scalaDslInheritingClass, searchScope)
73+
glueCodeClass <- findGlueCodeClass(module, project)
9974
containingFile <- Try(glueCodeClass.getContainingFile).toOption
10075
} yield containingFile
10176

102-
JavaConverters.seqAsJavaList(stepDefs)
77+
JavaConverters.seqAsJavaList(stepFiles)
78+
}
79+
80+
81+
private def findGlueCodeClass(module: Module, project: Project) = {
82+
val dependencies = module.getModuleWithDependenciesAndLibrariesScope(true)
83+
val psiFacade = JavaPsiFacade.getInstance(project)
84+
85+
for {
86+
cucumberDslClass <- psiFacade.findClasses(CUCUMBER_RUNTIME_SCALA_STEP_DEF_TRAIT, dependencies).toSeq
87+
scalaDslInheritingClass@(some: ScClass) <- psi.stubs.util.ScalaInheritors.withStableScalaInheritors(cucumberDslClass)
88+
glueCodeClass <- classAndItsInheritors(scalaDslInheritingClass)
89+
} yield glueCodeClass
10390
}
10491

92+
private def classAndItsInheritors(parent: ScTypeDefinition): Iterable[ScTypeDefinition] = {
93+
94+
@tailrec
95+
def rec(queue: Seq[ScTypeDefinition], accumulator: Set[ScTypeDefinition]): Set[ScTypeDefinition] = {
96+
queue match {
97+
case Seq() => accumulator
98+
case queueHead +: queueTail =>
99+
100+
val newChildren = ScalaInheritors.findInheritorObjects(queueHead).collect {
101+
case sc: ScClass => sc
102+
case sct: ScTrait => sct
103+
}
104+
105+
val childrenToExplore = newChildren
106+
.map(_.asInstanceOf[ScTypeDefinition])
107+
.diff(accumulator)
108+
.toSeq
109+
110+
rec(queueTail ++ childrenToExplore, accumulator + queueHead)
111+
}
112+
}
113+
114+
rec(Seq(parent), Set.empty)
115+
}
105116
}
Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
package com.github.danielwegener.intellij.cucumber.scala.steps
22

3-
import org.jetbrains.plugins.cucumber.steps.AbstractStepDefinition
4-
import org.jetbrains.plugins.scala.lang.psi.api.expr.ScMethodCall
5-
import org.jetbrains.annotations.Nullable
6-
import com.intellij.psi.PsiElement
7-
import org.jetbrains.plugins.scala.lang.psi.api.base.ScLiteral
83
import java.util
9-
import com.intellij.openapi.diagnostic.Logger
104
import java.util.Collections
115

6+
import com.intellij.openapi.diagnostic.Logger
7+
import com.intellij.psi.PsiElement
8+
import org.jetbrains.annotations.Nullable
9+
import org.jetbrains.plugins.cucumber.steps.AbstractStepDefinition
10+
import org.jetbrains.plugins.scala.lang.psi.api.expr.ScMethodCall
11+
import org.jetbrains.plugins.scala.lang.psi.util.ScalaConstantExpressionEvaluator
12+
1213
object ScalaStepDefinition {
1314
val LOG: Logger = Logger.getInstance(classOf[ScalaStepDefinition])
15+
16+
def apply(scMethodCall: ScMethodCall): ScalaStepDefinition = new ScalaStepDefinition(scMethodCall)
1417
}
1518

1619
class ScalaStepDefinition(scMethod: ScMethodCall) extends AbstractStepDefinition(scMethod) {
1720
import ScalaStepDefinition._
1821

22+
private final val evaluator = new ScalaConstantExpressionEvaluator()
23+
1924
override def getVariableNames: util.List[String] = {
2025
val r = for {
2126
// WHEN("""regexp""") { (arg0:Int, arg1:String) <-- we want to match these
@@ -30,17 +35,16 @@ class ScalaStepDefinition(scMethod: ScMethodCall) extends AbstractStepDefinition
3035

3136
@Nullable
3237
override def getCucumberRegexFromElement(element: PsiElement): String = {
33-
3438
element match {
3539
case mc: ScMethodCall =>
36-
val x = for {
40+
val literals = for {
3741
innerMethodCall <- Some(mc.getEffectiveInvokedExpr).toSeq.collect { case some: ScMethodCall => some }
38-
literalParameter @ (someOther: ScLiteral) <- innerMethodCall.args.exprs
39-
if literalParameter.isString
40-
} yield literalParameter.getValue.toString
41-
x.headOption.orNull
42+
expression <- innerMethodCall.args.exprs
43+
literal <- Option(evaluator.computeConstantExpression(expression, throwExceptionOnOverflow = false)).toSeq
44+
} yield literal.toString
45+
46+
literals.headOption.orNull
4247
case _ => null
4348
}
44-
4549
}
4650
}

example/src/test/resources/cucumber/examples/scalacalculator/basic_arithmetic.feature

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
Feature: Basic Arithmetic
33

44
Scenario: Adding
5-
# Try to change one of the values below to provoke a failure
5+
# Try to change one of the values below to provoke a failure
66
When I add 4 and 5
77
Then the result is 9
88

9+
Scenario: Subtracting
10+
When I sub 4 and 5
11+
Then the result is -1
12+
13+
Scenario: Dividing
14+
When I div 10 by 2
15+
Then the result is 5

example/src/test/scala/RpnCalculatorStepDefinitions.scala

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
2-
31
import cucumber.api.Scenario
4-
import cucumber.api.scala.{ScalaDsl, EN}
2+
import cucumber.api.scala.EN
53
import org.junit.Assert._
64

75
class RpnCalculatorStepDefinitions extends ScalaDslIndirection with EN {
@@ -14,7 +12,20 @@ class RpnCalculatorStepDefinitions extends ScalaDslIndirection with EN {
1412
calc push "+"
1513
}
1614

17-
Then("^the result is (\\d+)$") { expected: Double =>
15+
When("I sub (\\d+)" + " and " + "(\\d+)") {
16+
(arg1: Double, arg2: Double) =>
17+
calc push arg1
18+
calc push arg2
19+
calc push "-"
20+
}
21+
22+
When("I div " + (5 + 5) + " by " + (10 - 8)) {
23+
calc push 10.0
24+
calc push 2.0
25+
calc push "/"
26+
}
27+
28+
Then("^the result is ([+-]?\\d+)$") { expected: Double =>
1829
assertEquals(expected, calc.value, 0.001)
1930
}
2031

0 commit comments

Comments
 (0)