public static bool IsEnumerableValueType(this FieldDeclarationSyntax fieldDeclarationSyntax, SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out ITypeSymbol?typeSymbol)
        {
            typeSymbol = context.SemanticModel.GetTypeInfo(fieldDeclarationSyntax.Declaration.Type).Type;
            if (typeSymbol is null)
            {
                return(false);
            }

            if (typeSymbol.TypeKind == TypeKind.TypeParameter)
            {
                var typeDeclaration = fieldDeclarationSyntax.Ancestors().OfType <TypeDeclarationSyntax>().FirstOrDefault();
                if (typeDeclaration is null)
                {
                    return(false);
                }

                var typeName          = typeSymbol.Name;
                var constraintClauses = typeDeclaration.ConstraintClauses.FirstOrDefault(node => node.Name.Identifier.ValueText == typeName);
                if (constraintClauses is null || !constraintClauses.Constraints.Any(constraint => constraint.IsEnumerator(context)))
                {
                    return(false);
                }
            }
            else
            {
                if (!typeSymbol.IsValueType ||
                    !(typeSymbol.IsEnumerator(context.Compilation, out _) ||
                      typeSymbol.IsAsyncEnumerator(context.Compilation, out _)))
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #2
0
        private static async Task <Document> InitializeFromConstructor(Document document, FieldDeclarationSyntax fieldDeclaration, VariableDeclaratorSyntax fieldVariable, bool alwaysCreateNew, CancellationToken cancellationToken)
        {
            var classDeclaration = fieldDeclaration.Ancestors().OfType <ClassDeclarationSyntax>().Single();

            var parameterType   = fieldDeclaration.Declaration.Type.ToString();
            var identifierToken = fieldVariable.Identifier;
            var parameterName   = identifierToken.Text.TrimStart('_');

            // create the new parameter
            var parameter = Parameter(
                Identifier(parameterName))
                            .WithType(IdentifierName(parameterType)
                                      );

            // create the new assignment to add to the constructor body
            var assignment = ExpressionStatement(
                AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                     MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(identifierToken)),
                                     IdentifierName(parameterName)));

            // get the syntax root
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // get existing constructor if any
            var existingConstructors = GetConstructors(fieldVariable);

            // update the class by either updating the constructor, or adding one
            SyntaxNode updatedClassDecl = classDeclaration;

            if (!existingConstructors.Any() || alwaysCreateNew)
            {
                var constructor = ConstructorDeclaration(classDeclaration.Identifier.Text)
                                  .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                                  .WithParameterList(ParameterList(
                                                         SingletonSeparatedList(parameter)
                                                         ))
                                  .WithBody(Block(assignment))
                                  .WithLeadingTrivia(fieldVariable.GetLeadingTrivia().Insert(0, CarriageReturnLineFeed));

                var insertionPoint = (SyntaxNode)existingConstructors.LastOrDefault() ?? fieldDeclaration;

                updatedClassDecl = classDeclaration.InsertNodesAfter(insertionPoint, new[] { constructor });
            }
            else
            {
                updatedClassDecl = classDeclaration.ReplaceNodes(existingConstructors,
                                                                 (constructor, updatedConstructor) => UpdateConstructor(constructor, parameter, assignment));
            }

            // replace the root node with the updated class
            var newRoot = root.ReplaceNode(classDeclaration, updatedClassDecl);

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #3
0
        private async Task <Document> InjectDependencyAsync(Document document, FieldDeclarationSyntax fieldDeclaration, CancellationToken cancellationToken)
        {
            var editor = await DocumentEditor.CreateAsync(document, cancellationToken);

            var fieldIdentifier = fieldDeclaration.Declaration.Variables.First().Identifier;

            var parameter = SyntaxFactory
                            .Parameter(SyntaxFactory.Identifier(fieldIdentifier.Text.Substring(1, fieldIdentifier.Text.Length - 1)))
                            .WithType(fieldDeclaration.Declaration.Type);

            var left  = SyntaxFactory.IdentifierName(fieldIdentifier);
            var right = SyntaxFactory.IdentifierName(parameter.Identifier);

            var assignment =
                SyntaxFactory.ExpressionStatement(
                    SyntaxFactory.AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        left,
                        right));

            var classDeclaration = fieldDeclaration.Ancestors().First(x => x is ClassDeclarationSyntax) as ClassDeclarationSyntax;

            var constructor = classDeclaration.DescendantNodes().FirstOrDefault(x => x is ConstructorDeclarationSyntax) as ConstructorDeclarationSyntax;

            if (constructor is null)
            {
                constructor = SyntaxFactory
                              .ConstructorDeclaration(classDeclaration.Identifier.Text)
                              .WithoutTrivia()
                              .AddBodyStatements(assignment)
                              .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                              .AddParameterListParameters(parameter);

                var newClass = classDeclaration.AddMembers(constructor);
                editor.ReplaceNode(classDeclaration, newClass);
            }
            else
            {
                var newConstructor =
                    constructor.AddBodyStatements(assignment)
                    .AddParameterListParameters(parameter)
                    .WithAdditionalAnnotations(Formatter.Annotation);
                editor.ReplaceNode(constructor, newConstructor);
            }

            return(editor.GetChangedDocument());
        }