Ejemplo n.º 1
0
            static MemberDeclarationSyntax MethodDeclarationSyntax(SqModelMeta sqModelMeta, string name, bool?pkFilter)
            {
                var setter             = SyntaxFactory.IdentifierName("s");
                ExpressionSyntax chain = setter;

                foreach (var metaProperty in sqModelMeta.Properties.Where(p => pkFilter.HasValue? p.IsPrimaryKey == pkFilter.Value : !p.IsIdentity))
                {
                    var col = setter.MemberAccess(nameof(IDataMapSetter <object, object> .Target))
                              .MemberAccess(metaProperty.Column.First().ColumnName);
                    ExpressionSyntax prop = setter.MemberAccess(nameof(IDataMapSetter <object, object> .Source))
                                            .MemberAccess(metaProperty.Name);
                    if (metaProperty.CastType != null)
                    {
                        prop = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(metaProperty.Type), prop);
                    }

                    chain = chain.MemberAccess("Set").Invoke(col, prop);
                }


                var methodDeclarationSyntax = SyntaxFactory
                                              .MethodDeclaration(SyntaxFactory.ParseTypeName(nameof(IRecordSetterNext)), name)
                                              .WithModifiers(Modifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword))
                                              .AddParameterListParameters(FuncParameter("s",
                                                                                        $"{nameof(IDataMapSetter<object, object>)}<{sqModelMeta.Properties.First().Column.First().TableRef.TableTypeName},{sqModelMeta.Name}>"))
                                              .WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(chain)));

                return(methodDeclarationSyntax);
            }
Ejemplo n.º 2
0
        public static IEnumerable <MemberDeclarationSyntax> GenerateGetColumns(SqModelMeta meta)
        {
            return(meta.Properties.First()
                   .Column.Select(tableColumn =>
            {
                var arrayItems = meta.Properties.Select(p => p.Column.First())
                                 .Select(p => SyntaxFactory.IdentifierName("table").MemberAccess(p.ColumnName));
                var arrayType = SyntaxFactory.ArrayType(
                    SyntaxFactory.IdentifierName(nameof(TableColumn)),
                    new SyntaxList <ArrayRankSpecifierSyntax>(new[]
                {
                    SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenBracketToken),
                                                     new SeparatedSyntaxList <ExpressionSyntax>(),
                                                     SyntaxFactory.Token(SyntaxKind.CloseBracketToken))
                }));
                var array = SyntaxFactory.ArrayCreationExpression(
                    arrayType,
                    SyntaxFactory.InitializerExpression(SyntaxKind.ArrayInitializerExpression,
                                                        new SeparatedSyntaxList <ExpressionSyntax>().AddRange(arrayItems))
                    );

                return SyntaxFactory
                .MethodDeclaration(arrayType, MethodNameGetColumns)
                .WithModifiers(Modifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword))
                .AddParameterListParameters(FuncParameter("table", tableColumn.TableRef.TableTypeName))
                .WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(
                                                  array
                                                  )));
            }));
        }
Ejemplo n.º 3
0
        public static IEnumerable <MemberDeclarationSyntax> GenerateStaticFactory(SqModelMeta meta)
        {
            return(meta.Properties.First()
                   .Column.Select(tableColumn => SyntaxFactory
                                  .MethodDeclaration(SyntaxFactory.ParseTypeName(meta.Name), MethodNameRead)
                                  .WithModifiers(Modifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword))
                                  .AddParameterListParameters(FuncParameter("record", nameof(ISqDataRecordReader)))
                                  .AddParameterListParameters(FuncParameter("table", tableColumn.TableRef.TableTypeName))
                                  .WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(
                                                                    SyntaxFactory.ObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword),
                                                                                                           SyntaxFactory.ParseTypeName(meta.Name),
                                                                                                           ArgumentList(meta.Properties.Select(p =>
            {
                ExpressionSyntax invocation = MemberAccess("table", p.Column.First().ColumnName)
                                              .MemberAccess("Read")
                                              .Invoke(SyntaxFactory.ParseName("record"));

                if (p.CastType != null)
                {
                    invocation = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(p.CastType), invocation);
                }
                return new NamedArgument(p.Name.FirstToLower(),
                                         invocation);
            })
                                                                                                                        .ToArray()),
                                                                                                           null))))));
        }
