Exemple #1
0
            private MemberDeclarationSyntax CreateToDerivedTypeMethod(MetaType derivedType)
            {
                var derivedTypeName = GetFullyQualifiedSymbolName(derivedType.TypeSymbol);
                var thatLocal       = SyntaxFactory.IdentifierName("that");
                var body            = new List <StatementSyntax>();

                // var that = this as DerivedType;
                body.Add(SyntaxFactory.LocalDeclarationStatement(
                             SyntaxFactory.VariableDeclaration(
                                 varType,
                                 SyntaxFactory.SingletonSeparatedList(
                                     SyntaxFactory.VariableDeclarator(thatLocal.Identifier)
                                     .WithInitializer(SyntaxFactory.EqualsValueClause(
                                                          SyntaxFactory.BinaryExpression(
                                                              SyntaxKind.AsExpression,
                                                              SyntaxFactory.ThisExpression(),
                                                              derivedTypeName)))))));

                // this.GetType()
                var thisDotGetType = SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("GetType")),
                    SyntaxFactory.ArgumentList());

                // {0}.Equals(typeof(derivedType))
                var thisTypeIsEquivalentToDerivedType =
                    SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            thisDotGetType,
                            SyntaxFactory.IdentifierName(nameof(Type.Equals))),
                        SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(
                                                                                            SyntaxFactory.TypeOfExpression(derivedTypeName)))));

                var ifEquivalentTypeBlock = new List <StatementSyntax>();
                var fieldsBeyond          = derivedType.GetFieldsBeyond(this.generator.applyToMetaType);

                if (fieldsBeyond.Any())
                {
                    Func <MetaField, ExpressionSyntax> isUnchanged = v =>
                                                                     SyntaxFactory.ParenthesizedExpression(
                        v.IsRequired
                                ? // ({0} == that.{1})
                        SyntaxFactory.BinaryExpression(
                            SyntaxKind.EqualsExpression,
                            v.NameAsField,
                            SyntaxFactory.MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                thatLocal,
                                v.NameAsProperty))
                                : // (!{0}.IsDefined || {0}.Value == that.{1})
                        SyntaxFactory.BinaryExpression(
                            SyntaxKind.LogicalOrExpression,
                            SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(v.NameAsField)),
                            SyntaxFactory.BinaryExpression(
                                SyntaxKind.EqualsExpression,
                                Syntax.OptionalValue(v.NameAsField),
                                SyntaxFactory.MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    thatLocal,
                                    v.NameAsProperty))));
                    var noChangesExpression = fieldsBeyond.Select(isUnchanged).ChainBinaryExpressions(SyntaxKind.LogicalAndExpression);

                    ifEquivalentTypeBlock.Add(SyntaxFactory.IfStatement(
                                                  noChangesExpression,
                                                  SyntaxFactory.ReturnStatement(thatLocal)));
                }
                else
                {
                    ifEquivalentTypeBlock.Add(SyntaxFactory.ReturnStatement(thatLocal));
                }

                // if (that != null && this.GetType().IsEquivalentTo(typeof(derivedType))) { ... }
                body.Add(SyntaxFactory.IfStatement(
                             SyntaxFactory.BinaryExpression(
                                 SyntaxKind.LogicalAndExpression,
                                 SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, thatLocal, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)),
                                 thisTypeIsEquivalentToDerivedType),
                             SyntaxFactory.Block(ifEquivalentTypeBlock)));

                // return DerivedType.CreateWithIdentity(...)
                body.Add(SyntaxFactory.ReturnStatement(
                             SyntaxFactory.InvocationExpression(
                                 SyntaxFactory.MemberAccessExpression(
                                     SyntaxKind.SimpleMemberAccessExpression,
                                     derivedTypeName,
                                     CreateWithIdentityMethodName),
                                 this.generator.CreateArgumentList(this.generator.applyToMetaType.AllFields, asOptional: OptionalStyle.WhenNotRequired)
                                 .AddArguments(RequiredIdentityArgumentFromProperty)
                                 .AddArguments(this.generator.CreateArgumentList(fieldsBeyond, ArgSource.Argument).Arguments.ToArray()))));

                return(SyntaxFactory.MethodDeclaration(
                           derivedTypeName,
                           GetToTypeMethodName(derivedType.TypeSymbol.Name).Identifier)
                       .AddModifiers(
                           SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                           SyntaxFactory.Token(SyntaxKind.VirtualKeyword))
                       .WithParameterList(this.generator.CreateParameterList(fieldsBeyond, ParameterStyle.OptionalOrRequired))
                       .WithBody(SyntaxFactory.Block(body)));
            }
