You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by tw...@apache.org on 2016/08/08 09:13:56 UTC
flink git commit: [FLINK-3138] [types] Method References are not
supported as lambda expressions
Repository: flink
Updated Branches:
refs/heads/master 8d25c6414 -> ff777084b
[FLINK-3138] [types] Method References are not supported as lambda expressions
This closes #2329.
Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/ff777084
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/ff777084
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/ff777084
Branch: refs/heads/master
Commit: ff777084ba2e1f1070ce5ecbc5afc122756ba851
Parents: 8d25c64
Author: twalthr <tw...@apache.org>
Authored: Wed Aug 3 14:18:40 2016 +0200
Committer: twalthr <tw...@apache.org>
Committed: Mon Aug 8 11:11:45 2016 +0200
----------------------------------------------------------------------
.../flink/api/java/typeutils/TypeExtractor.java | 30 +++++++++--
.../java/type/lambdas/LambdaExtractionTest.java | 56 +++++++++++++++++++-
.../javaApiOperators/lambdas/MapITCase.java | 12 ++---
3 files changed, 85 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flink/blob/ff777084/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java
----------------------------------------------------------------------
diff --git a/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java b/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java
index 9d30743..aaa8e0d 100644
--- a/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java
+++ b/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java
@@ -345,12 +345,22 @@ public class TypeExtractor {
if (m != null) {
// check for lambda type erasure
validateLambdaGenericParameters(m);
-
+
// parameters must be accessed from behind, since JVM can add additional parameters e.g. when using local variables inside lambda function
final int paramLen = m.getGenericParameterTypes().length - 1;
- final Type input = (outputTypeArgumentIndex >= 0) ? m.getGenericParameterTypes()[paramLen - 1] : m.getGenericParameterTypes()[paramLen];
- validateInputType((inputTypeArgumentIndex >= 0) ? extractTypeArgument(input, inputTypeArgumentIndex) : input, inType);
- if(function instanceof ResultTypeQueryable) {
+
+ // method references "this" implicitly
+ if (paramLen < 0) {
+ // methods declaring class can also be a super class of the input type
+ // we only validate if the method exists in input type
+ validateInputContainsMethod(m, inType);
+ }
+ else {
+ final Type input = (outputTypeArgumentIndex >= 0) ? m.getGenericParameterTypes()[paramLen - 1] : m.getGenericParameterTypes()[paramLen];
+ validateInputType((inputTypeArgumentIndex >= 0) ? extractTypeArgument(input, inputTypeArgumentIndex) : input, inType);
+ }
+
+ if (function instanceof ResultTypeQueryable) {
return ((ResultTypeQueryable<OUT>) function).getProducedType();
}
return new TypeExtractor().privateCreateTypeInfo(
@@ -1234,7 +1244,17 @@ public class TypeExtractor {
}
}
}
-
+
+ private static void validateInputContainsMethod(Method m, TypeInformation<?> typeInfo) {
+ List<Method> methods = getAllDeclaredMethods(typeInfo.getTypeClass());
+ for (Method method : methods) {
+ if (method.equals(m)) {
+ return;
+ }
+ }
+ throw new InvalidTypesException("Type contains no method '" + m.getName() + "'.");
+ }
+
// --------------------------------------------------------------------------------------------
// Utility methods
// --------------------------------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flink/blob/ff777084/flink-java8/src/test/java/org/apache/flink/api/java/type/lambdas/LambdaExtractionTest.java
----------------------------------------------------------------------
diff --git a/flink-java8/src/test/java/org/apache/flink/api/java/type/lambdas/LambdaExtractionTest.java b/flink-java8/src/test/java/org/apache/flink/api/java/type/lambdas/LambdaExtractionTest.java
index b4fffed..64b7ae7 100644
--- a/flink-java8/src/test/java/org/apache/flink/api/java/type/lambdas/LambdaExtractionTest.java
+++ b/flink-java8/src/test/java/org/apache/flink/api/java/type/lambdas/LambdaExtractionTest.java
@@ -70,13 +70,17 @@ public class LambdaExtractionTest {
}
};
- MapFunction<String, Integer> lambda = Integer::parseInt;
+ MapFunction<String, Integer> staticLambda = Integer::parseInt;
+ MapFunction<Integer, String> instanceLambda = Object::toString;
+ MapFunction<String, Integer> constructorLambda = Integer::new;
assertNull(FunctionUtils.checkAndExtractLambdaMethod(anonymousFromInterface));
assertNull(FunctionUtils.checkAndExtractLambdaMethod(anonymousFromClass));
assertNull(FunctionUtils.checkAndExtractLambdaMethod(fromProperClass));
assertNull(FunctionUtils.checkAndExtractLambdaMethod(fromDerived));
- assertNotNull(FunctionUtils.checkAndExtractLambdaMethod(lambda));
+ assertNotNull(FunctionUtils.checkAndExtractLambdaMethod(staticLambda));
+ assertNotNull(FunctionUtils.checkAndExtractLambdaMethod(instanceLambda));
+ assertNotNull(FunctionUtils.checkAndExtractLambdaMethod(constructorLambda));
assertNotNull(FunctionUtils.checkAndExtractLambdaMethod(STATIC_LAMBDA));
}
catch (Exception e) {
@@ -248,4 +252,52 @@ public class LambdaExtractionTest {
Assert.assertTrue(ti instanceof MissingTypeInfo);
}
+ public static class MyType {
+ private int key;
+
+ public int getKey() {
+ return key;
+ }
+
+ public void setKey(int key) {
+ this.key = key;
+ }
+
+ protected int getKey2() {
+ return 0;
+ }
+ }
+
+ @Test
+ public void testInstanceMethodRefSameType() {
+ MapFunction<MyType, Integer> f = MyType::getKey;
+ TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeExtractor.createTypeInfo(MyType.class));
+ Assert.assertEquals(ti, BasicTypeInfo.INT_TYPE_INFO);
+ }
+
+ @Test
+ public void testInstanceMethodRefSuperType() {
+ MapFunction<Integer, String> f = Object::toString;
+ TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, BasicTypeInfo.INT_TYPE_INFO);
+ Assert.assertEquals(ti, BasicTypeInfo.STRING_TYPE_INFO);
+ }
+
+ public static class MySubtype extends MyType {
+ public boolean test;
+ }
+
+ @Test
+ public void testInstanceMethodRefSuperTypeProtected() {
+ MapFunction<MySubtype, Integer> f = MyType::getKey2;
+ TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, TypeExtractor.createTypeInfo(MySubtype.class));
+ Assert.assertEquals(ti, BasicTypeInfo.INT_TYPE_INFO);
+ }
+
+ @Test
+ public void testConstructorMethodRef() {
+ MapFunction<String, Integer> f = Integer::new;
+ TypeInformation<?> ti = TypeExtractor.getMapReturnTypes(f, BasicTypeInfo.STRING_TYPE_INFO);
+ Assert.assertEquals(ti, BasicTypeInfo.INT_TYPE_INFO);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/flink/blob/ff777084/flink-java8/src/test/java/org/apache/flink/test/javaApiOperators/lambdas/MapITCase.java
----------------------------------------------------------------------
diff --git a/flink-java8/src/test/java/org/apache/flink/test/javaApiOperators/lambdas/MapITCase.java b/flink-java8/src/test/java/org/apache/flink/test/javaApiOperators/lambdas/MapITCase.java
index d4cf585..cda1f1c 100644
--- a/flink-java8/src/test/java/org/apache/flink/test/javaApiOperators/lambdas/MapITCase.java
+++ b/flink-java8/src/test/java/org/apache/flink/test/javaApiOperators/lambdas/MapITCase.java
@@ -24,10 +24,10 @@ import org.apache.flink.test.util.JavaProgramTestBase;
public class MapITCase extends JavaProgramTestBase {
- private static final String EXPECTED_RESULT = "bb\n" +
- "bb\n" +
- "bc\n" +
- "bd\n";
+ private static final String EXPECTED_RESULT = "22\n" +
+ "22\n" +
+ "23\n" +
+ "24\n";
private String resultPath;
@@ -40,8 +40,8 @@ public class MapITCase extends JavaProgramTestBase {
protected void testProgram() throws Exception {
final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
- DataSet<String> stringDs = env.fromElements("aa", "ab", "ac", "ad");
- DataSet<String> mappedDs = stringDs.map (s -> s.replace("a", "b"));
+ DataSet<Integer> stringDs = env.fromElements(11, 12, 13, 14);
+ DataSet<String> mappedDs = stringDs.map(Object::toString).map (s -> s.replace("1", "2"));
mappedDs.writeAsText(resultPath);
env.execute();
}