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();
 	}