public Task <SyntaxList <MemberDeclarationSyntax> > GenerateAsync(TransformationContext context, IProgress <Diagnostic> progress, CancellationToken cancellationToken) { var results = SyntaxFactory.List <MemberDeclarationSyntax>(); // Our generator is applied to any class that our attribute is applied to. var applyToClass = (ClassDeclarationSyntax)context.ProcessingNode; // Apply a suffix to the name of a copy of the class. var partialClass = SyntaxFactory.ClassDeclaration($"{applyToClass.Identifier}") .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword))); var returnType = CodeGenUtil.TypeFromClass(applyToClass); var fields = applyToClass.Members.Where(m => m is FieldDeclarationSyntax) .Select(m => m as FieldDeclarationSyntax) .Where(m => m.Modifiers.Any(SyntaxKind.PublicKeyword)) .Where(m => m.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) .Where(m => !m.Modifiers.Any(SyntaxKind.StaticKeyword)) .ToList(); partialClass = CodeGenUtil.AddWith(partialClass, returnType, fields); return(Task.FromResult <SyntaxList <MemberDeclarationSyntax> >(results.Add(partialClass))); }
public static (ClassDeclarationSyntax PartialClass, TypeSyntax ReturnType, List <FieldDeclarationSyntax> Fields) GetState(TransformationContext context) { // Our generator is applied to any class that our attribute is applied to. var applyToClass = (ClassDeclarationSyntax)context.ProcessingNode; var classModifiers = SyntaxFactory.TokenList( Enumerable.Concat( applyToClass.Modifiers .Where(t => !t.IsKind(SyntaxKind.PartialKeyword)).AsEnumerable(), new[] { SyntaxFactory.Token(SyntaxKind.PartialKeyword) })); // Apply a suffix to the name of a copy of the class. var partialClass = SyntaxFactory.ClassDeclaration($"{applyToClass.Identifier}") .WithModifiers(classModifiers); if (applyToClass.TypeParameterList != null) { partialClass = partialClass.WithTypeParameterList(applyToClass.TypeParameterList); } if (applyToClass.ConstraintClauses != null) { partialClass = partialClass.WithConstraintClauses(applyToClass.ConstraintClauses); } var returnType = CodeGenUtil.TypeFromClass(applyToClass); var fields = applyToClass.Members .Where(m => m is FieldDeclarationSyntax) .Select(m => m as FieldDeclarationSyntax) .Where(f => f.Declaration.Variables.Count > 0) .Where(f => FirstCharIsUpper(f.Declaration.Variables[0].Identifier.ToString())) .Where(f => f.Modifiers.Any(SyntaxKind.PublicKeyword)) .Where(f => f.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) .Where(f => !f.Modifiers.Any(SyntaxKind.StaticKeyword)) .ToList(); return(partialClass, returnType, fields); }
public static (ClassDeclarationSyntax PartialClass, TypeSyntax ReturnType, List <(SyntaxToken Identifier, TypeSyntax Type, SyntaxTokenList Modifiers)> Fields) GetState(TransformationContext context) { // Our generator is applied to any class that our attribute is applied to. var applyToClass = (ClassDeclarationSyntax)context.ProcessingNode; var classModifiers = SyntaxFactory.TokenList( Enumerable.Concat( applyToClass.Modifiers .Where(t => !t.IsKind(SyntaxKind.PartialKeyword)).AsEnumerable(), new[] { SyntaxFactory.Token(SyntaxKind.PartialKeyword) })); // Apply a suffix to the name of a copy of the class. var partialClass = SyntaxFactory.ClassDeclaration($"{applyToClass.Identifier}") .WithModifiers(classModifiers); if (applyToClass.TypeParameterList != null) { partialClass = partialClass.WithTypeParameterList(applyToClass.TypeParameterList); } if (applyToClass.ConstraintClauses != null) { partialClass = partialClass.WithConstraintClauses(applyToClass.ConstraintClauses); } var returnType = CodeGenUtil.TypeFromClass(applyToClass); var indexedMembers = applyToClass.Members.Select((m, i) => (m, i)); var fields = indexedMembers.Where(m => m.m is FieldDeclarationSyntax) .Select(m => (f: m.m as FieldDeclarationSyntax, m.i)) .Where(m => m.f.Declaration.Variables.Count > 0) .Where(m => FirstCharIsUpper(m.f.Declaration.Variables[0].Identifier.ToString())) .Where(m => m.f.Modifiers.Any(SyntaxKind.PublicKeyword)) .Where(m => m.f.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) .Where(m => !m.f.Modifiers.Any(SyntaxKind.StaticKeyword)) .Select(m => ( m.f.Declaration.Variables[0].Identifier, m.f.Declaration.Type, m.f.Modifiers, m.i )); var properties = indexedMembers.Where(m => m.m is PropertyDeclarationSyntax) .Select(m => (p: m.m as PropertyDeclarationSyntax, m.i)) .Where(m => FirstCharIsUpper(m.p.Identifier.ToString())) .Where(m => m.p.Modifiers.Any(SyntaxKind.PublicKeyword)) .Where(m => !m.p.Modifiers.Any(SyntaxKind.StaticKeyword)) .Where(m => m.p.AccessorList.Accessors.Count == 1) .Where(m => m.p.AccessorList.Accessors[0].Kind() == SyntaxKind.GetAccessorDeclaration) .Where(m => m.p.AccessorList.Accessors[0].ExpressionBody == null) .Where(m => m.p.AccessorList.Accessors[0].Body == null) .Where(m => m.p.Initializer == null) .Select(m => ( m.p.Identifier, m.p.Type, m.p.Modifiers, m.i )); var members = fields.Concat(properties) .OrderBy(m => m.i) // Preserve the order between properties and fields. .Select(m => (m.Identifier, m.Type, m.Modifiers)) .ToList(); return(partialClass, returnType, members); }