public void visitMethodCallExpression()

in subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBuilder.java [154:373]


    public void visitMethodCallExpression(MethodCallExpression call) {
        final String methodName = call.getMethodAsString();
        if (KW_OVER.equals(methodName)) {
            visitingOverClause = true;
        }
        super.visitMethodCallExpression(call);
        if (KW_OVER.equals(methodName)) {
            visitingOverClause = false;
        }

        if (!KEYWORD_SET.contains(methodName)) {
            ignoredMethodCallExpressionList.add(call);
            return;
        }

        if (KW_FROM.equals(methodName)) {
            final GinqExpression ginqExpression = new GinqExpression();
            ginqExpression.setSourcePosition(call);
            ginqExpressionStack.push(ginqExpression); // store the result
        }

        GinqExpression currentGinqExpression = ginqExpressionStack.peek();
        AbstractGinqExpression latestGinqExpressionClause = getLatestGinqExpressionClause(call);

        if (KW_FROM.equals(methodName)  || JoinExpression.isJoinExpression(methodName)) {
            ArgumentListExpression arguments = (ArgumentListExpression) call.getArguments();
            if (arguments.getExpressions().size() != 1) {
                this.collectSyntaxError(
                        new GinqSyntaxError(
                                "Only 1 argument expected for `" + methodName + "`, e.g. `" + methodName + " n in nums`",
                                call.getLineNumber(), call.getColumnNumber()
                        )
                );
            }
            final Expression expression = arguments.getExpression(0);
            if (!(expression instanceof BinaryExpression
                    && ((BinaryExpression) expression).getOperation().getType() == Types.KEYWORD_IN)) {
                this.collectSyntaxError(
                        new GinqSyntaxError(
                                "`in` is expected for `" + methodName + "`, e.g. `" + methodName + " n in nums`",
                                call.getLineNumber(), call.getColumnNumber()
                        )
                );
            }
            BinaryExpression binaryExpression = (BinaryExpression) expression;
            Expression aliasExpr = binaryExpression.getLeftExpression();
            Expression dataSourceExpr = binaryExpression.getRightExpression();

            DataSourceExpression dataSourceExpression;
            if (KW_FROM.equals(methodName)) {
                dataSourceExpression = new FromExpression(aliasExpr, dataSourceExpr);
                currentGinqExpression.setFromExpression((FromExpression) dataSourceExpression);
            } else {
                dataSourceExpression = new JoinExpression(methodName, aliasExpr, dataSourceExpr);
                currentGinqExpression.addJoinExpression((JoinExpression) dataSourceExpression);
            }
            dataSourceExpression.setSourcePosition(call.getMethod());
            setLatestGinqExpressionClause(dataSourceExpression);

            return;
        }

        if (KW_WHERE.equals(methodName) || KW_ON.equals(methodName) || KW_HAVING.equals(methodName)) {
            Expression filterExpr = ((ArgumentListExpression) call.getArguments()).getExpression(0);

            FilterExpression filterExpression;
            if (KW_WHERE.equals(methodName)) {
                filterExpression = new WhereExpression(filterExpr);
            } else if (KW_ON.equals(methodName)) {
                filterExpression = new OnExpression(filterExpr);
            } else {
                filterExpression = new HavingExpression(filterExpr);
            }

            filterExpression.setSourcePosition(call.getMethod());

            if (latestGinqExpressionClause instanceof JoinExpression && filterExpression instanceof OnExpression) {
                ((JoinExpression) latestGinqExpressionClause).setOnExpression((OnExpression) filterExpression);
            } else if (latestGinqExpressionClause instanceof DataSourceHolder && filterExpression instanceof WhereExpression) {
                if (null != currentGinqExpression.getGroupExpression() || null != currentGinqExpression.getOrderExpression() || null != currentGinqExpression.getLimitExpression()) {
                    this.collectSyntaxError(new GinqSyntaxError(
                            "The preceding clause of `" + methodName + "` should be `from`/" + "join clause",
                            call.getLineNumber(), call.getColumnNumber()
                    ));
                }
                currentGinqExpression.setWhereExpression((WhereExpression) filterExpression);
            } else if (latestGinqExpressionClause instanceof GroupExpression && filterExpression instanceof HavingExpression) {
                ((GroupExpression) latestGinqExpressionClause).setHavingExpression((HavingExpression) filterExpression);
            } else {
                this.collectSyntaxError(new GinqSyntaxError(
                        "The preceding clause of `" + methodName + "` should be " + (KW_ON.equals(methodName) ? "" : "`from`/") + "join clause",
                        call.getLineNumber(), call.getColumnNumber()
                ));
            }

            if (latestGinqExpressionClause instanceof DataSourceHolder) {
                if (latestGinqExpressionClause instanceof DataSourceExpression) {
                    filterExpression.setDataSourceExpression(((DataSourceExpression) latestGinqExpressionClause));
                } else {
                    filterExpression.setDataSourceExpression(((DataSourceHolder) latestGinqExpressionClause).getDataSourceExpression());
                }
            }
            setLatestGinqExpressionClause(filterExpression);

            return;
        }

        if (KW_EXISTS.equals(methodName)) {
            if (null != latestGinqExpression) {
                ArgumentListExpression argumentListExpression = (ArgumentListExpression) call.getArguments();
                if (argumentListExpression.getExpressions().isEmpty() && isSelectMethodCallExpression(call.getObjectExpression())) {
                    call.setObjectExpression(latestGinqExpression);
                    // use the nested ginq and clear it
                    latestGinqExpression = null;
                }
            }
        }

        if (KW_GROUPBY.equals(methodName)) {
            GroupExpression groupExpression = new GroupExpression(call.getArguments());
            groupExpression.setSourcePosition(call.getMethod());

            currentGinqExpression.setGroupExpression(groupExpression);

            if (latestGinqExpressionClause instanceof OrderExpression) {
                this.collectSyntaxError(new GinqSyntaxError(
                        "The clause `" + methodName + "` should be in front of `orderby`",
                        call.getLineNumber(), call.getColumnNumber()
                ));
            } else if (latestGinqExpressionClause instanceof LimitExpression) {
                this.collectSyntaxError(new GinqSyntaxError(
                        "The clause `" + methodName + "` should be in front of `limit`",
                        call.getLineNumber(), call.getColumnNumber()
                ));
            }

            if (latestGinqExpressionClause instanceof DataSourceHolder) {
                groupExpression.setDataSourceExpression(((DataSourceHolder) latestGinqExpressionClause).getDataSourceExpression());
            }
            setLatestGinqExpressionClause(groupExpression);

            return;
        }

        if (KW_ORDERBY.equals(methodName) && !visitingOverClause) {
            OrderExpression orderExpression = new OrderExpression(call.getArguments());
            orderExpression.setSourcePosition(call.getMethod());

            currentGinqExpression.setOrderExpression(orderExpression);

            if (latestGinqExpressionClause instanceof LimitExpression) {
                this.collectSyntaxError(new GinqSyntaxError(
                        "The clause `" + methodName + "` should be in front of `limit`",
                        call.getLineNumber(), call.getColumnNumber()
                ));
            }

            if (latestGinqExpressionClause instanceof DataSourceHolder) {
                orderExpression.setDataSourceExpression(((DataSourceHolder) latestGinqExpressionClause).getDataSourceExpression());
            }
            setLatestGinqExpressionClause(orderExpression);

            return;
        }

        if (KW_LIMIT.equals(methodName)) {
            LimitExpression limitExpression = new LimitExpression(call.getArguments());
            limitExpression.setSourcePosition(call.getMethod());

            currentGinqExpression.setLimitExpression(limitExpression);

            if (latestGinqExpressionClause instanceof DataSourceHolder) {
                limitExpression.setDataSourceExpression(((DataSourceHolder) latestGinqExpressionClause).getDataSourceExpression());
            }
            setLatestGinqExpressionClause(limitExpression);

            return;
        }

        if (KW_SELECT.equals(methodName)) {
            TupleExpression tupleExpression = (TupleExpression) call.getArguments();
            if (1 == tupleExpression.getExpressions().size()) {
                Expression firstExpression = tupleExpression.getExpressions().get(0);
                if (firstExpression instanceof MethodCallExpression) {
                    MethodCallExpression mce = (MethodCallExpression) firstExpression;
                    if (KW_DISTINCT.equals(mce.getMethodAsString())) {
                        tupleExpression = (TupleExpression) mce.getArguments();
                        currentGinqExpression.putNodeMetaData(GINQ_SELECT_DISTINCT, true);
                    }
                }
            } else {
                for (Expression expression : tupleExpression.getExpressions()) {
                    if (expression instanceof MethodCallExpression) {
                        MethodCallExpression mce = (MethodCallExpression) expression;
                        if (KW_DISTINCT.equals(mce.getMethodAsString())) {
                            this.collectSyntaxError(new GinqSyntaxError(
                                    "Invalid usage of `distinct`",
                                    mce.getLineNumber(), mce.getColumnNumber()
                            ));
                        }
                    }
                }
            }

            SelectExpression selectExpression = new SelectExpression(tupleExpression);
            selectExpression.setSourcePosition(call.getMethod());

            currentGinqExpression.setSelectExpression(selectExpression);

            if (latestGinqExpressionClause instanceof DataSourceHolder) {
                selectExpression.setDataSourceExpression(((DataSourceHolder) latestGinqExpressionClause).getDataSourceExpression());
            }
            setLatestGinqExpressionClause(selectExpression);

            latestGinqExpression = ginqExpressionStack.pop();
            latestGinqExpression.setSourcePosition(call);

            return;
        }
    }