public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, NullCheckStyles.ComparisonToNull); if (!nullCheck.Success) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel .GetTypeInfo(nullCheck.Expression, context.CancellationToken) .ConvertedType? .SpecialType != SpecialType.System_String) { return; } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrEmpty)) { ReplaceEqualsExpressionWithStringIsNullOrEmptyRefactoring.Instance.RegisterRefactoring(context, nullCheck); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrWhiteSpace)) { ReplaceEqualsExpressionWithStringIsNullOrWhiteSpaceRefactoring.Instance.RegisterRefactoring(context, nullCheck); } }
private static IfRefactoring CreateIfToAssignment( IfStatementSyntax ifStatement, ExpressionSyntax left, ExpressionSyntax expression1, ExpressionSyntax expression2, NullCheckExpressionInfo nullCheck, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { if ((nullCheck.Kind & NullCheckKind.ComparisonToNull) != 0 && SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1)) { return(CreateIfToAssignment(ifStatement, left, expression1, expression2, options, isNullable: false)); } expression1 = GetNullableOfTValueProperty(expression1, semanticModel, cancellationToken); if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1)) { return(CreateIfToAssignment(ifStatement, left, expression1, expression2, options, isNullable: true)); } return(null); }
private static bool NullCheckExists(ExpressionSyntax expression, StatementSyntax statement) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement); if (!statementsInfo.Success) { return(false); } SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(statement); if (index >= statements.Count - 1) { return(false); } StatementSyntax nextStatement = statements[index + 1]; if (!(nextStatement is IfStatementSyntax ifStatement)) { return(false); } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull); if (!nullCheck.Success) { return(false); } return(CSharpFactory.AreEquivalent(expression, nullCheck.Expression)); }
private void RegisterRefactoring(RefactoringContext context, NullCheckExpressionInfo nullCheck) { string title = (nullCheck.Style == NullCheckStyles.EqualsToNull) ? $"Replace '{nullCheck.NullCheckExpression}' with 'string.{MethodName}({nullCheck.Expression})'" : $"Replace '{nullCheck.NullCheckExpression}' with '!string.{MethodName}({nullCheck.Expression})'"; context.RegisterRefactoring( title, cancellationToken => RefactorAsync(context.Document, nullCheck, cancellationToken)); }
private static void Analyze(SyntaxNodeAnalysisContext context, BinaryExpressionSyntax binaryExpression, NullCheckStyles allowedStyles) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, allowedStyles: allowedStyles); if (nullCheck.Success && IsUnconstrainedTypeParameter(context.SemanticModel.GetTypeSymbol(nullCheck.Expression, context.CancellationToken)) && !binaryExpression.SpanContainsDirectives()) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UnconstrainedTypeParameterCheckedForNull, binaryExpression); } }
private static async Task <Document> RemoveUnnecessaryNullCheckAsync( Document document, BinaryExpressionSyntax logicalAnd, CancellationToken cancellationToken) { BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo(logicalAnd); ExpressionSyntax right = binaryExpressionInfo.Right; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpressionInfo.Left, semanticModel, NullCheckStyles.HasValue | NullCheckStyles.NotEqualsToNull); var binaryExpression = right as BinaryExpressionSyntax; ExpressionSyntax newRight; switch (right.Kind()) { case SyntaxKind.SimpleMemberAccessExpression: { newRight = TrueLiteralExpression().WithTriviaFrom(right); break; } case SyntaxKind.LogicalNotExpression: { newRight = FalseLiteralExpression().WithTriviaFrom(right); break; } default: { newRight = binaryExpression.Right; break; } } BinaryExpressionSyntax newBinaryExpression = BinaryExpression( (binaryExpression != null) ? right.Kind() : SyntaxKind.EqualsExpression, nullCheck.Expression.WithLeadingTrivia(logicalAnd.GetLeadingTrivia()), (binaryExpression != null) ? ((BinaryExpressionSyntax)right).OperatorToken : Token(SyntaxKind.EqualsEqualsToken).WithTriviaFrom(logicalAnd.OperatorToken), newRight) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(logicalAnd, newBinaryExpression, cancellationToken).ConfigureAwait(false)); }
private static bool IsFixable( ExpressionSyntax left, ExpressionSyntax right, SyntaxKind binaryExpressionKind, SemanticModel semanticModel, CancellationToken cancellationToken) { NullCheckStyles allowedStyles = (binaryExpressionKind == SyntaxKind.LogicalAndExpression) ? NullCheckStyles.NotEqualsToNull : NullCheckStyles.EqualsToNull; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, allowedStyles: allowedStyles); ExpressionSyntax expression = nullCheck.Expression; if (expression == null) { return(false); } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken); if (typeSymbol == null) { return(false); } if (!typeSymbol.IsReferenceTypeOrNullableType()) { return(false); } if (right == null) { return(false); } if (!ValidateRightExpression(right, binaryExpressionKind, semanticModel, cancellationToken)) { return(false); } if (RefactoringUtility.ContainsOutArgumentWithLocal(right, semanticModel, cancellationToken)) { return(false); } ExpressionSyntax expression2 = FindExpressionThatCanBeConditionallyAccessed(expression, right, isNullable: !typeSymbol.IsReferenceType); return(expression2?.SpanContainsDirectives() == false); }
public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) { var ifStatement = (IfStatementSyntax)context.Node; if (ifStatement.IsSimpleIf() && !ifStatement.ContainsDiagnostics && ifStatement.TryGetContainingList(out SyntaxList <StatementSyntax> statements) && !IsPartOfLazyInitialization(ifStatement, statements)) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, semanticModel: context.SemanticModel, cancellationToken: context.CancellationToken); if (nullCheck.Success) { SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.GetSingleStatementOrDefault()); if (assignmentInfo.Success && SyntaxComparer.AreEquivalent(assignmentInfo.Left, nullCheck.Expression) && assignmentInfo.Right.IsSingleLine() && !ifStatement.SpanContainsDirectives()) { int index = statements.IndexOf(ifStatement); if (index > 0) { StatementSyntax previousStatement = statements[index - 1]; if (!previousStatement.ContainsDiagnostics && CanRefactor(previousStatement, ifStatement, nullCheck.Expression, ifStatement.Parent)) { context.ReportDiagnostic(DiagnosticDescriptors.UseCoalesceExpression, previousStatement); } } if (index < statements.Count - 1) { StatementSyntax nextStatement = statements[index + 1]; if (!nextStatement.ContainsDiagnostics) { MemberInvocationStatementInfo invocationInfo = SyntaxInfo.MemberInvocationStatementInfo(nextStatement); if (invocationInfo.Success && SyntaxComparer.AreEquivalent(nullCheck.Expression, invocationInfo.Expression) && !ifStatement.Parent.ContainsDirectives(TextSpan.FromBounds(ifStatement.SpanStart, nextStatement.Span.End))) { context.ReportDiagnostic(DiagnosticDescriptors.InlineLazyInitialization, ifStatement); } } } } } } }
private static Task <Document> UseIsNullPatternInsteadOfComparisonAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, NullCheckStyles.ComparisonToNull, walkDownParentheses: false); ExpressionSyntax expression = nullCheck.Expression; ExpressionSyntax nullLiteral; if (object.ReferenceEquals(expression, binaryExpression.Left)) { nullLiteral = binaryExpression.Right; } else { expression = expression.WithTrailingTrivia(binaryExpression.Left.GetTrailingTrivia()); nullLiteral = binaryExpression.Left.WithLeadingTrivia(expression.GetLeadingTrivia()); } bool useIsNotNull = !AnalyzerOptions.UseLogicalNegationAndPatternMatchingToCheckForNull.IsEnabled(document, binaryExpression); PatternSyntax pattern = ConstantPattern(nullLiteral); if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression) && useIsNotNull) { pattern = NotPattern(pattern); } ExpressionSyntax newExpression = IsPatternExpression( expression, Token(binaryExpression.OperatorToken.LeadingTrivia, SyntaxKind.IsKeyword, binaryExpression.OperatorToken.TrailingTrivia), pattern); if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression) && !useIsNotNull) { newExpression = LogicalNotExpression(ParenthesizedExpression(newExpression.WithoutTrivia())); } newExpression = newExpression .WithTriviaFrom(binaryExpression) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(binaryExpression, newExpression, cancellationToken)); }
private static async Task <Document> UseStringIsNullOrEmptyMethodAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { if (binaryExpression.IsKind(SyntaxKind.EqualsExpression)) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo(binaryExpression); ExpressionSyntax expression = (CSharpUtility.IsEmptyStringExpression(binaryExpressionInfo.Left, semanticModel, cancellationToken)) ? binaryExpressionInfo.Right : binaryExpressionInfo.Left; ExpressionSyntax newNode = SimpleMemberInvocationExpression( CSharpTypeFactory.StringType(), IdentifierName("IsNullOrEmpty"), Argument(expression)); newNode = newNode .WithTriviaFrom(binaryExpression) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); } else { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression.Left); ExpressionSyntax newNode = SimpleMemberInvocationExpression( CSharpTypeFactory.StringType(), IdentifierName("IsNullOrEmpty"), Argument(nullCheck.Expression)); if (nullCheck.IsCheckingNotNull) { newNode = LogicalNotExpression(newNode); } newNode = newNode .WithTriviaFrom(binaryExpression) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); } }
public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionType) { var ifStatement = (IfStatementSyntax)context.Node; if (!ifStatement.IsSimpleIf()) { return; } if (ifStatement.ContainsDiagnostics) { return; } if (ifStatement.SpanContainsDirectives()) { return; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedStyles: NullCheckStyles.NotEqualsToNull); if (!nullCheck.Success) { return; } SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); if (!invocationInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(nullCheck.Expression, invocationInfo.Expression)) { return; } if (ifStatement.IsInExpressionTree(expressionType, context.SemanticModel, context.CancellationToken)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement); }
public static void AnalyzeFirstOrDefault(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo) { InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression; SyntaxNode parent = invocation.WalkUpParentheses().Parent; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(parent, NullCheckStyles.ComparisonToNull | NullCheckStyles.IsNull); if (!nullCheck.Success) { return; } SyntaxNode node = nullCheck.NullCheckExpression; if (node.ContainsDirectives) { return; } ExtensionMethodSymbolInfo extensionMethodSymbolInfo = context.SemanticModel.GetReducedExtensionMethodInfo(invocation, context.CancellationToken); IMethodSymbol methodSymbol = extensionMethodSymbolInfo.Symbol; if (methodSymbol == null) { return; } if (!SymbolUtility.IsLinqExtensionOfIEnumerableOfTWithPredicate(methodSymbol, context.SemanticModel, name: invocationInfo.NameText, allowImmutableArrayExtension: true)) { return; } if (!extensionMethodSymbolInfo .ReducedSymbol .ReturnType .IsReferenceTypeOrNullableType()) { return; } context.ReportDiagnostic(DiagnosticDescriptors.SimplifyLinqMethodChain, node); }
public static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { var statement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); StatementSyntax newStatement = statement; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull); SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement); ExpressionSyntax expression = invocationInfo.Expression; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken).IsNullableType()) { var memberAccess = (MemberAccessExpressionSyntax)invocationInfo.Expression; newStatement = statement.ReplaceNode(memberAccess, memberAccess.Expression.WithTrailingTrivia(memberAccess.GetTrailingTrivia())); expression = memberAccess.Expression; } int insertIndex = expression.Span.End - statement.FullSpan.Start; newStatement = SyntaxFactory.ParseStatement(newStatement.ToFullString().Insert(insertIndex, "?")); IEnumerable <SyntaxTrivia> leading = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, statement.SpanStart)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia()) : newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(leading)); IEnumerable <SyntaxTrivia> trailing = ifStatement.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()) : newStatement.WithTrailingTrivia(trailing.Concat(ifStatement.GetTrailingTrivia())); return(await document.ReplaceNodeAsync(ifStatement, newStatement, cancellationToken).ConfigureAwait(false)); }
private static void AnalyzeLogicalOrExpression(SyntaxNodeAnalysisContext context) { var binaryExpression = (BinaryExpressionSyntax)context.Node; if (binaryExpression.ContainsDiagnostics) { return; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression.Left, context.SemanticModel, allowedStyles: NullCheckStyles.CheckingNull); ExpressionSyntax expression = nullCheck.Expression; if (expression == null) { return; } ExpressionSyntax right = binaryExpression.Right.WalkDownParentheses(); if (!right.IsKind(SyntaxKind.LogicalAndExpression)) { return; } var logicalAndExpression = (BinaryExpressionSyntax)right; ExpressionChain.Enumerator en = logicalAndExpression.AsChain().GetEnumerator(); if (!en.MoveNext()) { return; } NullCheckExpressionInfo nullCheck2 = SyntaxInfo.NullCheckExpressionInfo(en.Current, context.SemanticModel, allowedStyles: NullCheckStyles.CheckingNotNull); if (!CSharpFactory.AreEquivalent(expression, nullCheck2.Expression)) { return; } ReportExpressionAlwaysEqualToTrueOrFalse(context, nullCheck2.NullCheckExpression, "true"); }
private static IfAnalysis CreateIfToAssignment( IfStatementSyntax ifStatement, ExpressionSyntax left, ExpressionSyntax expression1, ExpressionSyntax expression2, NullCheckExpressionInfo nullCheck, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { if ((nullCheck.Style & NullCheckStyles.ComparisonToNull) != 0 && AreEquivalent(nullCheck.Expression, expression1)) { return(CreateIfToAssignment(isNullable: false)); } expression1 = GetNullableOfTValueProperty(expression1, semanticModel, cancellationToken); if (AreEquivalent(nullCheck.Expression, expression1)) { return(CreateIfToAssignment(isNullable: true)); } return(null); IfAnalysis CreateIfToAssignment(bool isNullable) { if (!isNullable && expression2.Kind() == SyntaxKind.NullLiteralExpression) { if (options.UseExpression) { return(new IfElseToAssignmentWithExpressionAnalysis(ifStatement, expression1.FirstAncestor <ExpressionStatementSyntax>(), semanticModel)); } } else if (options.UseCoalesceExpression) { return(new IfElseToAssignmentWithCoalesceExpressionAnalysis(ifStatement, left, expression1, expression2, semanticModel)); } return(null); } }
private static void AnalyzeNotEqualsExpression(SyntaxNodeAnalysisContext context) { if (context.Node.ContainsDiagnostics) { return; } var binaryExpression = (BinaryExpressionSyntax)context.Node; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, allowedStyles: NullCheckStyles.NotEqualsToNull); if (nullCheck.Success) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.UseIsNullPatternInsteadOfComparisonOrViceVersa, binaryExpression, "!="); } }
private static Task <Document> SimplifyNullChckWithFirstOrDefault( Document document, SyntaxNode node, CancellationToken cancellationToken) { NullCheckExpressionInfo nullCheck = NullCheckExpressionInfo(node, NullCheckStyles.ComparisonToNull | NullCheckStyles.IsNull); var invocation = (InvocationExpressionSyntax)nullCheck.Expression; ExpressionSyntax newNode = RefactoringUtility.ChangeInvokedMethodName(invocation, "Any"); if (node.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.IsPatternExpression)) { newNode = LogicalNotExpression(newNode.TrimTrivia().Parenthesize()); } newNode = newNode.WithTriviaFrom(node); return(document.ReplaceNodeAsync(node, newNode, cancellationToken)); }
private static void AnalyzeNotEqualsExpression(SyntaxNodeAnalysisContext context) { if (context.Node.ContainsDiagnostics) { return; } var binaryExpression = (BinaryExpressionSyntax)context.Node; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, allowedStyles: NullCheckStyles.NotEqualsToNull); if (nullCheck.Success) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.UsePatternMatchingToCheckForNullOrViceVersa, binaryExpression, "!="); } }
private Task <Document> RefactorAsync( Document document, NullCheckExpressionInfo nullCheck, CancellationToken cancellationToken) { ExpressionSyntax newNode = SimpleMemberInvocationExpression( StringType(), IdentifierName(MethodName), Argument(nullCheck.Expression)); if (nullCheck.Style == NullCheckStyles.NotEqualsToNull) { newNode = LogicalNotExpression(newNode); } newNode = newNode .WithTriviaFrom(nullCheck.NullCheckExpression) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(nullCheck.NullCheckExpression, newNode, cancellationToken)); }
public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionType) { var ifStatement = (IfStatementSyntax)context.Node; if (ifStatement.IsSimpleIf() && !ifStatement.ContainsDiagnostics) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedKinds: NullCheckKind.NotEqualsToNull); if (nullCheck.Success) { MemberInvocationStatementInfo invocationInfo = SyntaxInfo.MemberInvocationStatementInfo(ifStatement.GetSingleStatementOrDefault()); if (invocationInfo.Success && SyntaxComparer.AreEquivalent(nullCheck.Expression, invocationInfo.Expression) && !ifStatement.IsInExpressionTree(expressionType, context.SemanticModel, context.CancellationToken) && !ifStatement.SpanContainsDirectives()) { context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement); } } } }
private static void AnalyzeEqualsExpression(SyntaxNodeAnalysisContext context) { if (context.Node.ContainsDiagnostics) { return; } var binaryExpression = (BinaryExpressionSyntax)context.Node; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, allowedStyles: NullCheckStyles.EqualsToNull, walkDownParentheses: false); if (nullCheck.Success) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.UsePatternMatchingToCheckForNullOrViceVersa, binaryExpression, AnalyzerOptions.UseComparisonInsteadPatternMatchingToCheckForNull, "=="); } }
public static Task <Document> RefactorAsync( Document document, SyntaxNode node, CancellationToken cancellationToken) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(node); AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(nullCheck.Expression); ExpressionSyntax newNode = IsExpression(asExpressionInfo.Expression, asExpressionInfo.Type); if (nullCheck.IsCheckingNull) { newNode = LogicalNotExpression(newNode.WithoutTrivia().Parenthesize()).WithTriviaFrom(newNode); } newNode = newNode .Parenthesize() .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(node, newNode, cancellationToken)); }
private static bool IsFixable( ExpressionSyntax left, BinaryExpressionSyntax right, SemanticModel semanticModel, CancellationToken cancellationToken = default) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left); if (!nullCheck.Success) { return(false); } ExpressionSyntax expression = nullCheck.Expression; if (CSharpFactory.AreEquivalent(expression, right.Left)) { return(right.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression) && SymbolEquals(expression, right.Left, semanticModel, cancellationToken) && CSharpUtility.IsEmptyStringExpression(right.Right, semanticModel, cancellationToken)); } if (right.Left.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { var memberAccess = (MemberAccessExpressionSyntax)right.Left; return(string.Equals(memberAccess.Name.Identifier.ValueText, "Length", StringComparison.Ordinal) && right.Right.IsNumericLiteralExpression("0") && semanticModel.GetSymbol(memberAccess, cancellationToken) is IPropertySymbol propertySymbol && !propertySymbol.IsIndexer && SymbolUtility.IsPublicInstance(propertySymbol, "Length") && propertySymbol.Type.SpecialType == SpecialType.System_Int32 && propertySymbol.ContainingType?.SpecialType == SpecialType.System_String && CSharpFactory.AreEquivalent(expression, memberAccess.Expression) && SymbolEquals(expression, memberAccess.Expression, semanticModel, cancellationToken)); } return(false); }
public static bool CanRefactor( ParameterSyntax parameter, SemanticModel semanticModel, CancellationToken cancellationToken = default) { BlockSyntax body = GetBody(parameter); if (body == null) { return(false); } IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, cancellationToken); if (parameterSymbol?.Type.IsReferenceTypeOrNullableType() != true) { return(false); } foreach (StatementSyntax statement in body.Statements) { NullCheckExpressionInfo nullCheck = GetNullCheckExpressionInfo(statement, semanticModel, cancellationToken); if (nullCheck.Success) { if (string.Equals(((IdentifierNameSyntax)nullCheck.Expression).Identifier.ValueText, parameter.Identifier.ValueText, StringComparison.Ordinal)) { return(false); } } else { break; } } return(true); }
private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode node) { if (node.SpanContainsDirectives()) { return; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(node); if (!nullCheck.Success) { return; } AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(nullCheck.Expression); if (!asExpressionInfo.Success) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseIsOperatorInsteadOfAsOperator, node); }
private static void AnalyzeNotEqualsExpression(SyntaxNodeAnalysisContext context) { if (context.Node.ContainsDiagnostics) { return; } var binaryExpression = (BinaryExpressionSyntax)context.Node; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, allowedStyles: NullCheckStyles.NotEqualsToNull); if (!nullCheck.Success) { return; } if (binaryExpression.IsInExpressionTree(context.SemanticModel, context.CancellationToken)) { return; } ReportDiagnostic(context, binaryExpression, "pattern matching"); }
private static Task <Document> UseStringIsNullOrEmptyMethodAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression.Left); ExpressionSyntax newNode = SimpleMemberInvocationExpression( CSharpTypeFactory.StringType(), IdentifierName("IsNullOrEmpty"), Argument(nullCheck.Expression)); if (nullCheck.IsCheckingNotNull) { newNode = LogicalNotExpression(newNode); } newNode = newNode .WithTriviaFrom(binaryExpression) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken)); }
private static bool IsNullCheck( StatementSyntax statement, SemanticModel semanticModel, CancellationToken cancellationToken = default(CancellationToken)) { if (!(statement is IfStatementSyntax ifStatement)) { return(false); } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull); if (!nullCheck.Success) { return(false); } if (nullCheck.Expression.Kind() != SyntaxKind.IdentifierName) { return(false); } var throwStatement = ifStatement.SingleNonBlockStatementOrDefault() as ThrowStatementSyntax; if (throwStatement?.Expression?.Kind() != SyntaxKind.ObjectCreationExpression) { return(false); } var objectCreation = (ObjectCreationExpressionSyntax)throwStatement.Expression; INamedTypeSymbol exceptionType = semanticModel.GetTypeByMetadataName(MetadataNames.System_ArgumentNullException); ISymbol type = semanticModel.GetSymbol(objectCreation.Type, cancellationToken); return(type?.Equals(exceptionType) == true); }
private static ImmutableArray <IfRefactoring> Analyze( IfStatementSyntax ifStatement, ExpressionSyntax condition, ExpressionSyntax expression1, ExpressionSyntax expression2, IfAnalysisOptions options, bool isYield, SemanticModel semanticModel, CancellationToken cancellationToken) { if (expression1?.IsMissing != false) { return(Empty); } if (expression2?.IsMissing != false) { return(Empty); } if (options.UseCoalesceExpression || options.UseExpression) { SyntaxKind kind1 = expression1.Kind(); SyntaxKind kind2 = expression2.Kind(); if (kind1.IsBooleanLiteralExpression() && kind2.IsBooleanLiteralExpression() && kind1 != kind2) { if (options.UseExpression) { if (ifStatement.IsSimpleIf() && (ifStatement.PreviousStatementOrDefault() is IfStatementSyntax previousIf) && previousIf.IsSimpleIf() && (previousIf.GetSingleStatementOrDefault() is ReturnStatementSyntax returnStatement) && returnStatement.Expression?.WalkDownParentheses().Kind() == kind1) { return(Empty); } return(new IfToReturnWithExpression(ifStatement, condition, isYield, negate: kind1 == SyntaxKind.FalseLiteralExpression).ToImmutableArray()); } return(Empty); } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(condition, semanticModel: semanticModel, cancellationToken: cancellationToken); if (nullCheck.Success) { IfRefactoring refactoring = CreateIfToReturnStatement( ifStatement, (nullCheck.IsCheckingNull) ? expression2 : expression1, (nullCheck.IsCheckingNull) ? expression1 : expression2, nullCheck, options, isYield, semanticModel, cancellationToken); if (refactoring != null) { return(refactoring.ToImmutableArray()); } } } IfToReturnWithBooleanExpression ifToReturnWithBooleanExpression = null; if (options.UseBooleanExpression && (expression1.Kind().IsBooleanLiteralExpression() || expression2.Kind().IsBooleanLiteralExpression()) && semanticModel.GetTypeSymbol(expression1, cancellationToken)?.IsBoolean() == true && semanticModel.GetTypeSymbol(expression2, cancellationToken)?.IsBoolean() == true) { ifToReturnWithBooleanExpression = IfToReturnWithBooleanExpression.Create(ifStatement, expression1, expression2, isYield); } IfToReturnWithConditionalExpression ifToReturnWithConditionalExpression = null; if (options.UseConditionalExpression && (!expression1.Kind().IsBooleanLiteralExpression() || !expression2.Kind().IsBooleanLiteralExpression())) { ifToReturnWithConditionalExpression = IfToReturnWithConditionalExpression.Create(ifStatement, expression1, expression2, isYield); } return(ToImmutableArray(ifToReturnWithBooleanExpression, ifToReturnWithConditionalExpression)); }
private static ImmutableArray <IfRefactoring> Analyze( IfStatementSyntax ifStatement, ExpressionSyntax condition, ExpressionStatementSyntax expressionStatement1, ExpressionStatementSyntax expressionStatement2, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement1); if (!assignment1.Success) { return(Empty); } SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement2); if (!assignment2.Success) { return(Empty); } ExpressionSyntax left1 = assignment1.Left; ExpressionSyntax left2 = assignment2.Left; ExpressionSyntax right1 = assignment1.Right; ExpressionSyntax right2 = assignment2.Right; if (!SyntaxComparer.AreEquivalent(left1, left2)) { return(Empty); } if (options.UseCoalesceExpression || options.UseExpression) { SyntaxKind kind1 = right1.Kind(); SyntaxKind kind2 = right2.Kind(); if (kind1.IsBooleanLiteralExpression() && kind2.IsBooleanLiteralExpression() && kind1 != kind2) { if (options.UseExpression) { return(new IfElseToAssignmentWithCondition(ifStatement, left1, condition, negate: kind1 == SyntaxKind.FalseLiteralExpression).ToImmutableArray()); } return(Empty); } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(condition, semanticModel: semanticModel, cancellationToken: cancellationToken); if (nullCheck.Success) { IfRefactoring refactoring = CreateIfToAssignment( ifStatement, left1, (nullCheck.IsCheckingNull) ? right2 : right1, (nullCheck.IsCheckingNull) ? right1 : right2, nullCheck, options, semanticModel, cancellationToken); if (refactoring != null) { return(refactoring.ToImmutableArray()); } } } if (options.UseConditionalExpression) { return(new IfElseToAssignmentWithConditionalExpression(ifStatement, left1, right1, right2).ToImmutableArray()); } return(Empty); }