protected MemberDeclarationSyntax CreateConstructor()
            {
                var immutableParameterName = SyntaxFactory.IdentifierName("immutable");
                var body = SyntaxFactory.Block(
                    SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                          SyntaxKind.SimpleAssignmentExpression,
                                                          Syntax.ThisDot(ImmutableFieldName),
                                                          immutableParameterName)));

                foreach (var field in this.generator.applyToMetaType.LocalFields)
                {
                    if (!field.IsGeneratedImmutableType)
                    {
                        body = body.AddStatements(SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                                                        SyntaxKind.SimpleAssignmentExpression,
                                                                                        Syntax.ThisDot(field.NameAsField),
                                                                                        SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, immutableParameterName, field.NameAsField))));
                    }
                }

                var ctor = SyntaxFactory.ConstructorDeclaration(BuilderTypeName.Identifier)
                           .AddParameterListParameters(
                    SyntaxFactory.Parameter(immutableParameterName.Identifier).WithType(SyntaxFactory.IdentifierName(this.generator.applyTo.Identifier)))
                           .AddModifiers(SyntaxFactory.Token(SyntaxKind.InternalKeyword))
                           .WithBody(body);

                if (this.generator.applyToMetaType.HasAncestor)
                {
                    ctor = ctor.WithInitializer(SyntaxFactory.ConstructorInitializer(
                                                    SyntaxKind.BaseConstructorInitializer,
                                                    SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(immutableParameterName)))));
                }

                return(ctor);
            }
Exemple #2
0
            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 MethodDeclarationSyntax CreateParamsElementArrayMethod(MetaField field, IdentifierNameSyntax methodName, SimpleNameSyntax collectionMutationMethodName, bool passThroughChildSync = false)
            {
                var paramsArrayMethod = CreateMethodStarter(methodName.Identifier, field)
                                        .WithParameterList(CreateParamsElementArrayParameters(field));

                var lambdaParameter = SyntaxFactory.Parameter(SyntaxFactory.Identifier("v"));
                var argument        = passThroughChildSync
                    ? (ExpressionSyntax)Syntax.EnumerableExtension(
                    SyntaxFactory.IdentifierName(nameof(Enumerable.Select)),
                    ValuesParameterName,
                    SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                   SyntaxFactory.Argument(Syntax.ThisDot(SyncImmediateChildToCurrentVersionMethodName)))))
                    : ValuesParameterName;

                paramsArrayMethod = this.AddMethodBody(
                    paramsArrayMethod,
                    field,
                    receiver => SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            receiver,
                            collectionMutationMethodName),
                        SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                       SyntaxFactory.Argument(argument)))));

                return(paramsArrayMethod);
            }
            private MethodDeclarationSyntax CreateSingleElementMethod(MetaField field, IdentifierNameSyntax methodName, SimpleNameSyntax collectionMutationMethodName, bool passThroughChildSync = false, IdentifierNameSyntax elementParameterName = null, ITypeSymbol elementType = null)
            {
                elementParameterName = elementParameterName ?? ValueParameterName;

                var paramsArrayMethod = CreateMethodStarter(methodName.Identifier, field)
                                        .WithParameterList(SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList(
                                                                                           SyntaxFactory.Parameter(elementParameterName.Identifier)
                                                                                           .WithType(GetFullyQualifiedSymbolName(elementType ?? field.ElementType)))));

                var argument = passThroughChildSync
                    ? (ExpressionSyntax)SyntaxFactory.InvocationExpression(
                    Syntax.ThisDot(SyncImmediateChildToCurrentVersionMethodName),
                    SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(elementParameterName))))
                    : elementParameterName;

                paramsArrayMethod = this.AddMethodBody(
                    paramsArrayMethod,
                    field,
                    receiver => SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            receiver,
                            collectionMutationMethodName),
                        SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                       SyntaxFactory.Argument(argument)))));

                return(paramsArrayMethod);
            }
Exemple #5
0
            protected override void GenerateCore()
            {
                this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveType))));

                //// uint IRecursiveType.Identity => this.Identity;
                this.innerMembers.Add(SyntaxFactory.PropertyDeclaration(
                                          IdentityFieldTypeSyntax,
                                          nameof(IRecursiveType.Identity))
                                      .WithExplicitInterfaceSpecifier(
                                          SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveType))))
                                      .WithExpressionBody(
                                          SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(IdentityPropertyName)))
                                      .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                                      .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));
            }
Exemple #6
0
 protected MethodDeclarationSyntax CreateFindMethod()
 {
     // public TRecursiveType Find(uint identity)
     return(SyntaxFactory.MethodDeclaration(this.applyTo.RecursiveType.TypeSyntax, FindMethodName.Identifier)
            .AddParameterListParameters(RequiredIdentityParameter)
            .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
            .WithBody(SyntaxFactory.Block(
                          // return this.Find<TRecursiveParent, TRecursiveType>(identity);
                          SyntaxFactory.ReturnStatement(
                              SyntaxFactory.InvocationExpression(
                                  Syntax.ThisDot(
                                      SyntaxFactory.GenericName(FindMethodName.Identifier).AddTypeArgumentListArguments(
                                          this.applyTo.RecursiveParent.TypeSyntax,
                                          this.applyTo.RecursiveType.TypeSyntax)))
                              .AddArgumentListArguments(SyntaxFactory.Argument(IdentityParameterName))))));
 }
