diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.2-groovy-2.4.jar b/base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.3-groovy-2.4.jar
similarity index 77%
rename from base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.2-groovy-2.4.jar
rename to base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.3-groovy-2.4.jar
index c84e919c3c..2a220d01ca 100644
Binary files a/base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.2-groovy-2.4.jar and b/base-test/org.eclipse.jdt.groovy.core.tests.builder/lib/spock-core-1.3-groovy-2.4.jar differ
diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/builder/BasicGroovyBuildTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/builder/BasicGroovyBuildTests.java
index ad9aeadfa5..05eccc0309 100644
--- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/builder/BasicGroovyBuildTests.java
+++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/builder/BasicGroovyBuildTests.java
@@ -1998,21 +1998,18 @@ public void testSpock_GRE558() throws Exception {
assumeFalse(isAtLeastGroovy(30)); // TODO: Remove when spock-core supports Groovy 3
IPath[] paths = createSimpleProject("Project", true);
- env.addJar(paths[0], "lib/spock-core-1.2-groovy-2.4.jar");
+ env.addJar(paths[0], "lib/spock-core-1.3-groovy-2.4.jar");
env.addEntry(paths[0], JavaCore.newContainerEntry(new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4")));
env.addGroovyClass(paths[1], "", "MyTest",
//@formatter:off
- "import org.junit.runner.RunWith\n" +
- "import spock.lang.Specification\n" +
- "\n" +
- "final class MyTest extends Specification {\n" +
- " def aField\n" +
- " def aMethod() {\n" +
- " expect:\n" +
- " println 'hello'\n" +
+ "final class MyTest extends spock.lang.Specification {\n" +
+ " def prop\n" +
+ " def meth() {\n" +
+ " expect:\n" +
+ " 'hello' != 'world'\n" +
" }\n" +
- " static void main(String[] argv) {\n" +
+ " static main(args) {\n" +
" print 'success'\n" +
" }\n" +
"}\n");
@@ -2034,35 +2031,27 @@ public void testSpock_GRE605_1() throws Exception {
assumeFalse(isAtLeastGroovy(30)); // TODO: Remove when spock-core supports Groovy 3
IPath[] paths = createSimpleProject("Project", true);
- env.addJar(paths[0], "lib/spock-core-1.2-groovy-2.4.jar");
+ env.addJar(paths[0], "lib/spock-core-1.3-groovy-2.4.jar");
env.addEntry(paths[0], JavaCore.newContainerEntry(new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4")));
env.addGroovyClass(paths[1], "", "FoobarSpec",
//@formatter:off
- "import spock.lang.Specification\n" +
- "\n" +
- "class FoobarSpec extends Specification {\n" +
- " \n" +
- " Foobar barbar\n" +
- " \n" +
- " def example() {\n" +
- " when: \n" +
- " def foobar = new Foobar()\n" +
- " \n" +
- " then:\n" +
- " foobar.baz == 42\n" +
- " }\n" +
+ "class FoobarSpec extends spock.lang.Specification {\n" +
+ " private Foobar field\n" +
+ " def example() {\n" +
+ " when: \n" +
+ " def foobar = new Foobar()\n" +
" \n" +
+ " then:\n" +
+ " foobar.baz == 42\n" +
+ " }\n" +
"}");
//@formatter:on
env.addGroovyClass(paths[1], "", "Foobar",
//@formatter:off
"class Foobar {\n" +
- "\n" +
- "def baz = 42\n" +
- "//def quux = 36\n" +
- "\n" +
+ " def baz = 42\n" +
"}\n");
//@formatter:on
@@ -2077,10 +2066,8 @@ public void testSpock_GRE605_1() throws Exception {
env.addGroovyClass(paths[1], "", "Foobar",
//@formatter:off
"class Foobar {\n" +
- "\n" +
- "def baz = 42\n" +
- "def quux = 36\n" +
- "\n" +
+ " def baz = 42\n" +
+ " def xyz = 36\n" +
"}\n");
//@formatter:on
@@ -2106,34 +2093,27 @@ public void testSpock_GRE605_2() throws Exception {
assumeFalse(isAtLeastGroovy(30)); // TODO: Remove when spock-core supports Groovy 3
IPath[] paths = createSimpleProject("Project", true);
- env.addJar(paths[0], "lib/spock-core-1.2-groovy-2.4.jar");
+ env.addJar(paths[0], "lib/spock-core-1.3-groovy-2.4.jar");
env.addEntry(paths[0], JavaCore.newContainerEntry(new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4")));
env.addGroovyClass(paths[1], "", "FoobarSpec",
//@formatter:off
- "import spock.lang.Specification\n" +
- "\n" +
- "class FoobarSpec extends Specification {\n" +
- " \n" +
- " Foobar foob\n" +
- " def example() {\n" +
- " when: \n" +
- " def foobar = new Foobar()\n" +
- " \n" +
- " then:\n" +
- " foobar.baz == 42\n" +
- " }\n" +
+ "class FoobarSpec extends spock.lang.Specification {\n" +
+ " private Foobar field\n" +
+ " def example() {\n" +
+ " given: \n" +
+ " def foobar = new Foobar()\n" +
" \n" +
+ " expect:\n" +
+ " foobar.baz == 42\n" +
+ " }\n" +
"}");
//@formatter:on
env.addGroovyClass(paths[1], "", "Foobar",
//@formatter:off
"class Foobar {\n" +
- "\n" +
- "def baz = 42\n" +
- "//def quux = 36\n" +
- "\n" +
+ " def baz = 42\n" +
"}\n");
//@formatter:on
@@ -2144,10 +2124,8 @@ public void testSpock_GRE605_2() throws Exception {
env.addGroovyClass(paths[1], "", "Foobar",
//@formatter:off
"class Foobar {\n" +
- "\n" +
- "def baz = 42\n" +
- "def quux = 36\n" +
- "\n" +
+ " def baz = 42\n" +
+ " def xyz = 36\n" +
"}\n");
//@formatter:on
diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/SpockInferencingTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/SpockInferencingTests.java
index 8b0eb33dd8..7c25f37c7d 100644
--- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/SpockInferencingTests.java
+++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/SpockInferencingTests.java
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,32 +21,18 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.JavaCore;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public final class SpockInferencingTests extends InferencingTestSuite {
- private String xforms;
-
@Before
public void setUp() throws Exception {
assumeFalse(isAtLeastGroovy(30)); // TODO: Remove when spock-core supports Groovy 3
IPath projectPath = project.getFullPath();
- env.addJar(projectPath, "lib/spock-core-1.2-groovy-2.4.jar");
+ env.addJar(projectPath, "lib/spock-core-1.3-groovy-2.4.jar");
env.addEntry(projectPath, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4")));
-
- xforms = System.setProperty("greclipse.globalTransformsInReconcile", "org.spockframework.compiler.SpockTransform");
- }
-
- @After
- public void tearDown() {
- if (xforms == null) {
- System.clearProperty("greclipse.globalTransformsInReconcile");
- } else {
- System.setProperty("greclipse.globalTransformsInReconcile", xforms);
- }
}
@Test
@@ -54,6 +40,7 @@ public void testBasics() throws Exception {
createUnit("foo", "Bar", "package foo; class Bar {\n Integer baz\n}");
String source =
+ //@formatter:off
"final class SpockTests extends spock.lang.Specification {\n" +
" void 'test the basics'() {\n" +
" given:\n" +
@@ -66,6 +53,7 @@ public void testBasics() throws Exception {
" bar != new foo.Bar(baz:42)\n" +
" }\n" +
"}\n";
+ //@formatter:on
int offset = source.indexOf("bar");
assertType(source, offset, offset + 3, "foo.Bar");
@@ -74,9 +62,75 @@ public void testBasics() throws Exception {
assertType(source, offset, offset + 3, "foo.Bar");
}
+ @Test
+ public void testEqualsCheck() throws Exception {
+ createUnit("foo", "Bar", "package foo; class Bar {\n Integer baz\n}");
+
+ String source =
+ //@formatter:off
+ "final class SpockTests extends spock.lang.Specification {\n" +
+ " void 'test the property'() {\n" +
+ " given:\n" +
+ " def bar = new foo.Bar()\n" +
+ " \n" +
+ " expect:\n" +
+ " !bar.equals(null)\n" +
+ " }\n" +
+ "}\n";
+ //@formatter:on
+
+ int offset = source.lastIndexOf("equals");
+ assertType(source, offset, offset + 6, "java.lang.Boolean");
+ assertDeclaringType(source, offset, offset + 6, "java.lang.Object");
+ }
+
+ @Test
+ public void testGetterCheck() throws Exception {
+ createUnit("foo", "Bar", "package foo; class Bar {\n Integer baz\n}");
+
+ String source =
+ //@formatter:off
+ "final class SpockTests extends spock.lang.Specification {\n" +
+ " void 'test the property'() {\n" +
+ " given:\n" +
+ " def bar = new foo.Bar(baz: 42)\n" +
+ " \n" +
+ " expect:\n" +
+ " bar.getBaz() == 42\n" +
+ " }\n" +
+ "}\n";
+ //@formatter:on
+
+ int offset = source.lastIndexOf("getBaz");
+ assertType(source, offset, offset + 6, "java.lang.Integer");
+ assertDeclaringType(source, offset, offset + 6, "foo.Bar");
+ }
+
+ @Test
+ public void testPropertyCheck() throws Exception {
+ createUnit("foo", "Bar", "package foo; class Bar {\n Integer baz\n}");
+
+ String source =
+ //@formatter:off
+ "final class SpockTests extends spock.lang.Specification {\n" +
+ " void 'test the property'() {\n" +
+ " given:\n" +
+ " def bar = new foo.Bar(baz: 42)\n" +
+ " \n" +
+ " expect:\n" +
+ " bar.baz == 42\n" +
+ " }\n" +
+ "}\n";
+ //@formatter:on
+
+ int offset = source.lastIndexOf("baz");
+ assertType(source, offset, offset + 3, "java.lang.Integer");
+ }
+
@Test // https://github.com/groovy/groovy-eclipse/issues/812
- public void testDataTable() {
+ public void testDataTableChecks() {
String source =
+ //@formatter:off
"final class SpockTests extends spock.lang.Specification {\n" +
" @spock.lang.Unroll\n" +
" void 'test #a == #b'() {\n" +
@@ -88,6 +142,7 @@ public void testDataTable() {
" 2 | a\n" +
" }\n" +
"}\n";
+ //@formatter:on
int offset = source.indexOf("a == b");
assertType(source, offset, offset + 1, "java.lang.Object");
diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java
index 2edcf76970..e7ba6c40e5 100644
--- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java
+++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java
@@ -1429,17 +1429,26 @@ public void visitMethodCallExpression(MethodCallExpression node) {
visitMethodOverrides(type);
}
- MethodNode meth; // if return type depends on any Closure argument return types, deal with that now
- if (t.declaration instanceof MethodNode && (meth = (MethodNode) t.declaration).getGenericsTypes() != null &&
- Arrays.stream(meth.getParameters()).anyMatch(p -> p.getType().equals(VariableScope.CLOSURE_CLASS_NODE))) {
- scope.setMethodCallArgumentTypes(getMethodCallArgumentTypes(node));
- scope.setMethodCallGenericsTypes(getMethodCallGenericsTypes(node));
- try {
- boolean isStatic = (node.getObjectExpression() instanceof ClassExpression);
- returnType = lookupExpressionType(node.getMethod(), objExprType, isStatic, scope).type;
- } finally {
- scope.setMethodCallArgumentTypes(null);
- scope.setMethodCallGenericsTypes(null);
+ if (t.declaration instanceof MethodNode) {
+ MethodNode meth = (MethodNode) t.declaration;
+ // if return type depends on any Closure argument return types, deal with that
+ if (meth.getGenericsTypes() != null && Arrays.stream(meth.getParameters())
+ .anyMatch(p -> p.getType().equals(VariableScope.CLOSURE_CLASS_NODE))) {
+ scope.setMethodCallArgumentTypes(getMethodCallArgumentTypes(node));
+ scope.setMethodCallGenericsTypes(getMethodCallGenericsTypes(node));
+ try {
+ boolean isStatic = (node.getObjectExpression() instanceof ClassExpression);
+ returnType = lookupExpressionType(node.getMethod(), objExprType, isStatic, scope).type;
+ } finally {
+ scope.setMethodCallArgumentTypes(null);
+ scope.setMethodCallGenericsTypes(null);
+ }
+ } else if (t.declaringType.getName().equals("org.spockframework.runtime.ValueRecorder")) {
+ switch (meth.getName()) {
+ case "record":
+ case "realizeNas":
+ returnType = primaryTypeStack.removeLast();
+ }
}
}
@@ -2374,7 +2383,44 @@ private boolean isPrimaryExpression(Expression expr) {
result[0] = (expr == statement.getExpression());
}
});
- return result[0];
+ if (result[0]) return true;
+ }
+ return isSpockValueRecorderArgument(expr);
+ }
+
+ /**
+ * Spock rewrites the "expect" statements from foo.bar == baz
to:
+ *
+ * org.spockframework.runtime.SpockRuntime.verifyCondition( + * $spock_errorCollector, + * $spock_valueRecorder.reset(), + * foo == bar.baz, 14, 5, null, + * $spock_valueRecorder.record( + * $spock_valueRecorder.startRecordingValue(3), + * ( + * $spock_valueRecorder.record( + * $spock_valueRecorder.startRecordingValue(1), + * $spock_valueRecorder.record( + * $spock_valueRecorder.startRecordingValue(0), foo).bar + * ) == $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), baz) + * ) + * ) + * ) + *+ * + * ValueRecorder.record is defined as:
public Object record(int index, Object value)
.
+ * So, we want to save the inferred type of the last argument so it can be used as the return type.
+ */
+ private boolean isSpockValueRecorderArgument(Expression expr) {
+ VariableScope.CallAndType cat = scopes.getLast().getEnclosingMethodCallExpression();
+ if (cat != null && cat.declaration instanceof MethodNode && cat.declaringType.getName().equals("org.spockframework.runtime.ValueRecorder")) {
+ ArgumentListExpression args = (ArgumentListExpression) cat.call.getArguments();
+ MethodNode meth = (MethodNode) cat.declaration;
+ switch (meth.getName()) {
+ case "record":
+ case "realizeNas":
+ return expr == DefaultGroovyMethods.last(args.getExpressions());
+ }
}
return false;
}
diff --git a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy
index 77c7a94078..df21cae446 100644
--- a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy
+++ b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy
@@ -1,11 +1,11 @@
/*
- * Copyright 2009-2018 the original author or authors.
+ * Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -177,13 +177,13 @@ abstract class GroovyEclipseTestSuite {
testProject.addClasspathEntry(JavaCore.newContainerEntry(path, true))
}
- protected final void addJUnit(int n) {
+ protected final void addJUnit(int n) { assert n >= 3 && n <= 5
addClasspathContainer(new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/$n"))
}
protected final void addSpock() {
def bundle = Platform.getBundle('org.eclipse.jdt.groovy.core.tests.builder')
- URL jarUrl = FileLocator.toFileURL(bundle.getEntry('lib/spock-core-1.2-groovy-2.4.jar'))
+ URL jarUrl = FileLocator.toFileURL(bundle.getEntry('lib/spock-core-1.3-groovy-2.4.jar'))
testProject.addExternalLibrary(new Path(jarUrl.file))
}