Skip to content

Commit

Permalink
STC: method pointer/reference inferencing
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Dec 3, 2022
1 parent 7f8f14a commit 13ff11b
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.eclipse.jdt.core.groovy.tests.search;

import static org.eclipse.jdt.groovy.core.tests.GroovyBundle.isParrotParser;
import static org.junit.Assert.assertEquals;

import org.codehaus.groovy.ast.MethodNode;
Expand Down Expand Up @@ -49,6 +50,20 @@ public void testCategoryMethod1() {
assertKnown(contents, "with", "org.codehaus.groovy.runtime.DefaultGroovyMethods", "with", DeclarationKind.METHOD);
}

@Test
public void testCategoryMethod2() {
String contents = "@groovy.transform.TypeChecked m() {\nObject.&toString\n}";
assertKnown(contents, "toString", "java.lang.Object", "toString", DeclarationKind.METHOD);

contents = contents.replaceFirst("\n", "java.util.function.Function<Object,String> f = ");
assertKnown(contents, "toString", "java.lang.Object", "toString", DeclarationKind.METHOD);

if (isParrotParser()) {
contents = "@groovy.transform.TypeChecked m() {\njava.util.function.Function<Object,String> f = Object::toString\n}";
assertKnown(contents, "toString", "org.codehaus.groovy.runtime.DefaultGroovyMethods", "toString", DeclarationKind.METHOD);
}
}

@Test
public void testGetterAndField1() {
//@formatter:off
Expand Down Expand Up @@ -131,6 +146,9 @@ public void testGetterAndField2c() {

String contents = "new Other().&getXxx";
assertKnown(contents, "getXxx", "Other", "getXxx", DeclarationKind.METHOD);

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertKnown(contents, "getXxx", "Other", "getXxx", DeclarationKind.METHOD);
}

@Test
Expand Down Expand Up @@ -183,6 +201,9 @@ public void testGetterAndField3c() {

String contents = "new Other().&getXxx";
assertKnown(contents, "getXxx", "Other", "getXxx", DeclarationKind.METHOD);

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertKnown(contents, "getXxx", "Other", "getXxx", DeclarationKind.METHOD);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,31 +866,46 @@ public void testClosure1() {
public void testClosure2() {
String contents = "def fn = 'abc'.&length";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.Integer>");

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.Integer>");
}

@Test
public void testClosure3() {
String contents = "def fn = Collections.&emptyList";
assertType(contents, "fn", "groovy.lang.Closure<java.util.List<java.lang.Object>>");

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertType(contents, "fn", "groovy.lang.Closure<java.util.List<java.lang.Object>>");
}

@Test
public void testClosure4() {
String contents = "def fn = (String.&trim) >> (Class.&forName)";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.Class<?>>");

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.Class<?>>");
}

@Test
public void testClosure5() {
String contents = "def fn = String[].&new";
assertType(contents, "fn", isAtLeastGroovy(30) ? "groovy.lang.Closure<java.lang.String[]>" : "groovy.lang.Closure");

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.String[]>");
}

@Test
public void testClosure6() {
assumeTrue(isParrotParser());
String contents = "def fn = String[]::new";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.String[]>");

contents = "@groovy.transform.TypeChecked m() {" + contents + ";}";
assertType(contents, "fn", "groovy.lang.Closure<java.lang.String[]>");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2891,6 +2891,9 @@ && getType(nameExpr).equals(STRING_TYPE)) {
if ("new".equals(nameText)) {
ClassNode receiverType = getType(expression.getExpression());
if (isClassClassNodeWrappingConcreteType(receiverType)) {
// GRECLIPSE add
receiverType = receiverType.getGenericsTypes()[0].getType();
// GRECLIPSE end
storeType(expression, wrapClosureType(receiverType));
}
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2758,6 +2758,9 @@ && getType(nameExpr).equals(STRING_TYPE)) {
if ("new".equals(nameText)) {
ClassNode receiverType = getType(expression.getExpression());
if (isClassClassNodeWrappingConcreteType(receiverType)) {
// GRECLIPSE add
receiverType = receiverType.getGenericsTypes()[0].getType();
// GRECLIPSE end
storeType(expression, wrapClosureType(receiverType));
}
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2450,9 +2450,10 @@ && isStringType(getType(nameExpr))) {
String nameText = nameExpr.getText();

if ("new".equals(nameText)) {
ClassNode receiverType = getType(expression.getExpression());
if (isClassClassNodeWrappingConcreteType(receiverType)) {
storeType(expression, wrapClosureType(receiverType));
ClassNode type = getType(expression.getExpression());
if (isClassClassNodeWrappingConcreteType(type)){
type = type.getGenericsTypes()[0].getType();
storeType(expression,wrapClosureType(type));
}
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.MethodCall;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.MethodPointerExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.classgen.asm.MopWriter;
Expand Down Expand Up @@ -118,6 +119,13 @@ public TypeLookupResult lookupType(final Expression expr, final VariableScope sc
methodTarget = enclosingNode.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (methodTarget == null) methodTarget = getMopMethodTarget((MethodCallExpression) enclosingNode);
if (methodTarget == null) methodTarget = ((MethodCallExpression) enclosingNode).getMethodTarget();
//
} else if (enclosingNode instanceof MethodPointerExpression && ((MethodPointerExpression) enclosingNode).getMethodName() == expr) {
List<MethodNode> methods = enclosingNode.getNodeMetaData(MethodNode.class);
if (methods != null) {
methodTarget = methods.get(0);
if (methods.size() > 1) confidence = TypeConfidence.LOOSELY_INFERRED;
}
}

if (methodTarget instanceof ExtensionMethodNode) {
Expand All @@ -127,8 +135,9 @@ public TypeLookupResult lookupType(final Expression expr, final VariableScope sc

if (methodTarget instanceof MethodNode) {
declaration = ((MethodNode) methodTarget).getOriginal();
declaringType = ((MethodNode) methodTarget).getOriginal().getDeclaringClass();
inferredType = enclosingNode.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
declaringType = ((MethodNode) declaration).getDeclaringClass();
if (!(enclosingNode instanceof MethodPointerExpression)) // ignore Closure<Type>
inferredType = enclosingNode.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
if (inferredType == null) inferredType = ((MethodNode) methodTarget).getReturnType();
}
}
Expand Down

0 comments on commit 13ff11b

Please sign in to comment.