Exemple #7
0
            private MethodDeclarationSyntax CreateGetParentMethod()
            {
                // public TRecursiveParent GetParent(TRecursiveType descendent)
                var descendentParam = SyntaxFactory.IdentifierName("descendent");

                return(SyntaxFactory.MethodDeclaration(this.applyTo.RecursiveParent.TypeSyntax, GetParentMethodName.Identifier)
                       .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                       .AddParameterListParameters(SyntaxFactory.Parameter(descendentParam.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax))
                       .WithBody(SyntaxFactory.Block(
                                     // return this.GetParent<TRecursiveParent, TRecursiveType>(descendent);
                                     SyntaxFactory.ReturnStatement(
                                         SyntaxFactory.InvocationExpression(
                                             Syntax.ThisDot(
                                                 SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetParent))
                                                 .AddTypeArgumentListArguments(this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax)))
                                         .AddArgumentListArguments(SyntaxFactory.Argument(descendentParam))))));
            }
            private MethodDeclarationSyntax CreateSyncImmediateChildToCurrentVersionMethod()
            {
                var childParameterName  = SyntaxFactory.IdentifierName("child");
                var childType           = GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveField.ElementType);
                var currentValueVarName = SyntaxFactory.IdentifierName("currentValue");

                return(SyntaxFactory.MethodDeclaration(
                           childType,
                           SyncImmediateChildToCurrentVersionMethodName.Identifier)
                       .AddParameterListParameters(SyntaxFactory.Parameter(childParameterName.Identifier).WithType(childType))
                       .AddModifiers(SyntaxFactory.Token(SyntaxKind.ProtectedKeyword))
                       .WithBody(SyntaxFactory.Block(
                                     // ElementTypeName currentValue;
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(
                                                                                 childType,
                                                                                 SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(currentValueVarName.Identifier)))),
                                     // if (!this.TryFindImmediateChild(child.<#= templateType.RequiredIdentityField.NamePascalCase #>, out currentValue)) {
                                     SyntaxFactory.IfStatement(
                                         SyntaxFactory.PrefixUnaryExpression(
                                             SyntaxKind.LogicalNotExpression,
                                             SyntaxFactory.InvocationExpression(
                                                 Syntax.ThisDot(SyntaxFactory.IdentifierName(nameof(RecursiveTypeExtensions.TryFindImmediateChild))),
                                                 SyntaxFactory.ArgumentList(Syntax.JoinSyntaxNodes(
                                                                                SyntaxKind.CommaToken,
                                                                                SyntaxFactory.Argument(
                                                                                    SyntaxFactory.MemberAccessExpression(
                                                                                        SyntaxKind.SimpleMemberAccessExpression,
                                                                                        childParameterName,
                                                                                        IdentityPropertyName)),
                                                                                SyntaxFactory.Argument(
                                                                                    null,
                                                                                    SyntaxFactory.Token(SyntaxKind.OutKeyword),
                                                                                    currentValueVarName))))),
                                         SyntaxFactory.Block(
                                             SyntaxFactory.ThrowStatement(SyntaxFactory.ObjectCreationExpression(
                                                                              Syntax.GetTypeSyntax(typeof(ArgumentException)),
                                                                              SyntaxFactory.ArgumentList(),
                                                                              null)))),
                                     SyntaxFactory.ReturnStatement(currentValueVarName))));
            }
Exemple #9
0
            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))));
                }

                // IReadOnlyList<IRecursiveType> IRecursiveParentWithOrderedChildren.Children => this.children;
                this.innerMembers.Add(SyntaxFactory.PropertyDeclaration(
                                          Syntax.IReadOnlyListOf(Syntax.GetTypeSyntax(typeof(IRecursiveType))),
                                          nameof(IRecursiveParentWithOrderedChildren.Children))
                                      .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithOrderedChildren))))
                                      .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name))))
                                      .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                                      .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                // 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 MethodDeclarationSyntax AddMethodBody(MethodDeclarationSyntax containingMethod, MetaField field, Func <ExpressionSyntax, InvocationExpressionSyntax> mutatingInvocationFactory)
            {
                var returnExpression = field.IsLocallyDefined
                    ? (ExpressionSyntax)SyntaxFactory.InvocationExpression( // this.With(field: this.field.SomeOperation(someArgs))
                    Syntax.ThisDot(WithMethodName),
                    SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                   SyntaxFactory.Argument(
                                                       SyntaxFactory.NameColon(field.Name),
                                                       NoneToken,
                                                       mutatingInvocationFactory(Syntax.ThisDot(field.NameAsField))))))
                    : SyntaxFactory.CastExpression( // (TemplateType)base.SameMethod(sameArgs)
                    GetFullyQualifiedSymbolName(this.generator.applyToSymbol),
                    SyntaxFactory.InvocationExpression(
                        Syntax.BaseDot(SyntaxFactory.IdentifierName(containingMethod.Identifier)),
                        SyntaxFactory.ArgumentList(
                            Syntax.JoinSyntaxNodes(
                                SyntaxKind.CommaToken,
                                containingMethod.ParameterList.Parameters.Select(p => SyntaxFactory.Argument(SyntaxFactory.IdentifierName(p.Identifier)))))));

                return(containingMethod.WithBody(SyntaxFactory.Block(
                                                     SyntaxFactory.ReturnStatement(returnExpression))));
            }
Exemple #11
0
            private void ImplementIEnumerableInterfaces()
            {
                this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.IEnumerableOf(this.generator.applyToMetaType.RecursiveType.TypeSyntax)));

                // return ((IEnumerable<RecursiveType>)this.<#=templateType.RecursiveField.NameCamelCase#>).GetEnumerator();
                var body = SyntaxFactory.Block(
                    SyntaxFactory.ReturnStatement(
                        SyntaxFactory.InvocationExpression(
                            SyntaxFactory.MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                SyntaxFactory.ParenthesizedExpression(
                                    SyntaxFactory.CastExpression(
                                        Syntax.IEnumerableOf(GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveField.ElementType)),
                                        Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name)))),
                                SyntaxFactory.IdentifierName(nameof(IEnumerable <int> .GetEnumerator))),
                            SyntaxFactory.ArgumentList())));

                // public System.Collections.Generic.IEnumerator<RecursiveType> GetEnumerator()
                this.innerMembers.Add(
                    SyntaxFactory.MethodDeclaration(
                        Syntax.IEnumeratorOf(GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveField.ElementType)),
                        nameof(IEnumerable <int> .GetEnumerator))
                    .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                    .WithBody(body));

                // System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
                this.innerMembers.Add(
                    SyntaxFactory.MethodDeclaration(
                        Syntax.GetTypeSyntax(typeof(System.Collections.IEnumerator)),
                        nameof(IEnumerable <int> .GetEnumerator))
                    .WithExplicitInterfaceSpecifier(
                        SyntaxFactory.ExplicitInterfaceSpecifier(
                            SyntaxFactory.QualifiedName(
                                SyntaxFactory.QualifiedName(
                                    SyntaxFactory.IdentifierName(nameof(System)),
                                    SyntaxFactory.IdentifierName(nameof(System.Collections))),
                                SyntaxFactory.IdentifierName(nameof(System.Collections.IEnumerable)))))
                    .WithBody(body));
            }
