internal static NameSyntax GetTypeSyntax(Type type) { Requires.NotNull(type, nameof(type)); SimpleNameSyntax leafType = SyntaxFactory.IdentifierName(type.IsGenericType ? type.Name.Substring(0, type.Name.IndexOf('`')) : type.Name); if (type.IsGenericType) { leafType = SyntaxFactory.GenericName( ((IdentifierNameSyntax)leafType).Identifier, SyntaxFactory.TypeArgumentList(Syntax.JoinSyntaxNodes <TypeSyntax>(SyntaxKind.CommaToken, type.GenericTypeArguments.Select(GetTypeSyntax)))); } if (type.Namespace != null) { NameSyntax namespaceName = null; foreach (string segment in type.Namespace.Split('.')) { var segmentName = SyntaxFactory.IdentifierName(segment); namespaceName = namespaceName == null ? (NameSyntax)segmentName : SyntaxFactory.QualifiedName(namespaceName, SyntaxFactory.IdentifierName(segment)); } return(SyntaxFactory.QualifiedName(namespaceName, leafType)); } return(leafType); }
protected TypeSyntax GetLookupTableHelperType() { // ImmutableObjectGraph.RecursiveTypeExtensions.LookupTable<TRecursiveType, TRecursiveParent> return(SyntaxFactory.QualifiedName( SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)), SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.RecursiveTypeExtensions))), SyntaxFactory.GenericName( SyntaxFactory.Identifier(nameof(RecursiveTypeExtensions.LookupTable <IRecursiveType, IRecursiveParentWithLookupTable <IRecursiveType> >)), SyntaxFactory.TypeArgumentList(Syntax.JoinSyntaxNodes <TypeSyntax>( SyntaxKind.CommaToken, this.applyTo.RecursiveType.TypeSyntax, this.applyTo.RecursiveParent.TypeSyntax))))); }
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 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)))); }
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))); 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 { get; } this.innerMembers.Add( SyntaxFactory.PropertyDeclaration(inefficiencyLoadType, nameof(IRecursiveParentWithLookupTable <IRecursiveType> .InefficiencyLoad)) .WithExplicitInterfaceSpecifier(explicitImplementation) .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block(SyntaxFactory.ReturnStatement(Syntax.ThisDot(InefficiencyLoadFieldName)))))); // IReadOnlyCollection<TRecursiveType> IRecursiveParentWithLookupTable<TRecursiveType>.Children { get; } this.innerMembers.Add( SyntaxFactory.PropertyDeclaration( Syntax.IReadOnlyCollectionOf(this.applyTo.RecursiveType.TypeSyntax), nameof(IRecursiveParentWithLookupTable <IRecursiveType> .Children)) .WithExplicitInterfaceSpecifier(explicitImplementation) .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block(SyntaxFactory.ReturnStatement(Syntax.ThisDot(this.applyTo.RecursiveField.NameAsProperty)))))); // ImmutableDictionary<IdentityFieldType, KeyValuePair<TRecursiveType, IdentityFieldType>> IRecursiveParentWithLookupTable<TRecursiveType>.LookupTable { get; } this.innerMembers.Add( SyntaxFactory.PropertyDeclaration( this.lookupTableType, nameof(IRecursiveParentWithLookupTable <IRecursiveType> .LookupTable)) .WithExplicitInterfaceSpecifier(explicitImplementation) .AddAccessorListAccessors(SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block(SyntaxFactory.ReturnStatement(Syntax.ThisDot(LookupTablePropertyName)))))); } 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))); // public System.Collections.Immutable.ImmutableStack<TRecursiveType> GetSpine(TRecursiveType descendent) { // return this.GetSpine<TRecursiveParent, TRecursiveType>(descendent); // } var descendentParameter = SyntaxFactory.IdentifierName("descendent"); this.innerMembers.Add( SyntaxFactory.MethodDeclaration(Syntax.ImmutableStackOf(this.applyTo.RecursiveType.TypeSyntax), GetSpineMethodName.Identifier) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters(SyntaxFactory.Parameter(descendentParameter.Identifier).WithType(this.applyTo.RecursiveType.TypeSyntax)) .WithBody(SyntaxFactory.Block( SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( Syntax.ThisDot( SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetSpine)) .AddTypeArgumentListArguments(this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax)), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(descendentParameter)))))))); // public System.Collections.Immutable.ImmutableStack<TRecursiveType> GetSpine(uint identity) { // return this.GetSpine<TRecursiveParent, TRecursiveType>(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)) .WithBody(SyntaxFactory.Block( SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( Syntax.ThisDot( SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetSpine)) .AddTypeArgumentListArguments(this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax)), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(identityParameter)))))))); this.innerMembers.Add(this.CreateFindMethod()); } }
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)) .WithBody(body); if (this.generator.applyToMetaType.HasAncestor) { method = Syntax.AddNewKeyword(method); } return(method); }
private void ImplementSortedChildrenInterface() { this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveParentWithSortedChildren)))); // int IRecursiveParentWithSortedChildren.Compare(IRecursiveType first, IRecursiveType second) var firstParameterName = SyntaxFactory.IdentifierName("first"); var secondParameterName = SyntaxFactory.IdentifierName("second"); this.innerMembers.Add(SyntaxFactory.MethodDeclaration( SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)), nameof(IRecursiveParentWithSortedChildren.Compare)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithSortedChildren)))) .AddParameterListParameters( SyntaxFactory.Parameter(firstParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType))), SyntaxFactory.Parameter(secondParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType)))) .WithBody(SyntaxFactory.Block( // return this.Children.KeyComparer.Compare((<#= templateType.RecursiveType.TypeName #>)first, (<#= templateType.RecursiveType.TypeName #>)second); SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())), SyntaxFactory.IdentifierName(nameof(ImmutableSortedSet <int> .KeyComparer))), SyntaxFactory.IdentifierName(nameof(IComparer <int> .Compare))), SyntaxFactory.ArgumentList(Syntax.JoinSyntaxNodes(SyntaxKind.CommaToken, SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, firstParameterName)), SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, secondParameterName))))))))); }