Exemple #2
0
            private MemberDeclarationSyntax CreateCreateWithIdentityMethod()
            {
                ExpressionSyntax returnExpression = DefaultInstanceFieldName;

                if (this.generator.applyToMetaType.LocalFields.Any())
                {
                    returnExpression = SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            returnExpression,
                            WithFactoryMethodName),
                        this.generator.CreateArgumentList(this.generator.applyToMetaType.AllFields, ArgSource.OptionalArgumentOrTemplate, OptionalStyle.Always)
                        .AddArguments(OptionalIdentityArgument));
                }

                var method = SyntaxFactory.MethodDeclaration(
                    this.generator.applyToTypeName,
                    CreateWithIdentityMethodName.Identifier)
                             .AddModifiers(
                    SyntaxFactory.Token(SyntaxKind.InternalKeyword),
                    SyntaxFactory.Token(SyntaxKind.StaticKeyword))
                             .WithParameterList(
                    this.generator.CreateParameterList(
                        this.generator.applyToMetaType.AllFields,
                        ParameterStyle.OptionalOrRequired)
                    .AddParameters(OptionalIdentityParameter))
                             .WithBody(SyntaxFactory.Block(
                                           SyntaxFactory.IfStatement(
                                               SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(IdentityParameterName)),
                                               SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                                                     SyntaxKind.SimpleAssignmentExpression,
                                                                                     IdentityParameterName,
                                                                                     SyntaxFactory.InvocationExpression(NewIdentityMethodName, SyntaxFactory.ArgumentList())))),
                                           SyntaxFactory.ReturnStatement(returnExpression)));

                // BUG: the condition should be if there are local fields on *any* ancestor
                // from the closest non-abstract ancestor (exclusive) to this type (inclusive).
                if (!this.generator.applyToMetaType.LocalFields.Any() && this.generator.applyToMetaType.Ancestors.Any(a => !a.TypeSymbol.IsAbstract))
                {
                    method = Syntax.AddNewKeyword(method);
                }

                return(method);
            }
            private void ImplementSortedChildrenInterface()
            {
                this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveParentWithSortedChildren))));

                // int IRecursiveParentWithSortedChildren.Compare(IRecursiveType first, IRecursiveType second)
                var firstParameterName  = SyntaxFactory.IdentifierName("first");
                var secondParameterName = SyntaxFactory.IdentifierName("second");

                this.innerMembers.Add(SyntaxFactory.MethodDeclaration(
                                          SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)),
                                          nameof(IRecursiveParentWithSortedChildren.Compare))
                                      .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithSortedChildren))))
                                      .AddParameterListParameters(
                                          SyntaxFactory.Parameter(firstParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType))),
                                          SyntaxFactory.Parameter(secondParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType))))
                                      .WithBody(SyntaxFactory.Block(
                                                    // return this.Children.KeyComparer.Compare((<#= templateType.RecursiveType.TypeName #>)first, (<#= templateType.RecursiveType.TypeName #>)second);
                                                    SyntaxFactory.ReturnStatement(
                                                        SyntaxFactory.InvocationExpression(
                                                            SyntaxFactory.MemberAccessExpression(
                                                                SyntaxKind.SimpleMemberAccessExpression,
                                                                SyntaxFactory.MemberAccessExpression(
                                                                    SyntaxKind.SimpleMemberAccessExpression,
                                                                    Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())),
                                                                    SyntaxFactory.IdentifierName(nameof(ImmutableSortedSet <int> .KeyComparer))),
                                                                SyntaxFactory.IdentifierName(nameof(IComparer <int> .Compare))),
                                                            SyntaxFactory.ArgumentList(Syntax.JoinSyntaxNodes(SyntaxKind.CommaToken,
                                                                                                              SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, firstParameterName)),
                                                                                                              SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, secondParameterName)))))))));
            }
            private void ImplementOrderedChildrenInterface()
            {
                // We only need to declare this interface if the children are not sorted,
                // since sorted children merit a derived interface making this redundant.
                if (!this.generator.applyToMetaType.ChildrenAreSorted)
                {
                    this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveParentWithOrderedChildren))));
                }

                // int IRecursiveParentWithOrderedChildren.IndexOf(IRecursiveType value)
                var valueParameterName = SyntaxFactory.IdentifierName("value");

                this.innerMembers.Add(SyntaxFactory.MethodDeclaration(
                                          SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)),
                                          nameof(IRecursiveParentWithOrderedChildren.IndexOf))
                                      .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithOrderedChildren))))
                                      .AddParameterListParameters(SyntaxFactory.Parameter(valueParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType))))
                                      .WithBody(SyntaxFactory.Block(
                                                    // return this.Children.IndexOf((<#= templateType.RecursiveType.TypeName #>)value);
                                                    SyntaxFactory.ReturnStatement(
                                                        SyntaxFactory.InvocationExpression(
                                                            SyntaxFactory.MemberAccessExpression(
                                                                SyntaxKind.SimpleMemberAccessExpression,
                                                                Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())),
                                                                SyntaxFactory.IdentifierName(nameof(IList <int> .IndexOf))),
                                                            SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                                                           SyntaxFactory.Argument(
                                                                                               SyntaxFactory.CastExpression(
                                                                                                   this.generator.applyToMetaType.RecursiveType.TypeSyntax,
                                                                                                   valueParameterName)))))))));
            }
            private void ImplementRecursiveParentInterface()
            {
                var irecursiveParentOfT = CreateIRecursiveParentOfTSyntax(GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveType.TypeSymbol));

                this.baseTypes.Add(SyntaxFactory.SimpleBaseType(irecursiveParentOfT));

                // return this.Children;
                var returnThisDotChildren = SyntaxFactory.ReturnStatement(Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())));

                // System.Collections.Generic.IEnumerable<IRecursiveType> IRecursiveParent.Children
                this.innerMembers.Add(
                    SyntaxFactory.PropertyDeclaration(
                        Syntax.GetTypeSyntax(typeof(IEnumerable <IRecursiveType>)),
                        nameof(IRecursiveParent.Children))
                    .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent))))
                    .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration(
                                                  SyntaxKind.GetAccessorDeclaration,
                                                  SyntaxFactory.Block(returnThisDotChildren))));

                // public ParentedRecursiveType<TRecursiveParent, TRecursiveType> GetParentedNode(uint identity)
                this.innerMembers.Add(
                    SyntaxFactory.MethodDeclaration(
                        SyntaxFactory.GenericName(nameof(ParentedRecursiveType <IRecursiveParent <IRecursiveType>, IRecursiveType>)).AddTypeArgumentListArguments(
                            this.applyTo.RecursiveParent.TypeSyntax,
                            this.applyTo.RecursiveType.TypeSyntax),
                        nameof(IRecursiveParent.GetParentedNode))
                    .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                    //.WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent))))
                    .AddParameterListParameters(RequiredIdentityParameter)
                    .WithBody(SyntaxFactory.Block(
                                  // return this.GetParentedNode<TRecursiveParent, TRecursiveType>(identity);
                                  SyntaxFactory.ReturnStatement(
                                      SyntaxFactory.InvocationExpression(
                                          Syntax.ThisDot(SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetParentedNode)).AddTypeArgumentListArguments(
                                                             this.applyTo.RecursiveParent.TypeSyntax,
                                                             this.applyTo.RecursiveType.TypeSyntax)))
                                      .AddArgumentListArguments(SyntaxFactory.Argument(IdentityParameterName))))));

                // ParentedRecursiveType<IRecursiveParent<IRecursiveType>, IRecursiveType> IRecursiveParent.GetParentedNode(<#= templateType.RequiredIdentityField.TypeName #> identity) {
                var parentedVar = SyntaxFactory.IdentifierName("parented");
                var returnType  = Syntax.GetTypeSyntax(typeof(ParentedRecursiveTypeNonGeneric));

                this.innerMembers.Add(
                    SyntaxFactory.MethodDeclaration(
                        returnType,
                        nameof(IRecursiveParent.GetParentedNode))
                    .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent))))
                    .AddParameterListParameters(RequiredIdentityParameter)
                    .WithBody(SyntaxFactory.Block(
                                  // var parented = this.GetParentedNode(identity);
                                  SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables(
                                                                              SyntaxFactory.VariableDeclarator(parentedVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                           SyntaxFactory.InvocationExpression(Syntax.ThisDot(SyntaxFactory.IdentifierName(nameof(RecursiveTypeExtensions.GetParentedNode))))
                                                                                                                                                           .AddArgumentListArguments(SyntaxFactory.Argument(IdentityParameterName)))))),
                                  // return new ParentedRecursiveType<IRecursiveParent<IRecursiveType>, IRecursiveType>(parented.Value, parented.Parent);
                                  SyntaxFactory.ReturnStatement(SyntaxFactory.ObjectCreationExpression(returnType).AddArgumentListArguments(
                                                                    SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentedVar, SyntaxFactory.IdentifierName(nameof(ParentedRecursiveTypeNonGeneric.Value)))),
                                                                    SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentedVar, SyntaxFactory.IdentifierName(nameof(ParentedRecursiveTypeNonGeneric.Parent)))))))));

                ////System.Collections.Generic.IEnumerable<<#= templateType.RecursiveType.TypeName #>> IRecursiveParent<<#= templateType.RecursiveType.TypeName #>>.Children {
                ////	get { return this.Children; }
                ////}
                this.innerMembers.Add(
                    SyntaxFactory.PropertyDeclaration(
                        Syntax.IEnumerableOf(this.generator.applyToMetaType.RecursiveType.TypeSyntax),
                        nameof(IRecursiveParent <IRecursiveType> .Children))
                    .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(irecursiveParentOfT))
                    .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration(
                                                  SyntaxKind.GetAccessorDeclaration,
                                                  SyntaxFactory.Block(returnThisDotChildren))));
            }
            protected override void GenerateCore()
            {
                this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveType))));

                ////<#= templateType.RequiredIdentityField.TypeName #> IRecursiveType.Identity {
                ////	get { return this.Identity; }
                ////}
                this.innerMembers.Add(SyntaxFactory.PropertyDeclaration(
                                          IdentityFieldTypeSyntax,
                                          nameof(IRecursiveType.Identity))
                                      .WithExplicitInterfaceSpecifier(
                                          SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveType))))
                                      .AddAccessorListAccessors(
                                          SyntaxFactory.AccessorDeclaration(
                                              SyntaxKind.GetAccessorDeclaration,
                                              SyntaxFactory.Block(SyntaxFactory.ReturnStatement(Syntax.ThisDot(IdentityPropertyName))))));
            }