Exemple #12
0
            protected override void GenerateCore()
            {
                if (this.applyTo.IsRecursiveParent)
                {
                    this.baseTypes.Add(SyntaxFactory.SimpleBaseType(this.IRecursiveParentWithChildReplacementType));
                    this.innerMembers.Add(this.CreateReplaceChildMethod());

                    // private readonly uint inefficiencyLoad;
                    var inefficiencyLoadType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.UIntKeyword));
                    this.innerMembers.Add(SyntaxFactory.FieldDeclaration(
                                              SyntaxFactory.VariableDeclaration(inefficiencyLoadType)
                                              .AddVariables(SyntaxFactory.VariableDeclarator(InefficiencyLoadFieldName.Identifier)))
                                          .AddModifiers(
                                              SyntaxFactory.Token(SyntaxKind.PrivateKeyword),
                                              SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))
                                          .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                    var interfaceType = SyntaxFactory.QualifiedName(
                        SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)),
                        SyntaxFactory.GenericName(
                            SyntaxFactory.Identifier(nameof(IRecursiveParentWithLookupTable <IRecursiveType>)),
                            SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList <TypeSyntax>(this.applyTo.RecursiveType.TypeSyntax))));
                    this.baseTypes.Add(SyntaxFactory.SimpleBaseType(interfaceType));
                    var explicitImplementation = SyntaxFactory.ExplicitInterfaceSpecifier(interfaceType);

                    // uint IRecursiveParentWithLookupTable<TRecursiveType>.InefficiencyLoad => this.ineffiencyLoad;
                    this.innerMembers.Add(
                        SyntaxFactory.PropertyDeclaration(inefficiencyLoadType, nameof(IRecursiveParentWithLookupTable <IRecursiveType> .InefficiencyLoad))
                        .WithExplicitInterfaceSpecifier(explicitImplementation)
                        .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(InefficiencyLoadFieldName)))
                        .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                        .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                    // IReadOnlyCollection<TRecursiveType> IRecursiveParentWithLookupTable<TRecursiveType>.Children => this.recursiveField;
                    this.innerMembers.Add(
                        SyntaxFactory.PropertyDeclaration(
                            Syntax.IReadOnlyCollectionOf(this.applyTo.RecursiveType.TypeSyntax),
                            nameof(IRecursiveParentWithLookupTable <IRecursiveType> .Children))
                        .WithExplicitInterfaceSpecifier(explicitImplementation)
                        .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(this.applyTo.RecursiveField.NameAsProperty)))
                        .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                        .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                    // ImmutableDictionary<IdentityFieldType, KeyValuePair<TRecursiveType, IdentityFieldType>> IRecursiveParentWithLookupTable<TRecursiveType>.LookupTable => this.lookupTable;
                    this.innerMembers.Add(
                        SyntaxFactory.PropertyDeclaration(
                            this.lookupTableType,
                            nameof(IRecursiveParentWithLookupTable <IRecursiveType> .LookupTable))
                        .WithExplicitInterfaceSpecifier(explicitImplementation)
                        .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(LookupTablePropertyName)))
                        .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                        .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));
                }

                if (this.applyTo.IsRecursive)
                {
                    var lookupInitResultVarName = SyntaxFactory.IdentifierName("lookupInitResult");
                    this.additionalCtorStatements.AddRange(new StatementSyntax[] {
                        // var lookupInitResult = ImmutableObjectGraph.RecursiveTypeExtensions.LookupTable<TRecursiveType, TRecursiveParent>.Initialize(this, lookupTable);
                        SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(
                                                                    varType,
                                                                    SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(lookupInitResultVarName.Identifier)
                                                                                                         .WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                              SyntaxFactory.InvocationExpression(
                                                                                                                                  GetLookupTableHelperMember(nameof(LookupTableHelper.Initialize)),
                                                                                                                                  SyntaxFactory.ArgumentList(Syntax.JoinSyntaxNodes(
                                                                                                                                                                 SyntaxKind.CommaToken,
                                                                                                                                                                 SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                                                                                                                                                 SyntaxFactory.Argument(LookupTableFieldName))))))))),
                        // this.inefficiencyLoad = lookupInitResult.InefficiencyLoad;
                        SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                              SyntaxKind.SimpleAssignmentExpression,
                                                              Syntax.ThisDot(InefficiencyLoadFieldName),
                                                              SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, lookupInitResultVarName, SyntaxFactory.IdentifierName(nameof(LookupTableHelper.InitializeLookupResult.InefficiencyLoad))))),
                        // this.lookupTable = lookupInitResult.LookupTable;
                        SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                              SyntaxKind.SimpleAssignmentExpression,
                                                              Syntax.ThisDot(LookupTableFieldName),
                                                              SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, lookupInitResultVarName, SyntaxFactory.IdentifierName(nameof(LookupTableHelper.InitializeLookupResult.LookupTable)))))
                    });

                    this.innerMembers.Add(SyntaxFactory.PropertyDeclaration(
                                              this.lookupTableType,
                                              LookupTablePropertyName.Identifier)
                                          .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))
                                          .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration(
                                                                        SyntaxKind.GetAccessorDeclaration,
                                                                        SyntaxFactory.Block(
                                                                            SyntaxFactory.IfStatement(
                                                                                SyntaxFactory.BinaryExpression(
                                                                                    SyntaxKind.EqualsExpression,
                                                                                    Syntax.ThisDot(LookupTableFieldName),
                                                                                    GetLookupTableHelperMember(nameof(LookupTableHelper.LazySentinel))),
                                                                                SyntaxFactory.Block(
                                                                                    SyntaxFactory.ExpressionStatement(
                                                                                        SyntaxFactory.AssignmentExpression(
                                                                                            SyntaxKind.SimpleAssignmentExpression,
                                                                                            Syntax.ThisDot(LookupTableFieldName),
                                                                                            SyntaxFactory.InvocationExpression(
                                                                                                GetLookupTableHelperMember(nameof(LookupTableHelper.CreateLookupTable)),
                                                                                                SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                                                                                               SyntaxFactory.Argument(SyntaxFactory.ThisExpression())))))))),
                                                                            SyntaxFactory.ReturnStatement(Syntax.ThisDot(LookupTableFieldName))))));

                    // protected System.Collections.Immutable.ImmutableDictionary<System.UInt32, KeyValuePair<FileSystemEntry, System.UInt32>> lookupTable;
                    this.innerMembers.Add(SyntaxFactory.FieldDeclaration(
                                              SyntaxFactory.VariableDeclaration(this.lookupTableType)
                                              .AddVariables(SyntaxFactory.VariableDeclarator(LookupTableFieldName.Identifier)))
                                          .AddModifiers(SyntaxFactory.Token(SyntaxKind.ProtectedKeyword))
                                          .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                    // public System.Collections.Immutable.ImmutableStack<TRecursiveType> GetSpine(TRecursiveType descendent) {
                    //  return ImmutableObjectGraph.RecursiveTypeExtensions.GetSpine<TRecursiveParent, TRecursiveType>(this, descendent);
                    // }
                    var descendentParameter = SyntaxFactory.IdentifierName("descendent");
                    this.innerMembers.Add(
                        SyntaxFactory.MethodDeclaration(Syntax.ImmutableStackOf(this.applyTo.RecursiveType.TypeSyntax), GetSpineMethodName.Identifier)
                        .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                        .AddAttributeLists(PureAttributeList)
                        .AddParameterListParameters(SyntaxFactory.Parameter(descendentParameter.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax))
                        .WithBody(SyntaxFactory.Block(
                                      SyntaxFactory.ReturnStatement(
                                          SyntaxFactory.InvocationExpression(
                                              SyntaxFactory.MemberAccessExpression(
                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                  Syntax.GetTypeSyntax(typeof(RecursiveTypeExtensions)),
                                                  SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetSpine))
                                                  .AddTypeArgumentListArguments(this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax)))
                                          .AddArgumentListArguments(
                                              SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                              SyntaxFactory.Argument(descendentParameter))))));

                    // public System.Collections.Immutable.ImmutableStack<TRecursiveType> GetSpine(uint identity) {
                    //  return ImmutableObjectGraph.RecursiveTypeExtensions.GetSpine<TRecursiveParent, TRecursiveType>(this, identity);
                    // }
                    var identityParameter = SyntaxFactory.IdentifierName("identity");
                    this.innerMembers.Add(
                        SyntaxFactory.MethodDeclaration(Syntax.ImmutableStackOf(this.applyTo.RecursiveType.TypeSyntax), GetSpineMethodName.Identifier)
                        .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                        .AddParameterListParameters(SyntaxFactory.Parameter(identityParameter.Identifier).WithType(IdentityFieldTypeSyntax))
                        .AddAttributeLists(PureAttributeList)
                        .WithBody(SyntaxFactory.Block(
                                      SyntaxFactory.ReturnStatement(
                                          SyntaxFactory.InvocationExpression(
                                              SyntaxFactory.MemberAccessExpression(
                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                  Syntax.GetTypeSyntax(typeof(RecursiveTypeExtensions)),
                                                  SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetSpine))
                                                  .AddTypeArgumentListArguments(this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax)))
                                          .AddArgumentListArguments(
                                              SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                              SyntaxFactory.Argument(identityParameter))))));

                    this.innerMembers.Add(this.CreateFindMethod());
                }
            }
            protected IReadOnlyList <MemberDeclarationSyntax> CreateMutableProperties()
            {
                var properties = new List <PropertyDeclarationSyntax>();

                foreach (var field in this.generator.applyToMetaType.LocalFields)
                {
                    var thisField = Syntax.ThisDot(field.NameAsField);
                    var optionalFieldNotYetDefined = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(thisField));
                    var getterBlock = field.IsGeneratedImmutableType
                        ? SyntaxFactory.Block(
                        // if (!this.fieldName.IsDefined) {
                        SyntaxFactory.IfStatement(
                            optionalFieldNotYetDefined,
                            SyntaxFactory.Block(
                                // this.fieldName = this.immutable.fieldName?.ToBuilder();
                                SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                                      SyntaxKind.SimpleAssignmentExpression,
                                                                      thisField,
                                                                      SyntaxFactory.ConditionalAccessExpression(
                                                                          SyntaxFactory.MemberAccessExpression(
                                                                              SyntaxKind.SimpleMemberAccessExpression,
                                                                              Syntax.ThisDot(ImmutableFieldName),
                                                                              field.NameAsField),
                                                                          SyntaxFactory.InvocationExpression(
                                                                              SyntaxFactory.MemberBindingExpression(ToBuilderMethodName),
                                                                              SyntaxFactory.ArgumentList())))))),
                        SyntaxFactory.ReturnStatement(Syntax.OptionalValue(thisField)))
                        : SyntaxFactory.Block(SyntaxFactory.ReturnStatement(thisField));
                    var setterValueArg  = SyntaxFactory.IdentifierName("value");
                    var setterCondition = field.IsGeneratedImmutableType ?
                                          SyntaxFactory.BinaryExpression(
                        SyntaxKind.LogicalOrExpression,
                        optionalFieldNotYetDefined,
                        SyntaxFactory.BinaryExpression(
                            SyntaxKind.NotEqualsExpression,
                            Syntax.OptionalValue(thisField),
                            setterValueArg)) :
                                          HasEqualityOperators(field.Symbol.Type) ?
                                          SyntaxFactory.BinaryExpression(
                        SyntaxKind.NotEqualsExpression,
                        thisField,
                        setterValueArg) :
                                          null;
                    var setterSignificantBlock = SyntaxFactory.Block(
                        SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                              SyntaxKind.SimpleAssignmentExpression,
                                                              thisField,
                                                              setterValueArg)),
                        SyntaxFactory.ExpressionStatement(
                            SyntaxFactory.InvocationExpression(
                                SyntaxFactory.MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    SyntaxFactory.ThisExpression(),
                                    OnPropertyChangedMethodName))));
                    var setterBlock = setterCondition != null?
                                      SyntaxFactory.Block(
                        SyntaxFactory.IfStatement(
                            setterCondition,
                            setterSignificantBlock)) :
                                          setterSignificantBlock;

                    var property = SyntaxFactory.PropertyDeclaration(
                        this.GetPropertyTypeForBuilder(field),
                        field.Name.ToPascalCase())
                                   .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                                   .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List(new AccessorDeclarationSyntax[]
                    {
                        SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, getterBlock),
                        SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, setterBlock),
                    })));
                    properties.Add(property);
                }

                return(properties);
            }