Ejemplo n.º 4
0
        public static MemberDeclarationSyntax[] Constructors(SqModelMeta meta)
        {
            var constructor = SyntaxFactory.ConstructorDeclaration(meta.Name)
                              .WithModifiers(Modifiers(SyntaxKind.PublicKeyword))
                              .AddParameterListParameters(meta.Properties.Select(p => FuncParameter(p.Name.FirstToLower(), p.FinalType)).ToArray())
                              .WithBody(SyntaxFactory.Block(GenerateConstructorAssignments(meta)));

            return(new MemberDeclarationSyntax[] { constructor });
        }
Ejemplo n.º 5
0
        public static CompilationUnitSyntax Generate(SqModelMeta meta, string defaultNamespace, string existingFilePath, out bool existing)
        {
            CompilationUnitSyntax  result;
            ClassDeclarationSyntax?existingClass = null;

            existing = false;

            if (File.Exists(existingFilePath))
            {
                existing = true;
                var tClass = CSharpSyntaxTree.ParseText(File.ReadAllText(existingFilePath));

                existingClass = tClass.GetRoot()
                                .DescendantNodes()
                                .OfType <ClassDeclarationSyntax>()
                                .FirstOrDefault(cd => cd.Identifier.ValueText == meta.Name);
            }

            if (existingClass != null)
            {
                result = existingClass.FindParentOrDefault <CompilationUnitSyntax>() ?? throw new SqExpressCodeGenException($"Could not find compilation unit in \"{existingFilePath}\"");

                result = result.ReplaceNode(existingClass, GenerateClass(meta, existingClass));
            }
            else
            {
                var namespaces =
                    new[] {
                    nameof(System),
                    nameof(SqExpress),
                    $"{nameof(SqExpress)}.{nameof(SqExpress.QueryBuilders)}.{nameof(SqExpress.QueryBuilders.RecordSetter)}"
                }
                .Concat(meta.Properties.SelectMany(p => p.Column)
                        .Select(c => c.TableRef.TableTypeNameSpace)
                        .Where(n => n != defaultNamespace))
                .Distinct()
                .ToList();


                result = SyntaxFactory.CompilationUnit()
                         .AddUsings(namespaces.Select(n => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(n))).ToArray())
                         .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(defaultNamespace))
                                     .AddMembers(GenerateClass(meta, null)));
            }

            return(result.NormalizeWhitespace());
        }
