public static async Task ComputeRefactoringAsync( RefactoringContext context, PropertyDeclarationSyntax property) { AccessorDeclarationSyntax setter = property.Setter(); if (setter == null) { return; } if (setter.IsKind(SyntaxKind.InitAccessorDeclaration)) { return; } ExpressionSyntax expression = GetExpression(); if (expression == null) { return; } SimpleAssignmentExpressionInfo simpleAssignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!simpleAssignment.Success) { return; } if (!simpleAssignment.Left.IsKind(SyntaxKind.IdentifierName)) { return; } if (!(simpleAssignment.Right is IdentifierNameSyntax identifierName)) { return; } if (identifierName.Identifier.ValueText != "value") { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); INamedTypeSymbol containingType = semanticModel .GetDeclaredSymbol(property, context.CancellationToken)? .ContainingType; if (containingType == null) { return; } if (!containingType.Implements(MetadataNames.System_ComponentModel_INotifyPropertyChanged, allInterfaces: true)) { return; } IMethodSymbol methodSymbol = SymbolUtility.FindMethodThatRaisePropertyChanged(containingType, expression.SpanStart, semanticModel); if (methodSymbol == null) { return; } Document document = context.Document; context.RegisterRefactoring( "Notify when property change", ct => RefactorAsync(document, property, methodSymbol.Name, ct), RefactoringIdentifiers.NotifyWhenPropertyChange); ExpressionSyntax GetExpression() { BlockSyntax body = setter.Body; if (body != null) { if (body.Statements.SingleOrDefault(shouldThrow: false) is ExpressionStatementSyntax expressionStatement) { return(expressionStatement.Expression); } } else { return(setter.ExpressionBody?.Expression); } return(null); } }
internal static bool IsFixable( IndexerDeclarationSyntax indexerDeclaration, AccessorDeclarationSyntax accessor, SemanticModel semanticModel, CancellationToken cancellationToken) { switch (accessor.Kind()) { case SyntaxKind.GetAccessorDeclaration: { ExpressionSyntax expression = GetGetAccessorExpression(accessor); if (!(expression is ElementAccessExpressionSyntax elementAccess)) { return(false); } if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (elementAccess.ArgumentList == null) { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) && CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) && CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters)); } case SyntaxKind.SetAccessorDeclaration: { ExpressionSyntax expression = GetSetAccessorExpression(accessor); SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!assignment.Success) { return(false); } if (assignment.Left.Kind() != SyntaxKind.ElementAccessExpression) { return(false); } var elementAccess = (ElementAccessExpressionSyntax)assignment.Left; if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (elementAccess.ArgumentList == null) { return(false); } if (assignment.Right.Kind() != SyntaxKind.IdentifierName) { return(false); } var identifierName = (IdentifierNameSyntax)assignment.Right; if (identifierName.Identifier.ValueText != "value") { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) && CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) && CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters)); } case SyntaxKind.UnknownAccessorDeclaration: { return(false); } default: { Debug.Fail(accessor.Kind().ToString()); return(false); } } }
private static void AnalyzeSimpleAssignment(SyntaxNodeAnalysisContext context) { var assignmentExpression = (AssignmentExpressionSyntax)context.Node; SimpleAssignmentExpressionInfo assignmentInfo = SyntaxInfo.SimpleAssignmentExpressionInfo(assignmentExpression); if (!assignmentInfo.Success) { return; } if (assignmentExpression.IsParentKind(SyntaxKind.ObjectInitializerExpression)) { return; } ExpressionSyntax right = assignmentInfo.Right; if (!CanBeReplacedWithCompoundAssignment(right.Kind())) { return; } BinaryExpressionInfo binaryInfo = SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)right); if (!binaryInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(assignmentInfo.Left, binaryInfo.Left)) { return; } var binaryExpression = (BinaryExpressionSyntax)right; DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCompoundAssignment, assignmentExpression, GetCompoundAssignmentOperatorText(binaryExpression)); DiagnosticHelpers.ReportNode(context, DiagnosticDescriptors.UseCompoundAssignmentFadeOut, binaryExpression.Left); bool CanBeReplacedWithCompoundAssignment(SyntaxKind kind) { switch (kind) { case SyntaxKind.AddExpression: case SyntaxKind.SubtractExpression: case SyntaxKind.MultiplyExpression: case SyntaxKind.DivideExpression: case SyntaxKind.ModuloExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.LeftShiftExpression: case SyntaxKind.RightShiftExpression: return(true); case SyntaxKind.CoalesceExpression: return(((CSharpCompilation)context.Compilation).LanguageVersion >= LanguageVersion.CSharp8); default: return(false); } } }
internal static bool IsFixable( PropertyDeclarationSyntax propertyDeclaration, AccessorDeclarationSyntax accessor, SemanticModel semanticModel, CancellationToken cancellationToken) { switch (accessor.Kind()) { case SyntaxKind.GetAccessorDeclaration: { ExpressionSyntax expression = GetGetAccessorExpression(accessor); if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true) { return(false); } var memberAccess = (MemberAccessExpressionSyntax)expression; if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } SimpleNameSyntax simpleName = memberAccess.Name; IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol)); } case SyntaxKind.SetAccessorDeclaration: { ExpressionSyntax expression = GetSetAccessorExpression(accessor); SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!assignment.Success) { return(false); } if (assignment.Left.Kind() != SyntaxKind.SimpleMemberAccessExpression) { return(false); } var memberAccess = (MemberAccessExpressionSyntax)assignment.Left; if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (assignment.Right.Kind() != SyntaxKind.IdentifierName) { return(false); } var identifierName = (IdentifierNameSyntax)assignment.Right; if (identifierName.Identifier.ValueText != "value") { return(false); } SimpleNameSyntax simpleName = memberAccess.Name; if (simpleName == null) { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol)); } case SyntaxKind.UnknownAccessorDeclaration: { return(false); } default: { Debug.Fail(accessor.Kind().ToString()); return(false); } } }
public override bool IsFixableStatement( StatementSyntax statement, string name, ITypeSymbol typeSymbol, SemanticModel semanticModel, CancellationToken cancellationToken) { if (statement.SpanOrLeadingTriviaContainsDirectives()) { return(false); } if (!(statement is ExpressionStatementSyntax expressionStatement)) { return(false); } SimpleAssignmentExpressionInfo assignmentInfo = SyntaxInfo.SimpleAssignmentExpressionInfo(expressionStatement.Expression); if (!assignmentInfo.Success) { return(false); } if (name != (assignmentInfo.Left as IdentifierNameSyntax)?.Identifier.ValueText) { return(false); } SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(assignmentInfo.Right); if (!invocationInfo.Success) { return(false); } if (!(WalkDownMethodChain(invocationInfo).Expression is IdentifierNameSyntax identifierName)) { return(false); } if (name != identifierName.Identifier.ValueText) { return(false); } IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocationInfo.InvocationExpression, cancellationToken); if (methodSymbol == null) { return(false); } if (!SymbolEqualityComparer.Default.Equals(methodSymbol.ReturnType, typeSymbol)) { return(false); } if (IsReferenced(invocationInfo.InvocationExpression, identifierName, name, semanticModel, cancellationToken)) { return(false); } return(true); }