Exemple #14
0
            private MethodDeclarationSyntax CreateAddDescendentMethod()
            {
                var valueParameterName  = SyntaxFactory.IdentifierName("value");
                var parentParameterName = SyntaxFactory.IdentifierName("parent");
                var spineVar            = SyntaxFactory.IdentifierName("spine");
                var newParentVar        = SyntaxFactory.IdentifierName("newParent");
                var newSpineVar         = SyntaxFactory.IdentifierName("newSpine");

                return(SyntaxFactory.MethodDeclaration(
                           GetFullyQualifiedSymbolName(this.generator.applyToSymbol),
                           AddDescendentMethodName.Identifier)
                       .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                       .AddAttributeLists(PureAttributeList)
                       .AddParameterListParameters(
                           SyntaxFactory.Parameter(valueParameterName.Identifier).WithType(this.generator.applyToMetaType.RecursiveType.TypeSyntax),
                           SyntaxFactory.Parameter(parentParameterName.Identifier).WithType(this.generator.applyToMetaType.RecursiveParent.TypeSyntax))
                       .WithBody(SyntaxFactory.Block(
                                     // var spine = this.GetSpine(parent);
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables(
                                                                                 SyntaxFactory.VariableDeclarator(spineVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                           SyntaxFactory.InvocationExpression(Syntax.ThisDot(FastSpineGen.GetSpineMethodName))
                                                                                                                                                           .AddArgumentListArguments(SyntaxFactory.Argument(parentParameterName)))))),
                                     // var newParent = parent.With(children: parent.Children.Add(value));
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables(
                                                                                 SyntaxFactory.VariableDeclarator(newParentVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                               SyntaxFactory.InvocationExpression(
                                                                                                                                                                   SyntaxFactory.MemberAccessExpression(
                                                                                                                                                                       SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                                                       parentParameterName,
                                                                                                                                                                       WithMethodName))
                                                                                                                                                               .AddArgumentListArguments(SyntaxFactory.Argument(
                                                                                                                                                                                             SyntaxFactory.NameColon(this.applyTo.RecursiveField.NameAsField),
                                                                                                                                                                                             NoneToken,
                                                                                                                                                                                             SyntaxFactory.InvocationExpression(
                                                                                                                                                                                                 SyntaxFactory.MemberAccessExpression(
                                                                                                                                                                                                     SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                                                                                     SyntaxFactory.MemberAccessExpression(
                                                                                                                                                                                                         SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                                                                                         parentParameterName,
                                                                                                                                                                                                         this.applyTo.RecursiveField.NameAsProperty),
                                                                                                                                                                                                     SyntaxFactory.IdentifierName(nameof(List <int> .Add))),
                                                                                                                                                                                                 SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(valueParameterName)))))))))),
                                     // var newSpine = System.Collections.Immutable.ImmutableStack.Create(value, newParent);
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables(
                                                                                 SyntaxFactory.VariableDeclarator(newSpineVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                              SyntaxFactory.InvocationExpression(Syntax.CreateImmutableStack())
                                                                                                                                                              .AddArgumentListArguments(
                                                                                                                                                                  SyntaxFactory.Argument(valueParameterName),
                                                                                                                                                                  SyntaxFactory.Argument(newParentVar)))))),
                                     // return (ProjectElementContainer)RecursiveTypeExtensions.ReplaceDescendent(this, spine, newSpine, spineIncludesDeletedElement: false).Peek();
                                     SyntaxFactory.ReturnStatement(
                                         SyntaxFactory.CastExpression(
                                             this.applyTo.TypeSyntax,
                                             SyntaxFactory.InvocationExpression(
                                                 SyntaxFactory.MemberAccessExpression(
                                                     SyntaxKind.SimpleMemberAccessExpression,
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.MemberAccessExpression(
                                                             SyntaxKind.SimpleMemberAccessExpression,
                                                             SyntaxFactory.QualifiedName(
                                                                 SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)),
                                                                 SyntaxFactory.IdentifierName(nameof(RecursiveTypeExtensions))),
                                                             ReplaceDescendentMethodName))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                                         SyntaxFactory.Argument(spineVar),
                                                         SyntaxFactory.Argument(newSpineVar),
                                                         SyntaxFactory.Argument(SyntaxFactory.NameColon("spineIncludesDeletedElement"), NoneToken, SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression))),
                                                     SyntaxFactory.IdentifierName(nameof(ImmutableStack <int> .Peek))),
                                                 SyntaxFactory.ArgumentList())))
                                     )));
            }
