private static void RemoveExpression(DocumentEditor editor, ArgumentSyntax argument, IMethodSymbol invoker, bool usesUnderscoreNames, CancellationToken cancellationToken) { var invocation = argument.FirstAncestorOrSelf <InvocationExpressionSyntax>(); if (PropertyChanged.TryGetInvokedPropertyChangedName(invocation, editor.SemanticModel, cancellationToken, out var name) == AnalysisResult.Yes) { var property = editor.SemanticModel.GetDeclaredSymbolSafe(argument.FirstAncestorOrSelf <PropertyDeclarationSyntax>(), cancellationToken); if (property?.Name == name) { editor.ReplaceNode( invocation, SyntaxFactory.ParseExpression(Snippet.OnPropertyChanged(invoker, property?.Name, usesUnderscoreNames).TrimEnd(';')) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); } else { editor.ReplaceNode( invocation, SyntaxFactory.ParseExpression(Snippet.OnOtherPropertyChanged(invoker, name, usesUnderscoreNames).TrimEnd(';')) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); } } }
private static void MakeAutoPropertyNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken) { if (Property.IsMutableAutoProperty(propertyDeclaration, out var getter, out var setter)) { if (getter.Body != null || getter.ContainsSkippedText || setter.Body != null || setter.ContainsSkippedText) { return; } var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var backingField = editor.AddBackingField(propertyDeclaration, underscoreFields, cancellationToken); var fieldAccess = underscoreFields ? backingField.Name() : $"this.{backingField.Name()}"; var code = StringBuilderPool.Borrow() .AppendLine($"public Type PropertyName") .AppendLine("{") .AppendLine($" get => {fieldAccess};") .AppendLine() .AppendLine(" set") .AppendLine(" {") .AppendLine($" if ({Snippet.EqualityCheck(property.Type, "value", fieldAccess, semanticModel)})") .AppendLine(" {") .AppendLine($" return;") .AppendLine(" }") .AppendLine() .AppendLine($" {fieldAccess} = value;") .AppendLine($" {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}") .AppendLine(" }") .AppendLine("}") .Return(); var template = ParseProperty(code); editor.ReplaceNode( getter, x => x.WithExpressionBody(template.Getter().ExpressionBody) .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation)); editor.ReplaceNode( setter, x => x.WithBody(template.Setter().Body) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None)) .WithAdditionalAnnotations(Formatter.Annotation)); if (propertyDeclaration.Initializer != null) { editor.ReplaceNode( propertyDeclaration, x => x.WithoutInitializer()); } editor.ReplaceNode(propertyDeclaration, x => x.WithAdditionalAnnotations(Formatter.Annotation)); } }
private static void MakeWithBackingFieldNotify(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken) { var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>(); if (classDeclaration == null) { return; } if (IsSimpleAssignmentOnly(propertyDeclaration, out var setter, out var statement, out var assignment, out _)) { var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var notifyStatement = SyntaxFactory .ParseStatement(Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)) .WithLeadingTrivia(SyntaxFactory.ElasticMarker) .WithTrailingTrivia(SyntaxFactory.ElasticMarker) .WithSimplifiedNames() .WithAdditionalAnnotations(Formatter.Annotation); if (setter.ExpressionBody != null) { editor.ReplaceNode( setter, (x, _) => { var old = (AccessorDeclarationSyntax)x; return(old.WithBody( SyntaxFactory.Block( SyntaxFactory.ExpressionStatement(assignment), notifyStatement)) .WithExpressionBody(null) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))); }); editor.FormatNode(propertyDeclaration); } else if (setter.Body != null) { editor.InsertAfter(statement, notifyStatement); editor.FormatNode(propertyDeclaration); } } }
private static void MakeNotify(DocumentEditor editor, ExpressionSyntax assignment, string propertyName, IMethodSymbol invoker, bool usesUnderscoreNames) { var snippet = assignment.FirstAncestor <PropertyDeclarationSyntax>() is PropertyDeclarationSyntax propertyDeclaration && propertyDeclaration.Identifier.ValueText == propertyName ? Snippet.OnPropertyChanged(invoker, propertyName, usesUnderscoreNames) : Snippet.OnOtherPropertyChanged(invoker, propertyName, usesUnderscoreNames); var onPropertyChanged = SyntaxFactory.ParseStatement(snippet) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation); if (assignment.Parent is AnonymousFunctionExpressionSyntax anonymousFunction) { if (anonymousFunction.Body is BlockSyntax block) { if (block.Statements.Count > 1) { var previousStatement = InsertAfter(block, block.Statements.Last(), invoker); editor.InsertAfter(previousStatement, new[] { onPropertyChanged }); } return; } var expressionStatement = (ExpressionStatementSyntax)editor.Generator.ExpressionStatement(anonymousFunction.Body); var withStatements = editor.Generator.WithStatements(anonymousFunction, new[] { expressionStatement, onPropertyChanged }); editor.ReplaceNode(anonymousFunction, withStatements); } else if (assignment.Parent is ExpressionStatementSyntax assignStatement && assignStatement.Parent is BlockSyntax assignBlock) { var previousStatement = InsertAfter(assignBlock, assignStatement, invoker); editor.InsertAfter(previousStatement, new[] { onPropertyChanged }); }
private static void MakeWithBackingFieldNotifyWhenValueChanges(DocumentEditor editor, PropertyDeclarationSyntax propertyDeclaration, IMethodSymbol invoker, SemanticModel semanticModel, CancellationToken cancellationToken) { var classDeclaration = propertyDeclaration.FirstAncestorOrSelf <ClassDeclarationSyntax>(); if (classDeclaration == null) { return; } if (propertyDeclaration.TryGetSetter(out var setter)) { if (setter.ExpressionBody != null && IsSimpleAssignmentOnly(propertyDeclaration, out _, out _, out var assignment, out _)) { var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var code = StringBuilderPool.Borrow() .AppendLine($"public Type PropertyName") .AppendLine("{") .AppendLine($" get => {assignment.Left};") .AppendLine() .AppendLine(" set") .AppendLine(" {") .AppendLine($" if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})") .AppendLine(" {") .AppendLine($" return;") .AppendLine(" }") .AppendLine() .AppendLine($" {assignment};") .AppendLine($" {Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)}") .AppendLine(" }") .AppendLine("}") .Return(); var template = ParseProperty(code); editor.ReplaceNode( setter, (x, _) => { var old = (AccessorDeclarationSyntax)x; return(old.WithBody(template.Setter().Body) .WithExpressionBody(null) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))); }); editor.FormatNode(propertyDeclaration); } if (setter.Body?.Statements.Count == 1 && IsSimpleAssignmentOnly(propertyDeclaration, out _, out var statement, out assignment, out _)) { var property = semanticModel.GetDeclaredSymbolSafe(propertyDeclaration, cancellationToken); var code = StringBuilderPool.Borrow() .AppendLine($" if ({Snippet.EqualityCheck(property.Type, "value", assignment.Left.ToString(), semanticModel)})") .AppendLine(" {") .AppendLine($" return;") .AppendLine(" }") .AppendLine() .Return(); var ifStatement = SyntaxFactory.ParseStatement(code) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation); editor.InsertBefore( statement, ifStatement); var underscoreFields = CodeStyle.UnderscoreFields(semanticModel); var notifyStatement = SyntaxFactory .ParseStatement( Snippet.OnPropertyChanged(invoker, property.Name, underscoreFields)) .WithSimplifiedNames() .WithLeadingElasticLineFeed() .WithTrailingElasticLineFeed() .WithAdditionalAnnotations(Formatter.Annotation); editor.InsertAfter(statement, notifyStatement); editor.FormatNode(propertyDeclaration); } } }