private void AnalyzeInvocation(OperationAnalysisContext context, InfoCache infoCache) { // Check if the user wants these operators. var option = context.GetCSharpAnalyzerOptions().PreferRangeOperator; if (!option.Value) { return; } var operation = context.Operation; var result = AnalyzeInvocation((IInvocationOperation)operation, infoCache); if (result == null) { return; } if (CSharpSemanticFacts.Instance.IsInExpressionTree(operation.SemanticModel, operation.Syntax, infoCache.ExpressionOfTType, context.CancellationToken)) { return; } context.ReportDiagnostic(CreateDiagnostic(result.Value, option.Notification.Severity)); }
private void AnalyzeInvokedMember( OperationAnalysisContext context, InfoCache infoCache, IOperation?instance, IMethodSymbol?targetMethod, IOperation argumentValue, IPropertySymbol?lengthLikeProperty, CancellationToken cancellationToken) { // look for `s[s.Length - value]` or `s.Get(s.Length- value)`. // Needs to have the one arg for `s.Length - value`, and that arg needs to be // a subtraction. if (instance is null || !IsSubtraction(argumentValue, out var subtraction)) { return; } if (subtraction.Syntax is not BinaryExpressionSyntax binaryExpression) { return; } // Don't bother analyzing if the user doesn't like using Index/Range operators. var option = context.GetCSharpAnalyzerOptions().PreferIndexOperator; if (!option.Value) { return; } // Ok, looks promising. We're indexing in with some subtraction expression. Examine the // type this indexer is in to see if there's another member that takes a System.Index // that we can convert to. // // Also ensure that the left side of the subtraction : `s.Length - value` is actually // getting the length off the same instance we're indexing into. lengthLikeProperty ??= TryGetLengthLikeProperty(infoCache, targetMethod); if (lengthLikeProperty == null || !IsInstanceLengthCheck(lengthLikeProperty, instance, subtraction.LeftOperand)) { return; } if (CSharpSemanticFacts.Instance.IsInExpressionTree(instance.SemanticModel, instance.Syntax, infoCache.ExpressionOfTType, cancellationToken)) { return; } // Everything looks good. We can update this to use the System.Index member instead. context.ReportDiagnostic( DiagnosticHelper.Create( Descriptor, binaryExpression.GetLocation(), option.Notification.Severity, ImmutableArray <Location> .Empty, ImmutableDictionary <string, string?> .Empty)); }
private static bool ShouldAnalyze(OperationAnalysisContext context, out ReportDiagnostic severity) { var option = context.GetCSharpAnalyzerOptions().PreferNullCheckOverTypeCheck; if (!option.Value) { severity = ReportDiagnostic.Default; return false; } severity = option.Notification.Severity; return true; }
protected override CodeStyleOption2 <bool> PreferThrowExpressionStyle(OperationAnalysisContext context) => context.GetCSharpAnalyzerOptions().PreferThrowExpression;