Exemple #15
0
            private MethodDeclarationSyntax CreateReplaceDescendentDifferentIdentityMethod()
            {
                var currentParameter     = SyntaxFactory.IdentifierName("current");
                var replacementParameter = SyntaxFactory.IdentifierName("replacement");
                var spineVar             = SyntaxFactory.IdentifierName("spine");

                // public TemplateType ReplaceDescendent(TRecursiveType current, TRecursiveType replacement) {
                return(SyntaxFactory.MethodDeclaration(
                           this.applyTo.TypeSyntax,
                           ReplaceDescendentMethodName.Identifier)
                       .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                       .AddAttributeLists(PureAttributeList)
                       .AddParameterListParameters(
                           SyntaxFactory.Parameter(currentParameter.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax),
                           SyntaxFactory.Parameter(replacementParameter.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax))
                       .WithBody(SyntaxFactory.Block(
                                     // var spine = this.GetSpine(current);
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables(
                                                                                 SyntaxFactory.VariableDeclarator(spineVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                           SyntaxFactory.InvocationExpression(Syntax.ThisDot(FastSpineGen.GetSpineMethodName))
                                                                                                                                                           .AddArgumentListArguments(
                                                                                                                                                               SyntaxFactory.Argument(currentParameter)))))),
                                     // if (spine.IsEmpty) {
                                     SyntaxFactory.IfStatement(
                                         SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, spineVar, SyntaxFactory.IdentifierName(nameof(ImmutableStack <int> .IsEmpty))),
                                         //     // The descendent was not found.
                                         //     throw new System.ArgumentException("Old value not found");
                                         SyntaxFactory.Block(
                                             SyntaxFactory.ThrowStatement(
                                                 SyntaxFactory.ObjectCreationExpression(Syntax.GetTypeSyntax(typeof(ArgumentException))).AddArgumentListArguments(
                                                     SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("Old value not found."))))))),
                                     // return (TemplateType)ImmutableObjectGraph.RecursiveTypeExtensions.ReplaceDescendent(this, spine, ImmutableStack.Create(replacement), spineIncludesDeletedElement: false).Peek();
                                     SyntaxFactory.ReturnStatement(
                                         SyntaxFactory.CastExpression(
                                             this.applyTo.TypeSyntax,
                                             SyntaxFactory.InvocationExpression(
                                                 SyntaxFactory.MemberAccessExpression(
                                                     SyntaxKind.SimpleMemberAccessExpression,
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.MemberAccessExpression(
                                                             SyntaxKind.SimpleMemberAccessExpression,
                                                             Syntax.GetTypeSyntax(typeof(RecursiveTypeExtensions)),
                                                             ReplaceDescendentMethodName))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                                         SyntaxFactory.Argument(spineVar),
                                                         SyntaxFactory.Argument(SyntaxFactory.InvocationExpression(Syntax.CreateImmutableStack()).AddArgumentListArguments(
                                                                                    SyntaxFactory.Argument(replacementParameter))),
                                                         SyntaxFactory.Argument(SyntaxFactory.NameColon("spineIncludesDeletedElement"), NoneToken, SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression))
                                                         ),
                                                     SyntaxFactory.IdentifierName(nameof(ImmutableStack <int> .Peek))),
                                                 SyntaxFactory.ArgumentList()))))));
            }