Exemple #7
0
            protected override void GenerateCore()
            {
                var valueParameterName = SyntaxFactory.IdentifierName("value");

                foreach (var field in this.generator.applyToMetaType.LocalFields)
                {
                    var withPropertyMethod = SyntaxFactory.MethodDeclaration(
                        GetFullyQualifiedSymbolName(this.generator.applyToSymbol),
                        WithPropertyMethodPrefix + field.Name.ToPascalCase())
                                             .WithAdditionalAnnotations()
                                             .AddModifiers(
                        SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                                             .AddParameterListParameters(
                        SyntaxFactory.Parameter(valueParameterName.Identifier)
                        .WithType(GetFullyQualifiedSymbolName(field.Type)))
                                             .WithBody(SyntaxFactory.Block(
                                                           SyntaxFactory.IfStatement(
                                                               SyntaxFactory.BinaryExpression(
                                                                   SyntaxKind.EqualsExpression,
                                                                   valueParameterName,
                                                                   SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), field.NameAsField)),
                                                               SyntaxFactory.Block(
                                                                   SyntaxFactory.ReturnStatement(SyntaxFactory.ThisExpression()))),
                                                           SyntaxFactory.ReturnStatement(
                                                               SyntaxFactory.InvocationExpression(
                                                                   SyntaxFactory.MemberAccessExpression(
                                                                       SyntaxKind.SimpleMemberAccessExpression,
                                                                       SyntaxFactory.ThisExpression(),
                                                                       WithMethodName),
                                                                   SyntaxFactory.ArgumentList(
                                                                       SyntaxFactory.SingletonSeparatedList(
                                                                           SyntaxFactory.Argument(
                                                                               SyntaxFactory.NameColon(field.Name),
                                                                               NoneToken,
                                                                               Syntax.OptionalFor(valueParameterName))))))));

                    this.innerMembers.Add(withPropertyMethod);
                }

                foreach (var field in this.generator.applyToMetaType.InheritedFields)
                {
                    string withMethodName     = WithPropertyMethodPrefix + field.Name.ToPascalCase();
                    var    withPropertyMethod = SyntaxFactory.MethodDeclaration(
                        GetFullyQualifiedSymbolName(this.generator.applyToSymbol),
                        withMethodName)
                                                .AddModifiers(
                        SyntaxFactory.Token(SyntaxKind.NewKeyword),
                        SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                                                .AddParameterListParameters(
                        SyntaxFactory.Parameter(valueParameterName.Identifier)
                        .WithType(GetFullyQualifiedSymbolName(field.Type)))
                                                .WithBody(SyntaxFactory.Block(
                                                              SyntaxFactory.ReturnStatement(
                                                                  SyntaxFactory.CastExpression(
                                                                      GetFullyQualifiedSymbolName(this.generator.applyToSymbol),
                                                                      SyntaxFactory.InvocationExpression(
                                                                          SyntaxFactory.MemberAccessExpression(
                                                                              SyntaxKind.SimpleMemberAccessExpression,
                                                                              SyntaxFactory.BaseExpression(),
                                                                              SyntaxFactory.IdentifierName(withMethodName)),
                                                                          SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(valueParameterName))))))));

                    this.innerMembers.Add(withPropertyMethod);
                }
            }