Пример #1
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))));
            }
Пример #2
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());
                }
            }