Exemple #16
0
            private MethodDeclarationSyntax CreateRemoveDescendentMethod()
            {
                var valueParameter = SyntaxFactory.IdentifierName("value");
                var spineVar       = SyntaxFactory.IdentifierName("spine");
                var spineListVar   = SyntaxFactory.IdentifierName("spineList");
                var parentVar      = SyntaxFactory.IdentifierName("parent");
                var newParentVar   = SyntaxFactory.IdentifierName("newParent");
                var newSpineVar    = SyntaxFactory.IdentifierName("newSpine");

                // public TemplateType RemoveDescendent(TRecursiveType value) {
                return(SyntaxFactory.MethodDeclaration(
                           this.applyTo.TypeSyntax,
                           RemoveDescendentMethodName.Identifier)
                       .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                       .AddAttributeLists(PureAttributeList)
                       .AddParameterListParameters(
                           SyntaxFactory.Parameter(valueParameter.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax))
                       .WithBody(SyntaxFactory.Block(
                                     // var spine = this.GetSpine(value);
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType)
                                                                             .AddVariables(SyntaxFactory.VariableDeclarator(spineVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                     SyntaxFactory.InvocationExpression(Syntax.ThisDot(FastSpineGen.GetSpineMethodName)).AddArgumentListArguments(
                                                                                                                                                                         SyntaxFactory.Argument(valueParameter)))))),
                                     // var spineList = spine.ToList();
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType)
                                                                             .AddVariables(SyntaxFactory.VariableDeclarator(spineListVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                         Syntax.ToList(spineVar))))),
                                     // var parent = (TRecursiveParent)spineList[spineList.Count - 2];
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType)
                                                                             .AddVariables(SyntaxFactory.VariableDeclarator(parentVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                      SyntaxFactory.CastExpression(
                                                                                                                                                                          this.applyTo.RecursiveParent.TypeSyntax,
                                                                                                                                                                          SyntaxFactory.ElementAccessExpression(
                                                                                                                                                                              spineListVar,
                                                                                                                                                                              SyntaxFactory.BracketedArgumentList(
                                                                                                                                                                                  SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                      SyntaxFactory.Argument(SyntaxFactory.BinaryExpression(
                                                                                                                                                                                                                 SyntaxKind.SubtractExpression,
                                                                                                                                                                                                                 SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, spineListVar, SyntaxFactory.IdentifierName(nameof(List <int> .Count))),
                                                                                                                                                                                                                 SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(2)))))))))))),
                                     // var newParent = parent.With(children: parent.Children.Remove(spineList[spineList.Count - 1]));
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType)
                                                                             .AddVariables(SyntaxFactory.VariableDeclarator(newParentVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                         SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentVar, WithMethodName))
                                                                                                                                                                         .AddArgumentListArguments(
                                                                                                                                                                             SyntaxFactory.Argument(
                                                                                                                                                                                 SyntaxFactory.NameColon(this.applyTo.RecursiveField.NameAsField),
                                                                                                                                                                                 NoneToken,
                                                                                                                                                                                 SyntaxFactory.InvocationExpression(       // parent.Children.Remove(...)
                                                                                                                                                                                     SyntaxFactory.MemberAccessExpression( // parent.Children.Remove
                                                                                                                                                                                         SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                                                                         SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentVar, this.applyTo.RecursiveField.NameAsProperty),
                                                                                                                                                                                         SyntaxFactory.IdentifierName(nameof(List <int> .Remove))))
                                                                                                                                                                                 .AddArgumentListArguments(
                                                                                                                                                                                     SyntaxFactory.Argument(SyntaxFactory.ElementAccessExpression( // spineList[spineList.Count - 1]
                                                                                                                                                                                                                spineListVar,
                                                                                                                                                                                                                SyntaxFactory.BracketedArgumentList(SyntaxFactory.SingletonSeparatedList(
                                                                                                                                                                                                                                                        SyntaxFactory.Argument( // spineList.Count - 1
                                                                                                                                                                                                                                                            SyntaxFactory.BinaryExpression(
                                                                                                                                                                                                                                                                SyntaxKind.SubtractExpression,
                                                                                                                                                                                                                                                                SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, spineListVar, SyntaxFactory.IdentifierName(nameof(List <int> .Count))),
                                                                                                                                                                                                                                                                SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(1))))))))))))))),
                                     // var newSpine = System.Collections.Immutable.ImmutableStack.Create<TRecursiveType>(newParent);
                                     SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType)
                                                                             .AddVariables(SyntaxFactory.VariableDeclarator(newSpineVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                                        SyntaxFactory.InvocationExpression(Syntax.CreateImmutableStack(this.applyTo.RecursiveType.TypeSyntax))
                                                                                                                                                                        .AddArgumentListArguments(SyntaxFactory.Argument(newParentVar)))))),
                                     // return (TRecursiveParent)ImmutableObjectGraph.RecursiveTypeExtensions.ReplaceDescendent(this, spine, newSpine, spineIncludesDeletedElement: true).Peek();
                                     SyntaxFactory.ReturnStatement(
                                         SyntaxFactory.CastExpression(
                                             this.applyTo.RecursiveParent.TypeSyntax,
                                             SyntaxFactory.InvocationExpression(
                                                 SyntaxFactory.MemberAccessExpression(
                                                     SyntaxKind.SimpleMemberAccessExpression,
                                                     SyntaxFactory.InvocationExpression(
                                                         SyntaxFactory.MemberAccessExpression(
                                                             SyntaxKind.SimpleMemberAccessExpression,
                                                             Syntax.GetTypeSyntax(typeof(RecursiveTypeExtensions)),
                                                             ReplaceDescendentMethodName))
                                                     .AddArgumentListArguments(
                                                         SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                                         SyntaxFactory.Argument(spineVar),
                                                         SyntaxFactory.Argument(newSpineVar),
                                                         SyntaxFactory.Argument(SyntaxFactory.NameColon("spineIncludesDeletedElement"), NoneToken, SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression))
                                                         ),
                                                     SyntaxFactory.IdentifierName(nameof(ImmutableStack <int> .Peek))),
                                                 SyntaxFactory.ArgumentList()))))));
            }