Ejemplo n.º 6
0
        public static MemberDeclarationSyntax[] GenerateMapping(SqModelMeta meta)
        {
            var pkCount = meta.Properties.Count(i => i.IsPrimaryKey);

            if (pkCount > 0 && pkCount < meta.Properties.Count)
            {
                return(new []
                {
                    MethodDeclarationSyntax(meta, MethodNameGetMapping, null),
                    MethodDeclarationSyntax(meta, MethodNameGetUpdateKeyMapping, true),
                    MethodDeclarationSyntax(meta, MethodNameGetUpdateMapping, false)
                });
            }
            else
            {
                return(new [] { MethodDeclarationSyntax(meta, MethodNameGetMapping, null) });
            }
Ejemplo n.º 7
0
        public static IEnumerable <MemberDeclarationSyntax> Properties(SqModelMeta meta, IReadOnlyDictionary <string, SyntaxList <AttributeListSyntax> >?oldAttributes)
        {
            return(meta.Properties.Select(p =>
            {
                var res = SyntaxFactory.PropertyDeclaration(
                    SyntaxFactory.ParseTypeName(p.FinalType),
                    p.Name)
                          .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                          .AddAccessorListAccessors(
                    SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                    );
                if (oldAttributes != null && oldAttributes.TryGetValue(p.Name, out var attributeList))
                {
                    res = res.WithAttributeLists(attributeList);
                }

                return res;
            }));
        }
Ejemplo n.º 8
0
        public static MemberDeclarationSyntax[] GenerateMapping(SqModelMeta meta, SqModelTableRef tableRef)
        {
            if (!HasUpdater(tableRef))
            {
                return(Array.Empty <MemberDeclarationSyntax>());
            }

            if (meta.HasPk())
            {
                return(new []
                {
                    MethodDeclarationSyntax(meta, tableRef, MethodNameGetMapping, null),
                    MethodDeclarationSyntax(meta, tableRef, MethodNameGetUpdateKeyMapping, true),
                    MethodDeclarationSyntax(meta, tableRef, MethodNameGetUpdateMapping, false)
                });
            }
            else
            {
                return(new [] { MethodDeclarationSyntax(meta, tableRef, MethodNameGetMapping, null) });
            }
Ejemplo n.º 9
0
        private static ClassDeclarationSyntax GenerateClass(SqModelMeta meta, ClassDeclarationSyntax?existingClass)
        {
            ClassDeclarationSyntax result;

            MemberDeclarationSyntax[]? oldMembers = null;
            Dictionary <string, SyntaxList <AttributeListSyntax> >?oldAttributes = null;

            if (existingClass != null)
            {
                result = existingClass;

                oldMembers = result.DescendantNodes()
                             .OfType <MemberDeclarationSyntax>()
                             .Where(md =>
                {
                    if (md is ConstructorDeclarationSyntax)
                    {
                        return(false);
                    }

                    if (md is IncompleteMemberSyntax)
                    {
                        return(false);
                    }

                    if (md is PropertyDeclarationSyntax p)
                    {
                        if (meta.Properties.Any(mp => mp.Name == p.Identifier.ValueText))
                        {
                            if (p.AttributeLists.Count > 0)
                            {
                                oldAttributes ??= new Dictionary <string, SyntaxList <AttributeListSyntax> >();
                                oldAttributes.Add(p.Identifier.ValueText, p.AttributeLists);
                            }
                            return(false);
                        }
                    }

                    if (md is MethodDeclarationSyntax method)
                    {
                        var name = method.Identifier.ValueText;

                        if (name.StartsWith("With") || AllMethods.Contains(name))
                        {
                            return(false);
                        }
                    }

                    return(true);
                })
                             .ToArray();

                result = result.RemoveNodes(result.DescendantNodes().OfType <MemberDeclarationSyntax>(), SyntaxRemoveOptions.KeepNoTrivia) !;
            }
            else
            {
                result = SyntaxFactory.ClassDeclaration(meta.Name)
                         .WithModifiers(Modifiers(SyntaxKind.PublicKeyword));
            }

            result = result
                     .AddMembers(Constructors(meta)
                                 .Concat(GenerateStaticFactory(meta))
                                 .Concat(Properties(meta, oldAttributes))
                                 .Concat(GenerateGetColumns(meta))
                                 .Concat(GenerateMapping(meta))
                                 .Concat(GenerateWithModifiers(meta))
                                 .ToArray());

            if (oldMembers != null && oldMembers.Length > 0)
            {
                result = result.AddMembers(oldMembers);
            }

            return(result);
        }
Ejemplo n.º 10
0
 private static IEnumerable <Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax> GenerateConstructorAssignments(SqModelMeta meta)
 {
     return(meta.Properties.Select(p =>
                                   SyntaxFactory.ExpressionStatement(AssignmentThis(p.Name,
                                                                                    SyntaxFactory.IdentifierName(p.Name.FirstToLower())))));
 }
Ejemplo n.º 11
0
        public static CompilationUnitSyntax Generate(SqModelMeta meta, string defaultNamespace, string existingFilePath, bool rwClasses, ModelType modelType, IFileSystem fileSystem, out bool existing)
        {
            CompilationUnitSyntax result;
            TypeDeclarationSyntax?existingClass = null;

            existing = false;

            if (fileSystem.FileExists(existingFilePath))
            {
                existing = true;
                var tClass = CSharpSyntaxTree.ParseText(fileSystem.ReadAllText(existingFilePath));

                existingClass = tClass.GetRoot()
                                .DescendantNodes()
                                .OfType <TypeDeclarationSyntax>()
                                .FirstOrDefault(cd => cd.Identifier.ValueText == meta.Name);
            }

            var namespaces =
                new[] {
                nameof(System),
                nameof(SqExpress),
                $"{nameof(SqExpress)}.{nameof(SqExpress.QueryBuilders)}.{nameof(SqExpress.QueryBuilders.RecordSetter)}"
            }
            .Concat(meta.Properties.SelectMany(p => p.Column)
                    .Select(c => c.TableRef.TableTypeNameSpace)
                    .Where(n => n != defaultNamespace))
            .Distinct()
            .ToList();

            if (rwClasses || ExtractTableRefs(meta).Any(tr => tr.BaseTypeKindTag == BaseTypeKindTag.DerivedTableBase))
            {
                namespaces.Add($"{nameof(SqExpress)}.{nameof(SqExpress.Syntax)}.{nameof(SqExpress.Syntax.Names)}");
                namespaces.Add($"{nameof(System)}.{nameof(System.Collections)}.{nameof(System.Collections.Generic)}");
            }


            if (existingClass != null)
            {
                result = existingClass.FindParentOrDefault <CompilationUnitSyntax>() ?? throw new SqExpressCodeGenException($"Could not find compilation unit in \"{existingFilePath}\"");

                foreach (var usingDirectiveSyntax in result.Usings)
                {
                    var existingUsing = usingDirectiveSyntax.Name.ToFullString();
                    var index         = namespaces.IndexOf(existingUsing);
                    if (index >= 0)
                    {
                        namespaces.RemoveAt(index);
                    }
                }

                if (namespaces.Count > 0)
                {
                    result = result.AddUsings(namespaces
                                              .Select(n => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(n)))
                                              .ToArray());
                }

                var oldClass = existingClass;

                if (oldClass is ClassDeclarationSyntax classDeclaration && modelType == ModelType.Record)
                {
                    oldClass = SyntaxFactory.RecordDeclaration(classDeclaration.AttributeLists,
                                                               classDeclaration.Modifiers,
                                                               SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                                                               classDeclaration.Identifier,
                                                               classDeclaration.TypeParameterList,
                                                               null,
                                                               classDeclaration.BaseList,
                                                               classDeclaration.ConstraintClauses,
                                                               SyntaxFactory.Token(SyntaxKind.OpenBraceToken),
                                                               classDeclaration.Members,
                                                               SyntaxFactory.Token(SyntaxKind.CloseBraceToken),
                                                               SyntaxFactory.Token(SyntaxKind.None));
                }

                result = result.ReplaceNode(existingClass, GenerateClass(meta, rwClasses, modelType, oldClass));
            }
            else
            {
                result = SyntaxFactory.CompilationUnit()
                         .AddUsings(namespaces.Select(n => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(n))).ToArray())
                         .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(defaultNamespace))
                                     .AddMembers(GenerateClass(meta, rwClasses, modelType, null)));
            }

            return(result.NormalizeWhitespace());
        }
