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/06 13:36:31 UTC
[groovy] 06/22: GROOVY-8258: Implement the very basic LINQ
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 1ab90b54e7ed1b68f7eb31cb1398acb3a884ea97
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()
'''
}
}