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()); } }
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)))); }