Ejemplo n.º 12
0
 public static IEnumerable <MemberDeclarationSyntax> GenerateMapping(SqModelMeta meta)
 {
     return(ExtractTableRefs(meta).SelectMany(tr => GenerateMapping(meta, tr)));
 }
Ejemplo n.º 13
0
        public static IEnumerable <MemberDeclarationSyntax> GenerateOrdinalStaticFactory(SqModelMeta meta)
        {
            return(ExtractTableRefs(meta).Select(tableRef => SyntaxFactory
                                                 .MethodDeclaration(SyntaxFactory.ParseTypeName(meta.Name), MethodNameReadOrdinal)
                                                 .WithModifiers(Modifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword))
                                                 .AddParameterListParameters(FuncParameter("record", nameof(ISqDataRecordReader)))
                                                 .AddParameterListParameters(FuncParameter("table", ExtractTableTypeName(meta, tableRef)))
                                                 .AddParameterListParameters(FuncParameter("offset", "int"))
                                                 .WithBody(SyntaxFactory.Block(SyntaxFactory.ReturnStatement(
                                                                                   SyntaxFactory.ObjectCreationExpression(SyntaxFactory.Token(SyntaxKind.NewKeyword),
                                                                                                                          SyntaxFactory.ParseTypeName(meta.Name),
                                                                                                                          ArgumentList(meta.Properties.Select((p, index) =>
            {
                ExpressionSyntax invocation = MemberAccess("table", p.Column.First().ColumnName)
                                              .MemberAccess("Read")
                                              .Invoke(
                    SyntaxFactory.ParseName("record"),
                    index == 0
                                                ? SyntaxFactory.IdentifierName("offset")
                                                : SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, SyntaxFactory.IdentifierName("offset"), SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(index))));

                if (p.CastType != null)
                {
                    invocation = SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(p.CastType), invocation);
                }
                return new NamedArgument(p.Name.FirstToLower(),
                                         invocation);
            })
                                                                                                                                       .ToArray()),
                                                                                                                          null))))));
        }
