private static bool CanUseCoalesceExpression(StatementSyntax statement, ExpressionSyntax expression) { SyntaxKind kind = statement.Kind(); if (kind == SyntaxKind.LocalDeclarationStatement) { SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement); return(localInfo.Success && !localInfo.Type.IsKind(SyntaxKind.RefType) && expression.IsKind(SyntaxKind.IdentifierName) && string.Equals(localInfo.IdentifierText, ((IdentifierNameSyntax)expression).Identifier.ValueText, StringComparison.Ordinal) && !localInfo.Value.GetTrailingTrivia().Any(f => f.IsDirective) && !localInfo.SemicolonToken.ContainsDirectives); } else if (kind == SyntaxKind.ExpressionStatement) { var expressionStatement = (ExpressionStatementSyntax)statement; SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement); return(assignmentInfo.Success && CSharpFactory.AreEquivalent(expression, assignmentInfo.Left) && !assignmentInfo.Right.GetTrailingTrivia().Any(f => f.IsDirective) && !expressionStatement.SemicolonToken.ContainsDirectives); } return(false); }
private static bool AreEquivalent(StatementSyntax statement1, StatementSyntax statement2) { return(statement1.Kind() == statement2.Kind() && CSharpFactory.AreEquivalent(statement1, statement2) && statement1.DescendantTrivia().All(f => f.IsWhitespaceOrEndOfLineTrivia()) && statement2.DescendantTrivia().All(f => f.IsWhitespaceOrEndOfLineTrivia())); }
public static bool IsFixable(AssignmentExpressionSyntax assignmentExpression) { SimpleAssignmentExpressionInfo assignmentInfo = SyntaxInfo.SimpleAssignmentExpressionInfo(assignmentExpression); if (!assignmentInfo.Success) { return(false); } if (assignmentExpression.IsParentKind(SyntaxKind.ObjectInitializerExpression)) { return(false); } if (!IsFixableBinaryExpression(assignmentInfo.Right.Kind())) { return(false); } BinaryExpressionInfo binaryInfo = SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)assignmentInfo.Right); if (!binaryInfo.Success) { return(false); } if (!CSharpFactory.AreEquivalent(assignmentInfo.Left, binaryInfo.Left)) { return(false); } return(true); }
private static bool AreEquivalent(StatementSyntax statement1, StatementSyntax statement2) { if (statement1 == null) { return(false); } if (statement2 == null) { return(false); } if (statement1 is not BlockSyntax block1) { return(CSharpFactory.AreEquivalent(statement1, statement2.SingleNonBlockStatementOrDefault())); } SyntaxList <StatementSyntax> statements1 = block1.Statements; if (statement2 is not BlockSyntax block2) { return(CSharpFactory.AreEquivalent(statement2, statement1.SingleNonBlockStatementOrDefault())); } SyntaxList <StatementSyntax> statements2 = block2.Statements; return(SyntaxFactory.AreEquivalent(statements1, statements2, topLevel: false)); }
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)); }
internal static ExpressionSyntax FindExpressionThatCanBeConditionallyAccessed(ExpressionSyntax expressionToFind, ExpressionSyntax expression) { if (expression.IsKind(SyntaxKind.LogicalNotExpression)) { expression = ((PrefixUnaryExpressionSyntax)expression).Operand; } SyntaxKind kind = expressionToFind.Kind(); SyntaxToken firstToken = expression.GetFirstToken(); int start = firstToken.SpanStart; SyntaxNode node = firstToken.Parent; while (node?.SpanStart == start) { if (kind == node.Kind() && node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression) && CSharpFactory.AreEquivalent(expressionToFind, node)) { return((ExpressionSyntax)node); } node = node.Parent; } return(null); }
internal static SimplifyCodeBranchingKind?GetKind(IfStatementSyntax ifStatement, SemanticModel semanticModel, CancellationToken cancellationToken) { ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses(); if (condition?.IsMissing != false) { return(null); } StatementSyntax ifStatementStatement = ifStatement.Statement; if (ifStatementStatement == null) { return(null); } ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause != null) { if (IsFixableIfElseInsideWhile(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.IfElseInsideWhile); } else { var ifStatementBlock = ifStatementStatement as BlockSyntax; if (ifStatementBlock?.Statements.Any() == false && ifStatementBlock.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace() && ifStatementBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace() && IsFixableIfElseWithEmptyIf(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.IfElseWithEmptyIf); } else if (IsFixableIfElseWithReturnOrContinueInsideIf(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf); } } } else if (IsFixableSimpleIfInsideWhileOrDo(ifStatement, semanticModel, cancellationToken)) { return(SimplifyCodeBranchingKind.SimplifyIfInsideWhileOrDo); } else if (!ifStatement.IsParentKind(SyntaxKind.ElseClause) && (ifStatement.SingleNonBlockStatementOrDefault() is DoStatementSyntax doStatement) && CSharpFactory.AreEquivalent(condition, doStatement.Condition?.WalkDownParentheses())) { return(SimplifyCodeBranchingKind.SimpleIfContainingOnlyDo); } return(null); }
internal static ExpressionSyntax FindExpressionThatCanBeConditionallyAccessed( ExpressionSyntax expressionToFind, ExpressionSyntax expression, bool isNullable, SemanticModel semanticModel, CancellationToken cancellationToken = default) { if (expression.IsKind(SyntaxKind.LogicalNotExpression)) { expression = ((PrefixUnaryExpressionSyntax)expression).Operand; } SyntaxKind kind = expressionToFind.Kind(); SyntaxToken firstToken = expression.GetFirstToken(); int start = firstToken.SpanStart; SyntaxNode node = firstToken.Parent; while (node?.SpanStart == start) { if (kind == node.Kind() && node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression) && semanticModel.GetTypeSymbol(node.Parent, cancellationToken)?.Kind != SymbolKind.PointerType && CSharpFactory.AreEquivalent(expressionToFind, node)) { if (!isNullable) { return((ExpressionSyntax)node); } if (node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && (((MemberAccessExpressionSyntax)node.Parent).Name is IdentifierNameSyntax identifierName) && string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal) && node.Parent.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression)) { return((ExpressionSyntax)node.Parent); } return(null); } node = node.Parent; } return(null); }
private static void AnalyzeCoalesceExpression(SyntaxNodeAnalysisContext context) { var coalesceExpression = (BinaryExpressionSyntax)context.Node; BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo(coalesceExpression, walkDownParentheses: false); if (!binaryExpressionInfo.Success) { return; } ExpressionSyntax right = binaryExpressionInfo.Right; if (!right.IsKind(SyntaxKind.ParenthesizedExpression)) { return; } var parenthesizedExpression = (ParenthesizedExpressionSyntax)right; ExpressionSyntax expression = parenthesizedExpression.Expression; if (!expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) { return; } SimpleAssignmentExpressionInfo assignmentInfo = SyntaxInfo.SimpleAssignmentExpressionInfo((AssignmentExpressionSyntax)expression); if (!assignmentInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(binaryExpressionInfo.Left, assignmentInfo.Left)) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCompoundAssignment, coalesceExpression); DiagnosticHelpers.ReportToken(context, DiagnosticDescriptors.UseCompoundAssignmentFadeOut, parenthesizedExpression.OpenParenToken); DiagnosticHelpers.ReportNode(context, DiagnosticDescriptors.UseCompoundAssignmentFadeOut, assignmentInfo.Left); DiagnosticHelpers.ReportToken(context, DiagnosticDescriptors.UseCompoundAssignmentFadeOut, parenthesizedExpression.CloseParenToken); }
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); }
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 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; context.ReportDiagnostic(DiagnosticDescriptors.UseCompoundAssignment, assignmentExpression, GetCompoundAssignmentOperatorText(binaryExpression)); context.ReportNode(DiagnosticDescriptors.UseCompoundAssignmentFadeOut, binaryExpression.Left); }
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); }
private static bool IsFixableEqualsExpression( BinaryExpressionSyntax equalsExpression, ExpressionSyntax switchExpression, SemanticModel semanticModel, CancellationToken cancellationToken) { ExpressionSyntax left = equalsExpression.Left?.WalkDownParentheses(); if (IsFixableSwitchExpression(left, semanticModel, cancellationToken)) { ExpressionSyntax right = equalsExpression.Right?.WalkDownParentheses(); if (IsFixableSwitchExpression(right, semanticModel, cancellationToken) && semanticModel.HasConstantValue(right)) { return(switchExpression == null || CSharpFactory.AreEquivalent(left, switchExpression)); } } return(false); }
private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) { var ifStatement = (IfStatementSyntax)context.Node; if (ifStatement.ContainsDiagnostics) { return; } if (ifStatement.SpanContainsDirectives()) { return; } if (!ifStatement.IsSimpleIf()) { return; } SyntaxList <StatementSyntax> statements = SyntaxInfo.StatementListInfo(ifStatement).Statements; if (!statements.Any()) { return; } if (IsPartOfLazyInitialization()) { return; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo( ifStatement.Condition, semanticModel: context.SemanticModel, allowedStyles: NullCheckStyles.CheckingNull, cancellationToken: context.CancellationToken); if (!nullCheck.Success) { return; } SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); if (!assignmentInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(assignmentInfo.Left, nullCheck.Expression)) { return; } if (!assignmentInfo.Right.IsSingleLine()) { return; } int index = statements.IndexOf(ifStatement); if (index > 0 && !context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpression)) { StatementSyntax previousStatement = statements[index - 1]; if (!previousStatement.ContainsDiagnostics && !previousStatement.GetTrailingTrivia().Any(f => f.IsDirective) && !ifStatement.GetLeadingTrivia().Any(f => f.IsDirective) && CanUseCoalesceExpression(previousStatement, nullCheck.Expression)) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCoalesceExpression, previousStatement); } } if (context.IsAnalyzerSuppressed(DiagnosticDescriptors.InlineLazyInitialization)) { return; } if (index == statements.Count - 1) { return; } StatementSyntax nextStatement = statements[index + 1]; if (nextStatement.ContainsDiagnostics) { return; } SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(nextStatement); if (!invocationInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(nullCheck.Expression, invocationInfo.Expression)) { return; } if (ifStatement.GetTrailingTrivia().Any(f => f.IsDirective)) { return; } if (nextStatement.SpanOrLeadingTriviaContainsDirectives()) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.InlineLazyInitialization, ifStatement); bool IsPartOfLazyInitialization() { return(statements.Count == 2 && statements.IndexOf(ifStatement) == 0 && statements[1].IsKind(SyntaxKind.ReturnStatement)); } }
private static void AnalyzeElementAccessExpression(SyntaxNodeAnalysisContext context) { var elementAccessExpression = (ElementAccessExpressionSyntax)context.Node; ExpressionSyntax expression = elementAccessExpression .ArgumentList .Arguments .SingleOrDefault(shouldThrow: false)? .Expression .WalkDownParentheses(); if (expression == null) { return; } if (!expression.IsKind(SyntaxKind.SubtractExpression)) { return; } BinaryExpressionInfo subtractExpressionInfo = SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)expression); if (!subtractExpressionInfo.Right.IsNumericLiteralExpression("1")) { return; } if (!subtractExpressionInfo.Left.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { return; } var memberAccessExpression = (MemberAccessExpressionSyntax)subtractExpressionInfo.Left; if (!(memberAccessExpression.Name is IdentifierNameSyntax identifierName)) { return; } if (identifierName.Identifier.ValueText != "Count") { return; } if (!CSharpFactory.AreEquivalent(elementAccessExpression.Expression, memberAccessExpression.Expression)) { return; } ISymbol symbol = context.SemanticModel.GetSymbol(elementAccessExpression, context.CancellationToken); if (symbol?.Kind != SymbolKind.Property || symbol.IsStatic || symbol.DeclaredAccessibility != Accessibility.Public || !RoslynSymbolUtility.IsList(symbol.ContainingType.OriginalDefinition)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.CallLastInsteadOfUsingElementAccess, elementAccessExpression.ArgumentList); }
public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionOfTSymbol) { 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); ExpressionSyntax expression = nullCheck.Expression; if (expression == null) { return; } SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); ExpressionSyntax expression2 = invocationInfo.Expression; if (expression2 == null) { return; } ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(expression); if (typeSymbol == null) { return; } if (typeSymbol.IsNullableType()) { if (!expression2.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { return; } var memberAccess = (MemberAccessExpressionSyntax)expression2; if (!(memberAccess.Name is IdentifierNameSyntax identifierName)) { return; } if (!string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal)) { return; } expression2 = memberAccess.Expression; } if (!CSharpFactory.AreEquivalent(expression, expression2)) { return; } if (ifStatement.IsInExpressionTree(expressionOfTSymbol, context.SemanticModel, context.CancellationToken)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement); }
internal static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) { var ifStatement = (IfStatementSyntax)context.Node; ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses(); if (condition?.IsMissing != false) { return; } StatementSyntax statement = ifStatement.Statement; if (statement == null) { return; } var block = statement as BlockSyntax; if (block?.Statements.Any() == false && block.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace() && block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()) { if (IsFixableIfElse(ifStatement)) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyCodeBranching, ifStatement); } } else { ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause != null) { if (IsFixableIfElseInsideWhile(ifStatement, elseClause)) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyCodeBranching, ifStatement); } } else if (IsFixableSimpleIfInsideWhileOrDo(ifStatement, context.SemanticModel, context.CancellationToken)) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyCodeBranching, ifStatement); } else { if (ifStatement.IsParentKind(SyntaxKind.ElseClause)) { return; } if (!(ifStatement.SingleNonBlockStatementOrDefault() is DoStatementSyntax doStatement)) { return; } if (!CSharpFactory.AreEquivalent(condition, doStatement.Condition?.WalkDownParentheses())) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyCodeBranching, ifStatement); } } }
private static BinaryExpressionPart GetRedundantPart( ExpressionSyntax left, ExpressionSyntax right, SemanticModel semanticModel, CancellationToken cancellationToken) { SyntaxKind leftKind = left.Kind(); SyntaxKind rightKind = right.Kind(); switch (leftKind) { case SyntaxKind.ObjectCreationExpression: case SyntaxKind.AnonymousObjectCreationExpression: case SyntaxKind.ArrayCreationExpression: case SyntaxKind.ImplicitArrayCreationExpression: case SyntaxKind.InterpolatedStringExpression: case SyntaxKind.ThisExpression: case SyntaxKind.StringLiteralExpression: case SyntaxKind.TypeOfExpression: return(BinaryExpressionPart.Right); case SyntaxKind.NullLiteralExpression: return(BinaryExpressionPart.Left); case SyntaxKind.DefaultExpression: { if (IsDefaultOfReferenceOrNullableType((DefaultExpressionSyntax)left, semanticModel, cancellationToken)) { return(BinaryExpressionPart.Left); } break; } } Optional <object> optional = semanticModel.GetConstantValue(left, cancellationToken); if (optional.HasValue) { object value = optional.Value; if (value != null) { return(BinaryExpressionPart.Right); } else { return(BinaryExpressionPart.Left); } } ITypeSymbol leftSymbol = semanticModel.GetTypeSymbol(left, cancellationToken); if (leftSymbol?.IsErrorType() == false && leftSymbol.IsValueType && !leftSymbol.IsNullableType()) { return(BinaryExpressionPart.Right); } switch (rightKind) { case SyntaxKind.NullLiteralExpression: { return(BinaryExpressionPart.Right); } case SyntaxKind.DefaultExpression: { if (IsDefaultOfReferenceOrNullableType((DefaultExpressionSyntax)right, semanticModel, cancellationToken)) { return(BinaryExpressionPart.Right); } break; } } if (leftKind == rightKind && CSharpFactory.AreEquivalent(left, right)) { return(BinaryExpressionPart.Right); } return(BinaryExpressionPart.None); }
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); } } }
public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) { var ifStatement = (IfStatementSyntax)context.Node; if (!ifStatement.IsSimpleIf()) { return; } if (ifStatement.ContainsDiagnostics) { return; } if (ifStatement.SpanContainsDirectives()) { return; } SyntaxList <StatementSyntax> statements = SyntaxInfo.StatementListInfo(ifStatement).Statements; if (!statements.Any()) { return; } if (IsPartOfLazyInitialization(ifStatement, statements)) { return; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, semanticModel: context.SemanticModel, cancellationToken: context.CancellationToken); if (!nullCheck.Success) { return; } SimpleAssignmentStatementInfo simpleAssignment = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); if (!simpleAssignment.Success) { return; } if (!CSharpFactory.AreEquivalent(simpleAssignment.Left, nullCheck.Expression)) { return; } if (!simpleAssignment.Right.IsSingleLine()) { return; } int index = statements.IndexOf(ifStatement); if (index > 0) { StatementSyntax previousStatement = statements[index - 1]; if (!previousStatement.ContainsDiagnostics && IsFixable(previousStatement, ifStatement, nullCheck.Expression, ifStatement.Parent)) { context.ReportDiagnostic(DiagnosticDescriptors.UseCoalesceExpression, previousStatement); } } if (index == statements.Count - 1) { return; } StatementSyntax nextStatement = statements[index + 1]; if (nextStatement.ContainsDiagnostics) { return; } SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(nextStatement); if (!invocationInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(nullCheck.Expression, invocationInfo.Expression)) { return; } if (ifStatement.Parent.ContainsDirectives(TextSpan.FromBounds(ifStatement.SpanStart, nextStatement.Span.End))) { return; } context.ReportDiagnostic(DiagnosticDescriptors.InlineLazyInitialization, ifStatement); }
private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) { var ifStatement = (IfStatementSyntax)context.Node; SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; IsKindExpressionInfo isKindExpression = IsKindExpressionInfo.Create(ifStatement.Condition, semanticModel, cancellationToken: cancellationToken); if (!isKindExpression.Success) { return; } Optional <object> optionalConstantValue = semanticModel.GetConstantValue(isKindExpression.KindExpression, cancellationToken); if (!optionalConstantValue.HasValue) { return; } if (!(optionalConstantValue.Value is ushort value)) { return; } if (!_syntaxKindValuesToNames.TryGetValue(value, out string name)) { return; } if (!_syntaxKindNames.Contains(name)) { return; } switch (isKindExpression.Style) { case IsKindExpressionStyle.IsKind: case IsKindExpressionStyle.IsKindConditional: case IsKindExpressionStyle.Kind: case IsKindExpressionStyle.KindConditional: { if (!(ifStatement.Statement is BlockSyntax block)) { return; } Analyze(block.Statements.FirstOrDefault()); break; } case IsKindExpressionStyle.NotIsKind: case IsKindExpressionStyle.NotIsKindConditional: case IsKindExpressionStyle.NotKind: case IsKindExpressionStyle.NotKindConditional: { if (ifStatement.Else != null) { return; } StatementSyntax statement = ifStatement.Statement.SingleNonBlockStatementOrDefault(); if (statement == null) { return; } if (!CSharpFacts.IsJumpStatement(statement.Kind())) { return; } Analyze(ifStatement.NextStatement()); break; } } void Analyze(StatementSyntax statement) { SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(statement); if (!localInfo.Success) { return; } if (!(localInfo.Value is CastExpressionSyntax castExpression)) { return; } if (!IsFixableSyntaxSymbol(castExpression.Type, name, semanticModel, cancellationToken)) { return; } if (!CSharpFactory.AreEquivalent(isKindExpression.Expression, castExpression.Expression)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.UsePatternMatching, ifStatement.IfKeyword); } }
private static void AnalyzeBitwiseAndExpression(SyntaxNodeAnalysisContext context) { var bitwiseAnd = (BinaryExpressionSyntax)context.Node; ExpressionSyntax expression = bitwiseAnd.WalkUpParentheses(); if (!expression.IsParentKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression)) { return; } var equalsOrNotEquals = (BinaryExpressionSyntax)expression.Parent; ExpressionSyntax otherExpression = (ReferenceEquals(equalsOrNotEquals.Left, expression)) ? equalsOrNotEquals.Right : equalsOrNotEquals.Left; otherExpression = otherExpression.WalkDownParentheses(); ExpressionSyntax right = bitwiseAnd.Right.WalkDownParentheses(); SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; if (otherExpression.IsNumericLiteralExpression("0")) { if (SyntaxUtility.IsCompositeEnumValue(right, semanticModel, cancellationToken)) { return; } } else if (!CSharpFactory.AreEquivalent(right, otherExpression)) { return; } IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(bitwiseAnd, cancellationToken); if (methodSymbol?.MethodKind != MethodKind.BuiltinOperator || methodSymbol.Name != WellKnownMemberNames.BitwiseAndOperatorName || methodSymbol.ContainingType?.TypeKind != TypeKind.Enum) { return; } ExpressionSyntax left = bitwiseAnd.Left.WalkDownParentheses(); if (!IsSuitableAsExpressionOfHasFlag(left)) { return; } if (!IsSuitableAsArgumentOfHasFlag(right)) { return; } DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.ReportOnly.ConvertBitwiseOperationToHasFlagCall, equalsOrNotEquals); bool IsSuitableAsExpressionOfHasFlag(ExpressionSyntax expression) { if (expression.IsKind( SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.InvocationExpression, SyntaxKind.ElementAccessExpression)) { return(semanticModel.GetTypeSymbol(expression, cancellationToken)?.TypeKind == TypeKind.Enum); } return(false); } bool IsSuitableAsArgumentOfHasFlag(ExpressionSyntax expression) { expression = expression.WalkDownParentheses(); if (expression.IsKind( SyntaxKind.BitwiseAndExpression, SyntaxKind.BitwiseOrExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.IdentifierName)) { return(semanticModel.GetTypeSymbol(expression, cancellationToken)?.TypeKind == TypeKind.Enum); } return(false); } }
public static async Task <Document> RefactorAsync( Document document, ConditionalExpressionSyntax conditionalExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false); ConditionalExpressionInfo conditionalExpressionInfo = SyntaxInfo.ConditionalExpressionInfo(conditionalExpression); NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(conditionalExpressionInfo.Condition, semanticModel: semanticModel, cancellationToken: cancellationToken); ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse; ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue; ExpressionSyntax expression = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull); bool coalesce = false; ExpressionSyntax newNode = null; if (CSharpFactory.AreEquivalent(nullCheck.Expression, whenNotNull)) { newNode = nullCheck.Expression; coalesce = true; } else if (semanticModel .GetTypeSymbol(nullCheck.Expression, cancellationToken) .IsNullableType()) { if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)) { var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent; if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) && (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value") { if (memberAccessExpression == whenNotNull) { newNode = nullCheck.Expression; coalesce = true; } else { newNode = ParseExpression($"{expression}?{whenNotNull.ToString().Substring(memberAccessExpression.Span.End - whenNotNull.SpanStart)}"); } } } } if (newNode == null) { newNode = ParseExpression(whenNotNull.ToString().Insert(expression.Span.End - whenNotNull.SpanStart, "?")); } if (coalesce || !semanticModel.GetTypeSymbol(whenNotNull, cancellationToken).IsReferenceType) { newNode = CoalesceExpression(newNode.Parenthesize(), whenNull.Parenthesize()); } newNode = newNode .WithTriviaFrom(conditionalExpression) .Parenthesize(); return(await document.ReplaceNodeAsync(conditionalExpression, newNode, cancellationToken).ConfigureAwait(false)); }
private static void AnalyzeSimpleAssignmentExpression(SyntaxNodeAnalysisContext context) { if (context.Node.SpanContainsDirectives()) { return; } var assignment = (AssignmentExpressionSyntax)context.Node; if (assignment.IsParentKind( SyntaxKind.ObjectInitializerExpression, SyntaxKind.WithInitializerExpression)) { return; } ExpressionSyntax left = assignment.Left; ExpressionSyntax right = assignment.Right; if (left?.IsMissing != false) { return; } if (right?.IsKind(SyntaxKind.AddExpression, SyntaxKind.SubtractExpression) != true) { return; } var binaryExpression = (BinaryExpressionSyntax)right; ExpressionSyntax binaryLeft = binaryExpression.Left; ExpressionSyntax binaryRight = binaryExpression.Right; if (binaryLeft?.IsMissing != false) { return; } if (binaryRight?.IsNumericLiteralExpression("1") != true) { return; } ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(left, context.CancellationToken); if (typeSymbol?.SupportsPrefixOrPostfixUnaryOperator() != true) { return; } if (!CSharpFactory.AreEquivalent(left, binaryLeft)) { return; } string operatorText = GetOperatorText(assignment); ReportDiagnostic(context, assignment, operatorText); DiagnosticHelpers.ReportToken(context, DiagnosticDescriptors.UseUnaryOperatorInsteadOfAssignmentFadeOut, assignment.OperatorToken, operatorText); DiagnosticHelpers.ReportNode(context, DiagnosticDescriptors.UseUnaryOperatorInsteadOfAssignmentFadeOut, binaryLeft, operatorText); DiagnosticHelpers.ReportNode(context, DiagnosticDescriptors.UseUnaryOperatorInsteadOfAssignmentFadeOut, binaryRight, operatorText); }
public static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context) { if (context.Node.SpanContainsDirectives()) { return; } var conditionalExpression = (ConditionalExpressionSyntax)context.Node; ConditionalExpressionInfo conditionalExpressionInfo = SyntaxInfo.ConditionalExpressionInfo(conditionalExpression); if (!conditionalExpressionInfo.Success) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(conditionalExpressionInfo.Condition, semanticModel: semanticModel, cancellationToken: cancellationToken); if (!nullCheck.Success) { return; } ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse; ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue; if (CSharpFactory.AreEquivalent(nullCheck.Expression, whenNotNull)) { if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression) && semanticModel .GetTypeSymbol(nullCheck.Expression, cancellationToken)? .IsReferenceTypeOrNullableType() == true) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression, conditionalExpression); } } else if (whenNotNull.IsKind( SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression, SyntaxKind.ConditionalAccessExpression, SyntaxKind.InvocationExpression)) { ExpressionSyntax expression = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed( nullCheck.Expression, whenNotNull, semanticModel, cancellationToken); if (expression == null) { return; } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken); if (typeSymbol == null) { return; } if (typeSymbol.IsReferenceType) { Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken); } else if (typeSymbol.IsNullableType()) { if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)) { var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent; if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) && (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value") { if (memberAccessExpression == whenNotNull) { if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression, conditionalExpression); } } else { Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken); } } } } } else if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression) && whenNotNull.IsKind(SyntaxKind.CastExpression) && whenNull.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultLiteralExpression)) { var castExpression = (CastExpressionSyntax)whenNotNull; if (castExpression.Type.IsKind(SyntaxKind.NullableType) && castExpression.Expression.IsKind(SyntaxKind.InvocationExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression)) { ExpressionSyntax expression = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed( nullCheck.Expression, castExpression.Expression, isNullable: true, semanticModel, cancellationToken); if (expression != null) { ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken); if (typeSymbol?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression, conditionalExpression); } } } } }
private static void AnalyzeUsingStatement(SyntaxNodeAnalysisContext context) { var usingStatement = (UsingStatementSyntax)context.Node; StatementSyntax statement = usingStatement.Statement; if (statement?.Kind() != SyntaxKind.Block) { return; } var block = (BlockSyntax)statement; StatementSyntax lastStatement = block.Statements.LastOrDefault(); if (lastStatement == null) { return; } if (lastStatement.SpanContainsDirectives()) { return; } SimpleMemberInvocationStatementInfo info = SyntaxInfo.SimpleMemberInvocationStatementInfo(lastStatement); if (!info.Success) { return; } if (info.Arguments.Any()) { return; } string methodName = info.NameText; if (methodName != "Dispose" && methodName != "Close") { return; } ExpressionSyntax usingExpression = usingStatement.Expression; if (usingExpression != null) { if (CSharpFactory.AreEquivalent(info.Expression, usingExpression)) { ReportDiagnostic(context, info.Statement, methodName); } } else { VariableDeclarationSyntax usingDeclaration = usingStatement.Declaration; if (usingDeclaration != null && info.Expression.Kind() == SyntaxKind.IdentifierName) { var identifierName = (IdentifierNameSyntax)info.Expression; VariableDeclaratorSyntax declarator = usingDeclaration.Variables.LastOrDefault(); if (declarator != null && declarator.Identifier.ValueText == identifierName.Identifier.ValueText) { ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); if (symbol?.Equals(context.SemanticModel.GetSymbol(identifierName, context.CancellationToken)) == true) { ReportDiagnostic(context, info.Statement, methodName); } } } } }
private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context) { var invocationExpression = (InvocationExpressionSyntax)context.Node; if (invocationExpression.ContainsDiagnostics) { return; } SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression); if (!invocationInfo.Success) { return; } ISymbol symbol = null; string methodName = invocationInfo.NameText; switch (invocationInfo.Arguments.Count) { case 0: { switch (methodName) { case "First": { if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseElementAccess)) { UseElementAccessInsteadOfCallingFirst(); } break; } } break; } case 1: { switch (methodName) { case "ElementAt": { if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseElementAccess)) { UseElementAccessInsteadOfCallingElementAt(); } break; } case "IsKind": { if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UnnecessaryNullCheck)) { AnalyzeUnnecessaryNullCheck(); } break; } } break; } } if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseReturnValue) && invocationExpression.IsParentKind(SyntaxKind.ExpressionStatement)) { UseReturnValue(); } void AnalyzeUnnecessaryNullCheck() { ExpressionSyntax expression = invocationInfo.InvocationExpression.WalkUpParentheses(); SyntaxNode parent = expression.Parent; if (!parent.IsKind(SyntaxKind.LogicalAndExpression)) { return; } var binaryExpression = (BinaryExpressionSyntax)parent; if (expression != binaryExpression.Right) { return; } if (binaryExpression.Left.ContainsDirectives) { return; } if (binaryExpression.OperatorToken.ContainsDirectives) { return; } NullCheckExpressionInfo nullCheckInfo = SyntaxInfo.NullCheckExpressionInfo(binaryExpression.Left, NullCheckStyles.CheckingNotNull & ~NullCheckStyles.HasValue); if (!nullCheckInfo.Success) { return; } if (!CSharpFactory.AreEquivalent(invocationInfo.Expression, nullCheckInfo.Expression)) { return; } if (!CSharpSymbolUtility.IsIsKindExtensionMethod(invocationExpression, context.SemanticModel, context.CancellationToken)) { return; } TextSpan span = TextSpan.FromBounds(binaryExpression.Left.SpanStart, binaryExpression.OperatorToken.Span.End); DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.UnnecessaryNullCheck, Location.Create(invocationInfo.InvocationExpression.SyntaxTree, span)); } void UseElementAccessInsteadOfCallingFirst() { if (!invocationInfo.Expression.GetTrailingTrivia().IsEmptyOrWhitespace()) { return; } symbol = context.SemanticModel.GetSymbol(invocationExpression, context.CancellationToken); if (symbol?.Kind != SymbolKind.Method || symbol.IsStatic || symbol.DeclaredAccessibility != Accessibility.Public || !RoslynSymbolUtility.IsList(symbol.ContainingType.OriginalDefinition)) { return; } TextSpan span = TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationExpression.Span.End); DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.UseElementAccess, Location.Create(invocationExpression.SyntaxTree, span)); } void UseElementAccessInsteadOfCallingElementAt() { if (!invocationInfo.Expression.GetTrailingTrivia().IsEmptyOrWhitespace()) { return; } symbol = context.SemanticModel.GetSymbol(invocationExpression, context.CancellationToken); if (symbol?.Kind != SymbolKind.Method || symbol.IsStatic || symbol.DeclaredAccessibility != Accessibility.Public || !symbol.ContainingType.OriginalDefinition.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_SyntaxTriviaList)) { return; } TextSpan span = TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationExpression.Span.End); DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.UseElementAccess, Location.Create(invocationExpression.SyntaxTree, span)); } void UseReturnValue() { if (symbol == null) { symbol = context.SemanticModel.GetSymbol(invocationExpression, context.CancellationToken); } if (symbol?.Kind != SymbolKind.Method) { return; } if (!RoslynSymbolUtility.IsRoslynType(symbol.ContainingType)) { return; } var methodSymbol = (IMethodSymbol)symbol; if (!RoslynSymbolUtility.IsRoslynType(methodSymbol.ReturnType)) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseReturnValue, invocationExpression); } }