private static List <StatementSyntax> HandleMap(string map, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector, ref SyntaxList <MemberDeclarationSyntax> members) { try { map = NormalizeFunction(map); var expression = SyntaxFactory.ParseExpression(map).NormalizeWhitespace(); fieldNamesValidator.Validate(map, expression); methodsDetector.Visit(expression); var queryExpression = expression as QueryExpressionSyntax; if (queryExpression != null) { return(HandleSyntaxInMap(fieldNamesValidator, new MapFunctionProcessor(CollectionNameRetriever.QuerySyntax, SelectManyRewriter.QuerySyntax), queryExpression, ref members)); } var invocationExpression = expression as InvocationExpressionSyntax; if (invocationExpression != null) { return(HandleSyntaxInMap(fieldNamesValidator, new MapFunctionProcessor(CollectionNameRetriever.MethodSyntax, SelectManyRewriter.MethodSyntax), invocationExpression, ref members)); } throw new InvalidOperationException("Not supported expression type."); } catch (Exception ex) { throw new IndexCompilationException(ex.Message, ex) { IndexDefinitionProperty = nameof(IndexDefinition.Maps), ProblematicText = map }; } }
private static StatementSyntax HandleReduce(string reduce, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector, out string[] groupByFields) { try { reduce = NormalizeFunction(reduce); var expression = SyntaxFactory.ParseExpression(reduce).NormalizeWhitespace(); fieldNamesValidator?.Validate(reduce, expression); methodsDetector.Visit(expression); StatementSyntax result; switch (expression) { case QueryExpressionSyntax queryExpression: result = HandleSyntaxInReduce( new ReduceFunctionProcessor( ResultsVariableNameRewriter.QuerySyntax, GroupByFieldsRetriever.QuerySyntax, SelectManyRewriter.QuerySyntax), MethodsInGroupByValidator.QuerySyntaxValidator, queryExpression, out groupByFields); break; case InvocationExpressionSyntax invocationExpression: result = HandleSyntaxInReduce( new ReduceFunctionProcessor( ResultsVariableNameRewriter.MethodSyntax, GroupByFieldsRetriever.MethodSyntax, SelectManyRewriter.MethodSyntax), MethodsInGroupByValidator.MethodSyntaxValidator, invocationExpression, out groupByFields); break; default: throw new InvalidOperationException("Not supported expression type."); } foreach (var groupByField in groupByFields) { if (fieldNamesValidator?.Fields.Contains(groupByField) == false) { throw new InvalidOperationException($"Group by field '{groupByField}' was not found on the list of index fields ({string.Join(", ",fieldNamesValidator.Fields)})"); } } return(result); } catch (Exception ex) { throw new IndexCompilationException(ex.Message, ex) { IndexDefinitionProperty = nameof(IndexDefinition.Reduce), ProblematicText = reduce }; } }
private static SyntaxNode OptimizeExpression(string str) { var expression = SyntaxFactory.ParseExpression(str.Trim()); var result = new RavenLinqPrettifier().Visit(expression); var validator = new FieldNamesValidator(); validator.Validate(str, SyntaxFactory.ParseExpression(str).NormalizeWhitespace()); var expr = new RavenLinqOptimizer(validator).Visit(result); expr = expr.ReplaceTrivia(expr.DescendantTrivia(), (t1, t2) => new SyntaxTrivia()); return(expr.NormalizeWhitespace()); }
private static StatementSyntax HandleReduce(string reduce, FieldNamesValidator fieldNamesValidator, MethodDetectorRewriter methodsDetector, out string[] groupByFields) { try { reduce = NormalizeFunction(reduce); var expression = SyntaxFactory.ParseExpression(reduce).NormalizeWhitespace(); fieldNamesValidator?.Validate(reduce, expression); methodsDetector.Visit(expression); var queryExpression = expression as QueryExpressionSyntax; if (queryExpression != null) { return HandleSyntaxInReduce( new ReduceFunctionProcessor( ResultsVariableNameRewriter.QuerySyntax, GroupByFieldsRetriever.QuerySyntax, SelectManyRewriter.QuerySyntax), MethodsInGroupByValidator.QuerySyntaxValidator, queryExpression, out groupByFields); } var invocationExpression = expression as InvocationExpressionSyntax; if (invocationExpression != null) { return HandleSyntaxInReduce( new ReduceFunctionProcessor( ResultsVariableNameRewriter.MethodSyntax, GroupByFieldsRetriever.MethodSyntax, SelectManyRewriter.MethodSyntax), MethodsInGroupByValidator.MethodSyntaxValidator, invocationExpression, out groupByFields); } throw new InvalidOperationException("Not supported expression type."); } catch (Exception ex) { throw new IndexCompilationException(ex.Message, ex) { IndexDefinitionProperty = nameof(IndexDefinition.Reduce), ProblematicText = reduce }; } }
public override SyntaxNode VisitQueryExpression(QueryExpressionSyntax node) { var stripExpressionParentParenthesis = StripExpressionParentParenthesis(node); if (stripExpressionParentParenthesis != null && stripExpressionParentParenthesis is QueryExpressionSyntax == false) { return(node); } ForEachStatementSyntax parent = null; var queryExpressionSyntax = StripExpressionParenthesis(node.FromClause.Expression) as QueryExpressionSyntax; if (queryExpressionSyntax != null && StripExpressionParentParenthesis(queryExpressionSyntax) is QueryExpressionSyntax) { using (RecursiveCall()) { parent = VisitQueryExpression(queryExpressionSyntax) as ForEachStatementSyntax; } if (parent != null) { node = node.WithFromClause( node.FromClause.WithExpression(IdentifierName(queryExpressionSyntax.FromClause.Identifier))); } } var dummyYield = YieldStatement(SyntaxKind.YieldReturnStatement, LiteralExpression(SyntaxKind.NullLiteralExpression)); var body = Block().AddStatements(dummyYield); foreach (var clause in node.Body.Clauses) { if (TryRewriteBodyClause(clause, dummyYield, ref body)) { continue; } return(base.VisitQueryExpression(node)); } var selectClauseSyntax = node.Body.SelectOrGroup as SelectClauseSyntax; if (selectClauseSyntax == null) { return(base.VisitQueryExpression(node)); } var continuation = node.Body.Continuation; while (continuation != null) { // select new { } into var selectIntoVar = LocalDeclarationStatement( VariableDeclaration(IdentifierName("var"), SingletonSeparatedList(VariableDeclarator( continuation.Identifier) .WithInitializer( EqualsValueClause(selectClauseSyntax.Expression) ) ) ) ); selectClauseSyntax = continuation.Body.SelectOrGroup as SelectClauseSyntax; if (selectClauseSyntax == null) { return(base.VisitQueryExpression(node)); } body = body.InsertNodesBefore(FindDummyYieldIn(body), new[] { selectIntoVar }); foreach (var clause in continuation.Body.Clauses) { if (TryRewriteBodyClause(clause, dummyYield, ref body)) { continue; } return(base.VisitQueryExpression(node)); } continuation = continuation.Body.Continuation; } var stmt = ForEachStatement( IdentifierName("var"), node.FromClause.Identifier, node.FromClause.Expression, body ); stmt = stmt.ReplaceNode(FindDummyYieldIn(stmt), YieldStatement(SyntaxKind.YieldReturnStatement, selectClauseSyntax.Expression) ); if (parent == null) { if (_recursiveCallCounter == 0 && _validator.Validate(stmt.ToFullString(), selectClauseSyntax.Expression, throwOnError: false) == false) { ThrowIndexRewritingException(node, stmt); } return(stmt); } var parentBody = (BlockSyntax)parent.Statement; var yieldStatementSyntax = (YieldStatementSyntax)parentBody.Statements.Last(); var parentVar = LocalDeclarationStatement( VariableDeclaration(IdentifierName("var"), SingletonSeparatedList(VariableDeclarator( node.FromClause.Identifier) .WithInitializer( EqualsValueClause(yieldStatementSyntax.Expression) ) ) ) ); var statementSyntax = stmt.Statement; if (statementSyntax is BlockSyntax bs) { statementSyntax = bs.Statements.Single(); } return(parent.WithStatement( parentBody.ReplaceNode(yieldStatementSyntax, parentVar).AddStatements(statementSyntax) )); }