public static SyntaxNode IntroduceFieldFromConstructorAsync(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter) { var oldClass = constructorStatement.FirstAncestorOrSelf <ClassDeclarationSyntax>(); var newClass = oldClass; var fieldMembers = oldClass.Members.OfType <FieldDeclarationSyntax>(); var fieldName = parameter.Identifier.ValueText; if (!fieldMembers.Any(p => p.Declaration.Variables.First().Identifier.Text == fieldName && p.Declaration.Type.ToString() == parameter.Type.ToString())) { var identifierPostFix = 0; while (fieldMembers.Any(p => p.Declaration.Variables.Any(d => d.Identifier.Text == fieldName))) { fieldName = parameter.Identifier.ValueText + ++identifierPostFix; } var newField = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(parameter.Type) .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName))))) .WithModifiers(SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) })) .WithAdditionalAnnotations(Formatter.Annotation); newClass = newClass.WithMembers(newClass.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation); } var assignmentField = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(fieldName)), SyntaxFactory.IdentifierName(parameter.Identifier.ValueText))); var newConstructor = constructorStatement.WithBody(constructorStatement.Body.AddStatements(assignmentField)); newClass = newClass.ReplaceNode(newClass.DescendantNodes().OfType <ConstructorDeclarationSyntax>().First(), newConstructor); var newRoot = root.ReplaceNode(oldClass, newClass); return(newRoot); }
public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) { var containingTypeSyntax = node.FirstAncestorOrSelf <TypeDeclarationSyntax>(); var methodSymbol = this.SemanticModel.GetDeclaredSymbol(node); this.ProcessMethodDecl(node, containingTypeSyntax, methodSymbol); base.VisitConstructorDeclaration(node); }
public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken) { SyntaxNode root = (SyntaxNode)document.GetSyntaxRoot(cancellationToken); SyntaxToken token = root.FindToken(textSpan.Start, findInsideTrivia: true); // Verify is the selected token an identifier if (token.Kind == SyntaxKind.IdentifierToken && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End) { ISemanticModel model = document.GetSemanticModel(cancellationToken); CommonSyntaxNode parentNode = token.Parent; // Verify that the selected node is an identifier of constructor if (!(parentNode is ConstructorDeclarationSyntax)) { return(null); } ConstructorDeclarationSyntax ctorDeclaration = (ConstructorDeclarationSyntax)parentNode; if (ctorDeclaration.HasDiagnostics) { return(null); } // This refactoring does not apply to static constructors if (ctorDeclaration.Modifiers.Any(m => m.Kind == SyntaxKind.StaticKeyword)) { return(null); } // Get the containing type ClassDeclarationSyntax typeDeclaration = ctorDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>(); if (typeDeclaration == null) { return(null); } return(new CodeRefactoring( new[] { new ReplaceConstructorWithFactoryMethodAction(document, ctorDeclaration, typeDeclaration) }, token.Span)); } return(null); }
private async Task <ConstructorDeclarationSyntax> DocumentConstructorAsync(CodeFixContext context, ConstructorDeclarationSyntax constructor, CancellationToken cancellationToken) { if (constructor == null) { return(null); } SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); INamedTypeSymbol apiCallClass = semanticModel.GetDeclaredSymbol(constructor.FirstAncestorOrSelf <ClassDeclarationSyntax>(), cancellationToken); string parameterName = constructor.ParameterList.Parameters[0].Identifier.ValueText; DocumentationCommentTriviaSyntax documentationComment = XmlSyntaxFactory.DocumentationComment( XmlSyntaxFactory.SummaryElement( XmlSyntaxFactory.Text("Initializes a new instance of the "), XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName(apiCallClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)))), XmlSyntaxFactory.Text(" class"), XmlSyntaxFactory.NewLine(), XmlSyntaxFactory.Text("with the behavior provided by another "), XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::OpenStack.Net.IHttpApiCall<T>"))), XmlSyntaxFactory.Text(" instance.")), XmlSyntaxFactory.NewLine(), XmlSyntaxFactory.ParamElement( parameterName, XmlSyntaxFactory.List( XmlSyntaxFactory.Text("The "), XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::OpenStack.Net.IHttpApiCall<T>"))), XmlSyntaxFactory.Text(" providing the behavior for the API call."))), XmlSyntaxFactory.NewLine(), XmlSyntaxFactory.ExceptionElement( SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::System.ArgumentNullException")), XmlSyntaxFactory.List( XmlSyntaxFactory.Text("If "), XmlSyntaxFactory.ParamRefElement(parameterName), XmlSyntaxFactory.Text(" is "), XmlSyntaxFactory.NullKeywordElement(), XmlSyntaxFactory.Text(".")))) .WithAdditionalAnnotations(Simplifier.Annotation); SyntaxTrivia documentationTrivia = SyntaxFactory.Trivia(documentationComment); return(constructor.WithLeadingTrivia(constructor.GetLeadingTrivia().Add(documentationTrivia))); }
public static SyntaxNode IntroduceFieldFromConstructor(SyntaxNode root, ConstructorDeclarationSyntax constructorStatement, ParameterSyntax parameter) { // There are no constructors in interfaces, therefore all types remaining type (class and struct) are fine. var oldType = constructorStatement.FirstAncestorOrSelf <TypeDeclarationSyntax>(); var newType = oldType; var fieldName = parameter.Identifier.ValueText; var fieldType = parameter.Type; var members = ExtractMembersFromClass(oldType.Members); var addMember = false; if (!members.Any(p => p.Key == fieldName && p.Value == fieldType.ToString())) { var identifierPostFix = 0; while (members.Any(p => p.Key == fieldName)) { fieldName = parameter.Identifier.ValueText + ++identifierPostFix; } addMember = true; } var assignmentField = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(fieldName)), SyntaxFactory.IdentifierName(parameter.Identifier.ValueText))); var newConstructor = constructorStatement.WithBody(constructorStatement.Body.AddStatements(assignmentField)); newType = newType.ReplaceNode(constructorStatement, newConstructor); if (addMember) { var newField = SyntaxFactory.FieldDeclaration(SyntaxFactory.VariableDeclaration(parameter.Type) .WithVariables(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName))))) .WithModifiers(SyntaxFactory.TokenList(new[] { SyntaxFactory.Token(SyntaxKind.PrivateKeyword), SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) })) .WithAdditionalAnnotations(Formatter.Annotation); newType = newType.WithMembers(newType.Members.Insert(0, newField)).WithoutAnnotations(Formatter.Annotation); } var newRoot = root.ReplaceNode(oldType, newType); return(newRoot); }