Exemple #17
0
            public override ClassDeclarationSyntax ProcessApplyToClassDeclaration(ClassDeclarationSyntax applyTo)
            {
                applyTo = base.ProcessApplyToClassDeclaration(applyTo);

                if (this.applyTo.IsRecursiveParentOrDerivative)
                {
                    // Add the lookupTable parameter to the constructor's signature.
                    var origCtor    = GetMeaningfulConstructor(applyTo);
                    var alteredCtor = origCtor.AddParameterListParameters(SyntaxFactory.Parameter(LookupTableFieldName.Identifier).WithType(Syntax.OptionalOf(this.lookupTableType)));

                    // If this type isn't itself the recursive parent then we derive from it. And we must propagate the value to the chained base type.
                    if (!this.applyTo.IsRecursiveParent)
                    {
                        Assumes.NotNull(alteredCtor.Initializer); // we expect a chained call to the base constructor.
                        alteredCtor = alteredCtor.WithInitializer(
                            alteredCtor.Initializer.AddArgumentListArguments(
                                SyntaxFactory.Argument(SyntaxFactory.NameColon(LookupTableFieldName), NoneToken, LookupTableFieldName)));
                    }

                    // Apply the updated constructor back to the generated type.
                    applyTo = applyTo.ReplaceNode(origCtor, alteredCtor);

                    // Search for invocations of the constructor that we now have to update.
                    var creationInvocations = (
                        from n in applyTo.DescendantNodes()
                        let ctorInvocation = n as ObjectCreationExpressionSyntax
                                             let instantiatedTypeName = ctorInvocation?.Type?.ToString()
                                                                        where instantiatedTypeName == this.applyTo.TypeSyntax.ToString() || instantiatedTypeName == this.applyTo.TypeSymbol.Name
                                                                        select ctorInvocation).ToImmutableArray();
                    var chainedInvocations = (
                        from n in applyTo.DescendantNodes()
                        let chained = n as ConstructorInitializerSyntax
                                      where chained.IsKind(SyntaxKind.ThisConstructorInitializer) && chained.FirstAncestorOrSelf <ConstructorDeclarationSyntax>().Identifier.ValueText == this.applyTo.TypeSymbol.Name
                                      select chained).ToImmutableArray();
                    var invocations = creationInvocations.Concat <CSharpSyntaxNode>(chainedInvocations);
                    var trackedTree = applyTo.TrackNodes(invocations);

                    var recursiveField = this.applyTo.RecursiveParent.RecursiveField;
                    foreach (var ctorInvocation in invocations)
                    {
                        ExpressionSyntax lookupTableValue = SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression);

                        var currentInvocation         = trackedTree.GetCurrentNode(ctorInvocation);
                        var currentCreationInvocation = currentInvocation as ObjectCreationExpressionSyntax;
                        var currentChainedInvocation  = currentInvocation as ConstructorInitializerSyntax;

                        if (currentCreationInvocation != null)
                        {
                            var containingMethod = currentInvocation.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                            if (containingMethod != null)
                            {
                                if (containingMethod.ParameterList.Parameters.Any(p => p.Identifier.ToString() == recursiveField.Name))
                                {
                                    // We're in a method that accepts the recursive field as a parameter.
                                    // The value we want to pass in for the lookup table is:
                                    // (children.IsDefined && children.Value != this.Children) ? default(Optional<ImmutableDictionary<uint, KeyValuePair<RecursiveType, uint>>>) : Optional.For(this.lookupTable);
                                    lookupTableValue = SyntaxFactory.ConditionalExpression(
                                        SyntaxFactory.ParenthesizedExpression(
                                            SyntaxFactory.BinaryExpression(
                                                SyntaxKind.LogicalAndExpression,
                                                Syntax.OptionalIsDefined(recursiveField.NameAsField),
                                                SyntaxFactory.BinaryExpression(
                                                    SyntaxKind.NotEqualsExpression,
                                                    Syntax.OptionalValue(recursiveField.NameAsField),
                                                    Syntax.ThisDot(recursiveField.NameAsProperty)))),
                                        SyntaxFactory.DefaultExpression(Syntax.OptionalOf(this.lookupTableType)),
                                        Syntax.OptionalFor(Syntax.ThisDot(LookupTableFieldName)));
                                }
                            }

                            var alteredInvocation = currentCreationInvocation.AddArgumentListArguments(
                                SyntaxFactory.Argument(SyntaxFactory.NameColon(LookupTableFieldName), NoneToken, lookupTableValue));
                            trackedTree = trackedTree.ReplaceNode(currentInvocation, alteredInvocation);
                        }
                        else
                        {
                            var alteredInvocation = currentChainedInvocation.AddArgumentListArguments(
                                SyntaxFactory.Argument(SyntaxFactory.NameColon(LookupTableFieldName), NoneToken, lookupTableValue));
                            trackedTree = trackedTree.ReplaceNode(currentInvocation, alteredInvocation);
                        }
                    }

                    applyTo = trackedTree;
                }

                return(applyTo);
            }
