You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/10/04 20:09:11 UTC
[groovy] branch GROOVY-8258 updated (85879be -> fcb8590)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch GROOVY-8258
in repository https://gitbox.apache.org/repos/asf/groovy.git.
from 85879be GROOVY-8258: test `stream` method and tweak tests
new a950f51 GROOVY-8258: mark backend classes as internal
new fcb8590 GROOVY-8258: Implement the very basic LINQ
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../apache/groovy/linq/LinqGroovyMethods.groovy | 104 ++++++++++++++++++++-
.../groovy/org/apache/groovy/linq/Queryable.java | 2 +
.../groovy/linq/provider/QueryableCollection.java | 7 ++
.../groovy/org/apache/groovy/linq/LinqTest.groovy | 9 +-
4 files changed, 118 insertions(+), 4 deletions(-)
[groovy] 02/02: GROOVY-8258: Implement the very basic LINQ
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-8258
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit fcb8590583181d9e062e87b86cad6592eb0bf080
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Oct 5 04:08:42 2020 +0800
GROOVY-8258: Implement the very basic LINQ
---
.../apache/groovy/linq/LinqGroovyMethods.groovy | 104 ++++++++++++++++++++-
.../groovy/linq/provider/QueryableCollection.java | 5 +
.../groovy/org/apache/groovy/linq/LinqTest.groovy | 9 +-
3 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
index 224c958..cd6b502 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/LinqGroovyMethods.groovy
@@ -18,16 +18,116 @@
*/
package org.apache.groovy.linq
+import groovy.transform.ToString
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.expr.ArgumentListExpression
import org.codehaus.groovy.ast.expr.ClosureExpression
-import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.MethodCallExpression
+import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.BlockStatement
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.ast.stmt.Statement
import org.codehaus.groovy.macro.runtime.Macro
import org.codehaus.groovy.macro.runtime.MacroContext
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt
+
class LinqGroovyMethods {
@Macro
static Expression LINQ(MacroContext ctx, final ClosureExpression closureExpression) {
- return macro { 'TODO LINQ' }
+ BlockStatement code = (BlockStatement) closureExpression.getCode()
+ List<Statement> statementList = code.getStatements()
+
+ LinqContext linqContext = new LinqContext()
+ for (Statement statement : statementList) {
+ ExpressionStatement expressionStatement = (ExpressionStatement) statement
+ MethodCallExpression methodCallExpression = (MethodCallExpression) expressionStatement.getExpression()
+
+ String methodName = methodCallExpression.getMethodAsString()
+ switch (methodName) {
+ case 'from': {
+ break
+ }
+ case 'of': {
+ MethodCallExpression fromMethodCallExpression = methodCallExpression.getObjectExpression()
+ VariableExpression aliasVariable = (VariableExpression) ((ArgumentListExpression) fromMethodCallExpression.getArguments()).getExpression(0)
+ Expression dataSourceExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
+ linqContext.addFrom(aliasVariable, dataSourceExpression)
+ break
+ }
+ case 'where': {
+ Expression conditionExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
+ linqContext.addWhere(conditionExpression)
+ break
+ }
+ case 'select': {
+ Expression selectExpression = ((ArgumentListExpression) methodCallExpression.getArguments()).getExpression(0)
+ linqContext.addSelect(selectExpression)
+ break
+ }
+ default: {
+ break
+ }
+ }
+ }
+
+ constructLinqMethodCalls(linqContext)
+ }
+
+ private static constructLinqMethodCalls(LinqContext linqContext) {
+ Map.Entry<VariableExpression, Expression> fromEntry = linqContext.fromMap.entrySet().toList().get(0)
+ VariableExpression aliasVariable = fromEntry.key
+
+ MethodCallExpression from = macro {
+ org.apache.groovy.linq.provider.QueryableCollection
+ .from($v { fromEntry.value })
+ }
+
+ MethodCallExpression where =
+ callX(
+ from,
+ "where",
+ closureX(
+ params(param(ClassHelper.DYNAMIC_TYPE, aliasVariable.name)),
+ stmt(linqContext.whereList[0])
+ )
+ )
+
+ MethodCallExpression select =
+ callX(
+ where,
+ "select",
+ closureX(
+ params(param(ClassHelper.DYNAMIC_TYPE, aliasVariable.name)),
+ stmt(linqContext.selectList[0])
+ )
+ )
+
+ return select
+ }
+
+ @ToString(includeNames=true)
+ static class LinqContext {
+ Map<VariableExpression, Expression> fromMap = new LinkedHashMap<>()
+ List<Expression> whereList = new ArrayList<>()
+ List<Expression> selectList = new ArrayList<>()
+
+ void addFrom(VariableExpression aliasVariable, Expression dataSourceExpression) {
+ fromMap.put(aliasVariable, dataSourceExpression)
+ }
+
+ void addWhere(Expression... conditionExpressions) {
+ whereList.addAll(conditionExpressions)
+ }
+
+ void addSelect(Expression... selectExpressions) {
+ selectList.addAll(selectExpressions)
+ }
}
}
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
index 0eb3239..9d5d19d 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
@@ -243,4 +243,9 @@ public class QueryableCollection<T> implements Queryable<T>, Iterable<T> {
private static <T> Iterable<T> toIterable(Stream<T> sourceStream) {
return sourceStream::iterator;
}
+
+ @Override
+ public String toString() {
+ return toList().toString();
+ }
}
diff --git a/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/LinqTest.groovy b/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/LinqTest.groovy
index 701f1c6..a19d39e 100644
--- a/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/LinqTest.groovy
+++ b/subprojects/groovy-linq/src/test/groovy/org/apache/groovy/linq/LinqTest.groovy
@@ -28,9 +28,14 @@ import static groovy.test.GroovyAssert.assertScript
@CompileStatic
class LinqTest {
@Test
- void testLinqMacroMethod() {
+ void "testLinqMacroMethod - from where select"() {
assertScript '''
- assert 'TODO LINQ' == LINQ {}
+ def numbers = [0, 1, 2, 3, 4, 5]
+ assert [2, 4, 6] == LINQ {
+ from n of numbers
+ where n > 0 && n <= 3
+ select n * 2
+ }.toList()
'''
}
}
[groovy] 01/02: GROOVY-8258: mark backend classes as internal
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-8258
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit a950f5162701035b2b8b652d61c1627ce462f428
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Oct 5 01:10:32 2020 +0800
GROOVY-8258: mark backend classes as internal
---
.../groovy-linq/src/main/groovy/org/apache/groovy/linq/Queryable.java | 2 ++
.../groovy/org/apache/groovy/linq/provider/QueryableCollection.java | 2 ++
2 files changed, 4 insertions(+)
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/Queryable.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/Queryable.java
index 95d67f9..56803ac 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/Queryable.java
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/Queryable.java
@@ -19,6 +19,7 @@
package org.apache.groovy.linq;
import groovy.lang.Tuple2;
+import groovy.transform.Internal;
import java.math.BigDecimal;
import java.util.List;
@@ -34,6 +35,7 @@ import java.util.stream.Stream;
* @param <T> the type of Queryable element
* @since 4.0.0
*/
+@Internal
public interface Queryable<T> {
<U> Queryable<Tuple2<T, U>> innerJoin(Queryable<? extends U> queryable, BiPredicate<? super T, ? super U> joiner);
diff --git a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
index 282e68b..0eb3239 100644
--- a/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
+++ b/subprojects/groovy-linq/src/main/groovy/org/apache/groovy/linq/provider/QueryableCollection.java
@@ -20,6 +20,7 @@ package org.apache.groovy.linq.provider;
import groovy.lang.Tuple;
import groovy.lang.Tuple2;
+import groovy.transform.Internal;
import org.apache.groovy.linq.Queryable;
import java.math.BigDecimal;
@@ -40,6 +41,7 @@ import java.util.stream.StreamSupport;
* @param <T> the type of Queryable element
* @since 4.0.0
*/
+@Internal
public class QueryableCollection<T> implements Queryable<T>, Iterable<T> {
private final Iterable<T> sourceIterable;
private Stream<T> sourceStream;