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