Exemple #18
0
            protected MemberDeclarationSyntax CreateReplaceChildMethod()
            {
                var irecursiveParentType = SyntaxFactory.QualifiedName(
                    SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)),
                    SyntaxFactory.GenericName(nameof(IRecursiveParent <IRecursiveType>))
                    .AddTypeArgumentListArguments(this.applyTo.RecursiveType.TypeSyntax));
                var oldSpineParameter          = SyntaxFactory.IdentifierName("oldSpine");
                var newSpineParameter          = SyntaxFactory.IdentifierName("newSpine");
                var newChildrenVar             = SyntaxFactory.IdentifierName("newChildren");
                var newSelfVar                 = SyntaxFactory.IdentifierName("newSelf");
                var lookupTableLazySentinelVar = SyntaxFactory.IdentifierName("lookupTableLazySentinel");
                Func <ExpressionSyntax, InvocationExpressionSyntax> callPeek = receiver =>
                                                                               SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, receiver, SyntaxFactory.IdentifierName(nameof(ImmutableStack <int> .Peek))),
                    SyntaxFactory.ArgumentList());
                Func <ExpressionSyntax, InvocationExpressionSyntax> createDeque = stack =>
                                                                                  SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxFactory.QualifiedName(
                            SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)),
                            SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.ImmutableDeque))),
                        SyntaxFactory.IdentifierName(nameof(ImmutableDeque.Create))),
                    SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(stack))));

                return(SyntaxFactory.MethodDeclaration(
                           irecursiveParentType,
                           nameof(IRecursiveParentWithChildReplacement <IRecursiveType> .ReplaceChild))
                       .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(IRecursiveParentWithChildReplacementType))
                       .AddParameterListParameters(
                           SyntaxFactory.Parameter(oldSpineParameter.Identifier).WithType(Syntax.ImmutableStackOf(this.applyTo.RecursiveType.TypeSyntax)),
                           SyntaxFactory.Parameter(newSpineParameter.Identifier).WithType(Syntax.ImmutableStackOf(this.applyTo.RecursiveType.TypeSyntax)))
                       .WithBody(SyntaxFactory.Block(
                                     // var newChildren = this.Children.Replace(oldSpine.Peek(), newSpine.Peek());
                                     SyntaxFactory.LocalDeclarationStatement(
                                         SyntaxFactory.VariableDeclaration(varType)
                                         .AddVariables(SyntaxFactory.VariableDeclarator(newChildrenVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                       SyntaxFactory.InvocationExpression(
                                                                                                                                           SyntaxFactory.MemberAccessExpression(
                                                                                                                                               SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                               Syntax.ThisDot(this.applyTo.RecursiveField.NameAsProperty),
                                                                                                                                               SyntaxFactory.IdentifierName(nameof(CollectionExtensions.Replace))))
                                                                                                                                       .AddArgumentListArguments(
                                                                                                                                           SyntaxFactory.Argument(callPeek(oldSpineParameter)), // oldSpine.Peek()
                                                                                                                                           SyntaxFactory.Argument(callPeek(newSpineParameter))  // newSpine.Peek()
                                                                                                                                           ))))),
                                     // var newSelf = this.With(children: newChildren);
                                     SyntaxFactory.LocalDeclarationStatement(
                                         SyntaxFactory.VariableDeclaration(varType)
                                         .AddVariables(SyntaxFactory.VariableDeclarator(newSelfVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                   SyntaxFactory.InvocationExpression(Syntax.ThisDot(WithMethodName))
                                                                                                                                   .AddArgumentListArguments(
                                                                                                                                       SyntaxFactory.Argument(SyntaxFactory.NameColon(this.applyTo.RecursiveField.NameAsField), NoneToken, newChildrenVar)))))),
                                     // var lookupTableLazySentinel = RecursiveTypeExtensions.LookupTable<TRecursiveType, TRecursiveParent>.LazySentinel;
                                     SyntaxFactory.LocalDeclarationStatement(
                                         SyntaxFactory.VariableDeclaration(varType)
                                         .AddVariables(SyntaxFactory.VariableDeclarator(lookupTableLazySentinelVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause(
                                                                                                                                                   GetLookupTableHelperMember(nameof(LookupTableHelper.LazySentinel)))))),
                                     // if (newSelf.lookupTable == lookupTableLazySentinel && this.lookupTable != null && this.lookupTable != lookupTableLazySentinel) {
                                     SyntaxFactory.IfStatement(
                                         new ExpressionSyntax[] {
                    // newSelf.lookupTable == lookupTableLazySentinel
                    SyntaxFactory.BinaryExpression(
                        SyntaxKind.EqualsExpression,
                        SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, newSelfVar, LookupTableFieldName),
                        lookupTableLazySentinelVar),
                    // this.lookupTable != null
                    SyntaxFactory.BinaryExpression(
                        SyntaxKind.NotEqualsExpression,
                        Syntax.ThisDot(LookupTableFieldName),
                        SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)),
                    // this.lookupTable != lookupTableLazySentinel
                    SyntaxFactory.BinaryExpression(
                        SyntaxKind.NotEqualsExpression,
                        Syntax.ThisDot(LookupTableFieldName),
                        lookupTableLazySentinelVar)
                }.ChainBinaryExpressions(SyntaxKind.LogicalAndExpression),
                                         SyntaxFactory.Block(
                                             // // Our newly mutated self wants a lookup table. If we already have one we can use it,
                                             // // but it needs to be fixed up given the newly rewritten spine through our descendents.
                                             // newSelf.lookupTable = RecursiveTypeExtensions.LookupTable<TRecursiveType, TRecursiveParent>.Fixup(this, ImmutableDeque.Create(newSpine), ImmutableDeque.Create(oldSpine));
                                             SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
                                                                                   SyntaxKind.SimpleAssignmentExpression,
                                                                                   SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, newSelfVar, LookupTableFieldName),
                                                                                   SyntaxFactory.InvocationExpression(
                                                                                       GetLookupTableHelperMember(nameof(LookupTableHelper.Fixup)))
                                                                                   .AddArgumentListArguments(
                                                                                       SyntaxFactory.Argument(SyntaxFactory.ThisExpression()),
                                                                                       SyntaxFactory.Argument(createDeque(newSpineParameter)),
                                                                                       SyntaxFactory.Argument(createDeque(oldSpineParameter))))),
                                             // RecursiveTypeExtensions.LookupTable<TRecursiveType, TRecursiveParent>.ValidateInternalIntegrityDebugOnly(newSelf);
                                             SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(
                                                                                   GetLookupTableHelperMember(nameof(LookupTableHelper.ValidateInternalIntegrityDebugOnly)))
                                                                               .AddArgumentListArguments(SyntaxFactory.Argument(newSelfVar))))),
                                     // return newSelf;
                                     SyntaxFactory.ReturnStatement(newSelfVar))));
            }
            protected MethodDeclarationSyntax CreateToImmutableMethod()
            {
                // var fieldName = this.fieldName.IsDefined ? this.fieldName.Value?.ToImmutable() : this.immutable.FieldName;
                var body = SyntaxFactory.Block(
                    from field in this.generator.applyToMetaType.AllFields
                    where field.IsGeneratedImmutableType
                    let thisField = Syntax.ThisDot(field.NameAsField)                                                                                                                                                               // this.fieldName
                                    let thisFieldValue = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, thisField, SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.Optional <int> .Value))) // this.fieldName.Value
                                                         select SyntaxFactory.LocalDeclarationStatement(
                        SyntaxFactory.VariableDeclaration(varType))
                                                         .AddDeclarationVariables(
                        SyntaxFactory.VariableDeclarator(field.Name).WithInitializer(
                            SyntaxFactory.EqualsValueClause(
                                SyntaxFactory.ConditionalExpression(
                                    Syntax.OptionalIsDefined(thisField),    // this.fieldName.IsDefined
                                    SyntaxFactory.InvocationExpression(     // this.fieldName.Value?.ToImmutable()
                                        SyntaxFactory.ConditionalAccessExpression(thisFieldValue, SyntaxFactory.MemberBindingExpression(ToImmutableMethodName)),
                                        SyntaxFactory.ArgumentList()),
                                    SyntaxFactory.MemberAccessExpression(     // this.immutable.FieldName
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        Syntax.ThisDot(ImmutableFieldName),
                                        field.NameAsProperty))))));

                ExpressionSyntax returnExpression;

                if (this.generator.applyToMetaType.AllFields.Any())
                {
                    // this.immutable = this.immutable.With(...)
                    returnExpression = SyntaxFactory.AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        Syntax.ThisDot(ImmutableFieldName),
                        SyntaxFactory.InvocationExpression(
                            SyntaxFactory.MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                Syntax.ThisDot(ImmutableFieldName),
                                WithMethodName),
                            SyntaxFactory.ArgumentList(
                                Syntax.JoinSyntaxNodes(
                                    SyntaxKind.CommaToken,
                                    this.generator.applyToMetaType.AllFields.Select(
                                        f => SyntaxFactory.Argument(Syntax.OptionalFor(f.IsGeneratedImmutableType ? SyntaxFactory.IdentifierName(f.Name) : Syntax.ThisDot(SyntaxFactory.IdentifierName(f.Name.ToPascalCase())))))))));
                }
                else
                {
                    // this.immutable
                    returnExpression = Syntax.ThisDot(ImmutableFieldName);
                }

                body = body.AddStatements(
                    SyntaxFactory.ReturnStatement(returnExpression));

                // public TemplateType ToImmutable() { ... }
                var method = SyntaxFactory.MethodDeclaration(
                    SyntaxFactory.IdentifierName(this.generator.applyTo.Identifier),
                    ToImmutableMethodName.Identifier)
                             .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                             .AddAttributeLists(PureAttributeList)
                             .WithBody(body);

                if (this.generator.applyToMetaType.HasAncestor)
                {
                    method = Syntax.AddNewKeyword(method);
                }

                return(method);
            }
Exemple #20
0
            private void ImplementRecursiveParentInterface()
            {
                var irecursiveParentOfT = CreateIRecursiveParentOfTSyntax(GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveType.TypeSymbol));

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

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

                // System.Collections.Generic.IReadOnlyCollection<IRecursiveType> IRecursiveParent.Children
                this.innerMembers.Add(
                    SyntaxFactory.PropertyDeclaration(
                        Syntax.GetTypeSyntax(typeof(IReadOnlyCollection <IRecursiveType>)),
                        nameof(IRecursiveParent.Children))
                    .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent))))
                    .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(thisDotChildren))
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                    .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));

                // 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.IReadOnlyCollection<<#= templateType.RecursiveType.TypeName #>> IRecursiveParent<<#= templateType.RecursiveType.TypeName #>>.Children
                ////	=> return this.Children;
                this.innerMembers.Add(
                    SyntaxFactory.PropertyDeclaration(
                        Syntax.IReadOnlyCollectionOf(this.generator.applyToMetaType.RecursiveType.TypeSyntax),
                        nameof(IRecursiveParent <IRecursiveType> .Children))
                    .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(irecursiveParentOfT))
                    .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(thisDotChildren))
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
                    .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute))));
            }