Ejemplo n.º 14
0
        private static TypeDeclarationSyntax GenerateClass(SqModelMeta meta, bool rwClasses, ModelType modelType, TypeDeclarationSyntax?existingClass)
        {
            TypeDeclarationSyntax result;

            MemberDeclarationSyntax[]? oldMembers = null;
            Dictionary <string, SyntaxList <AttributeListSyntax> >?oldAttributes = null;

            if (existingClass != null)
            {
                result = existingClass;

                oldMembers = result.Members
                             .Where(md =>
                {
                    if (md is ConstructorDeclarationSyntax)
                    {
                        return(false);
                    }

                    if (md is IncompleteMemberSyntax)
                    {
                        return(false);
                    }

                    if (md is PropertyDeclarationSyntax p)
                    {
                        if (meta.Properties.Any(mp => mp.Name == p.Identifier.ValueText))
                        {
                            if (p.AttributeLists.Count > 0)
                            {
                                oldAttributes ??= new Dictionary <string, SyntaxList <AttributeListSyntax> >();
                                oldAttributes.Add(p.Identifier.ValueText, p.AttributeLists);
                            }
                            return(false);
                        }
                    }

                    if (md is MethodDeclarationSyntax method)
                    {
                        var name = method.Identifier.ValueText;

                        if (name.StartsWith("With") || AllMethods.Contains(name) || name.StartsWith(MethodNameGetReader + "For") || name.StartsWith(MethodNameGetUpdater + "For"))
                        {
                            return(false);
                        }
                    }

                    if (md is ClassDeclarationSyntax classDeclaration)
                    {
                        var name = classDeclaration.Identifier.ValueText;

                        if (name == meta.Name + ReaderClassSuffix || name.StartsWith(meta.Name + ReaderClassSuffix + "For"))
                        {
                            return(false);
                        }
                        if (name == meta.Name + UpdaterClassSuffix || name.StartsWith(meta.Name + UpdaterClassSuffix + "For"))
                        {
                            return(false);
                        }
                    }

                    return(true);
                })
                             .ToArray();

                result = result.RemoveNodes(result.DescendantNodes().OfType <MemberDeclarationSyntax>(), SyntaxRemoveOptions.KeepNoTrivia) !;
            }
            else
            {
                result = (modelType == ModelType.Record
                        ? (TypeDeclarationSyntax)SyntaxFactory
                          .RecordDeclaration(SyntaxFactory.Token(SyntaxKind.RecordKeyword), meta.Name)
                          .WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken))
                          .WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken))
                        : SyntaxFactory.ClassDeclaration(meta.Name))
                         .WithModifiers(existingClass?.Modifiers ?? Modifiers(SyntaxKind.PublicKeyword));
            }

            result = result
                     .AddMembers(Constructors(meta)
                                 .Concat(GenerateStaticFactory(meta))
                                 .Concat(rwClasses ? GenerateOrdinalStaticFactory(meta) : Array.Empty <MemberDeclarationSyntax>())
                                 .Concat(Properties(meta, oldAttributes))
                                 .Concat(modelType == ModelType.ImmutableClass ? GenerateWithModifiers(meta) : Array.Empty <MemberDeclarationSyntax>())
                                 .Concat(GenerateGetColumns(meta))
                                 .Concat(GenerateMapping(meta))
                                 .Concat(rwClasses ? GenerateReaderClass(meta): Array.Empty <MemberDeclarationSyntax>())
                                 .Concat(rwClasses ? GenerateWriterClass(meta) : Array.Empty <MemberDeclarationSyntax>())
                                 .ToArray());

            if (oldMembers != null && oldMembers.Length > 0)
            {
                result = result.AddMembers(oldMembers);
            }

            return(result);
        }