private static List <string> GetIndexedFields(IndexDefinition definition, FieldNamesValidator fieldNamesValidator) { var fields = fieldNamesValidator.Fields.ToList(); foreach (var spatialField in definition.Fields) { if (spatialField.Value.Spatial == null) { continue; } if (spatialField.Value.Spatial.Strategy != Client.Documents.Indexes.Spatial.SpatialSearchStrategy.BoundingBox) { continue; } fields.Remove(spatialField.Key); fields.AddRange(new[] { spatialField.Key + "__minX", spatialField.Key + "__minY", spatialField.Key + "__maxX", spatialField.Key + "__maxY", }); } return(fields); }
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 }; } }
public RavenLinqOptimizer(FieldNamesValidator validator) { if (validator.Fields == null || validator.Fields.Length == 0) { throw new InvalidOperationException("Validator should have been validating original indexing func"); } _validator = validator; }
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 List <StatementSyntax> HandleSyntaxInMap(FieldNamesValidator fieldValidator, MapFunctionProcessor mapRewriter, ExpressionSyntax expression, ref SyntaxList <MemberDeclarationSyntax> members) { var rewrittenExpression = (CSharpSyntaxNode)mapRewriter.Visit(expression); var optimized = new RavenLinqOptimizer(fieldValidator).Visit(new RavenLinqPrettifier().Visit(rewrittenExpression)) as StatementSyntax; var collectionName = string.IsNullOrWhiteSpace(mapRewriter.CollectionName) ? Constants.Documents.Collections.AllDocumentsCollection : mapRewriter.CollectionName; var collection = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(collectionName)); var results = new List <StatementSyntax>(); if (optimized != null) { var method = SyntaxFactory.MethodDeclaration(SyntaxFactory.IdentifierName("IEnumerable"), SyntaxFactory.Identifier("Map_" + members.Count)) .WithParameterList( SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs")) .WithType( SyntaxFactory.GenericName("IEnumerable") .WithTypeArgumentList( SyntaxFactory.TypeArgumentList( SyntaxFactory.SingletonSeparatedList <TypeSyntax>(SyntaxFactory.IdentifierName("dynamic")) ) ) ) )) ) .WithBody(SyntaxFactory.Block().AddStatements(optimized)); members = members.Add(method); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, RoslynHelper.This(method.Identifier.Text)).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... ) } else { var indexingFunction = SyntaxFactory.SimpleLambdaExpression(SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs")), rewrittenExpression); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, indexingFunction).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... ) } if (mapRewriter.ReferencedCollections != null) { foreach (var referencedCollection in mapRewriter.ReferencedCollections) { var rc = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(referencedCollection)); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddReferencedCollection)).Invoke(collection, rc).AsExpressionStatement()); } } return(results); }
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 MemberDeclarationSyntax CreateClass(string name, IndexDefinition definition) { var statements = new List <StatementSyntax>(); var maps = definition.Maps.ToList(); var fieldNamesValidator = new FieldNamesValidator(); var methodDetector = new MethodDetectorRewriter(); var members = new SyntaxList <MemberDeclarationSyntax>(); for (var i = 0; i < maps.Count; i++) { var map = maps[i]; statements.AddRange(HandleMap(map, fieldNamesValidator, methodDetector, ref members)); } if (string.IsNullOrWhiteSpace(definition.Reduce) == false) { statements.Add(HandleReduce(definition.Reduce, fieldNamesValidator, methodDetector, out string[] groupByFields)); var groupByFieldsArray = GetArrayCreationExpression(groupByFields); statements.Add(RoslynHelper.This(nameof(StaticIndexBase.GroupByFields)).Assign(groupByFieldsArray).AsExpressionStatement()); } var fields = GetIndexedFields(definition, fieldNamesValidator); var outputFieldsArray = GetArrayCreationExpression(fields); statements.Add(RoslynHelper.This(nameof(StaticIndexBase.OutputFields)).Assign(outputFieldsArray).AsExpressionStatement()); var methods = methodDetector.Methods; if (methods.HasCreateField) { statements.Add(RoslynHelper.This(nameof(StaticIndexBase.HasDynamicFields)).Assign(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)).AsExpressionStatement()); } if (methods.HasBoost) { statements.Add(RoslynHelper.This(nameof(StaticIndexBase.HasBoostedFields)).Assign(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)).AsExpressionStatement()); } var ctor = RoslynHelper.PublicCtor(name) .AddBodyStatements(statements.ToArray()); return(RoslynHelper.PublicClass(name) .WithBaseClass <StaticIndexBase>() .WithMembers(members.Add(ctor))); }
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 }; } }