public static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo) { InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression; SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; ExtensionMethodSymbolInfo extensionInfo = semanticModel.GetReducedExtensionMethodInfo(invocationExpression, cancellationToken); if (extensionInfo.Symbol == null) { return; } if (!SymbolUtility.IsLinqCast(extensionInfo.Symbol, semanticModel)) { return; } ITypeSymbol typeArgument = extensionInfo.ReducedSymbol.TypeArguments.SingleOrDefault(shouldThrow: false); if (typeArgument == null) { return; } var memberAccessExpressionType = semanticModel.GetTypeSymbol(invocationInfo.Expression, cancellationToken) as INamedTypeSymbol; if (memberAccessExpressionType?.OriginalDefinition.IsIEnumerableOfT() != true) { return; } if (!typeArgument.Equals(memberAccessExpressionType.TypeArguments[0])) { return; } if (invocationExpression.ContainsDirectives(TextSpan.FromBounds(invocationInfo.Expression.Span.End, invocationExpression.Span.End))) { return; } context.ReportDiagnostic( DiagnosticDescriptors.RemoveRedundantCast, Location.Create(invocationExpression.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationInfo.ArgumentList.Span.End))); }
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 void Analyze( SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo) { InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression; if (invocationInfo.Name.SpanOrTrailingTriviaContainsDirectives()) { return; } if (invocationInfo.ArgumentList.SpanOrLeadingTriviaContainsDirectives()) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; ExtensionMethodSymbolInfo extensionInfo = semanticModel.GetExtensionMethodInfo(invocationExpression, cancellationToken); if (extensionInfo.Symbol == null) { return; } if (!SymbolUtility.IsLinqSelect(extensionInfo.Symbol, semanticModel, allowImmutableArrayExtension: true)) { return; } ITypeSymbol typeArgument = extensionInfo.ReducedSymbolOrSymbol.TypeArguments[0]; if (!typeArgument.IsReferenceType) { return; } if (typeArgument.SpecialType == SpecialType.System_Object) { return; } ExpressionSyntax expression = invocationExpression.ArgumentList?.Arguments.Last().Expression; SingleParameterLambdaExpressionInfo lambdaInfo = SyntaxInfo.SingleParameterLambdaExpressionInfo(expression); if (!lambdaInfo.Success) { return; } CastExpressionSyntax castExpression = GetCastExpression(lambdaInfo.Body); if (castExpression == null) { return; } if (!(castExpression.Expression is IdentifierNameSyntax identifierName)) { return; } if (!string.Equals(lambdaInfo.Parameter.Identifier.ValueText, identifierName.Identifier.ValueText, StringComparison.Ordinal)) { return; } var castSymbol = semanticModel.GetSymbol(castExpression, cancellationToken) as IMethodSymbol; if (castSymbol?.MethodKind == MethodKind.Conversion) { return; } context.ReportDiagnostic( DiagnosticDescriptors.CallCastInsteadOfSelect, Location.Create(invocationExpression.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationExpression.Span.End))); }