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