private void AnalyzeOperation(OperationAnalysisContext context) { var ifOperation = (IConditionalOperation)context.Operation; if (!(ifOperation.Syntax is TIfStatementSyntax ifStatement)) { return; } var language = ifStatement.Language; var option = context.GetOption(_option, language); if (!option.Value) { return; } if (!TryMatchPattern(ifOperation, context.ContainingSymbol)) { return; } var additionalLocations = ImmutableArray.Create(ifStatement.GetLocation()); context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, ifStatement.GetFirstToken().GetLocation(), option.Notification.Severity, additionalLocations, properties: null)); }
private void AnalyzeOperation(OperationAnalysisContext context) { // We only create a diagnostic if the option's value is set to true. var option = context.GetOption(CodeStyleOptions2.PreferExplicitTupleNames, context.Compilation.Language); if (!option.Value) { return; } var severity = option.Notification.Severity; if (severity == ReportDiagnostic.Suppress) { return; } var fieldReferenceOperation = (IFieldReferenceOperation)context.Operation; var field = fieldReferenceOperation.Field; if (field.ContainingType.IsTupleType) { if (field.CorrespondingTupleField?.Equals(field) == true) { var namedField = GetNamedField(field.ContainingType, field, context.CancellationToken); if (namedField != null) { var memberAccessSyntax = fieldReferenceOperation.Syntax; var nameNode = memberAccessSyntax.ChildNodesAndTokens().Reverse().FirstOrDefault(); if (nameNode != null) { var properties = ImmutableDictionary <string, string> .Empty.Add( nameof(ElementName), namedField.Name); context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, nameNode.GetLocation(), severity, additionalLocations: null, properties)); } } } } }
private void AnalyzeOperation(OperationAnalysisContext context, IOperation operation, IOperation?instanceOperation) { // this is a static reference so we don't care if it's qualified if (instanceOperation == null) { return; } // if we're not referencing `this.` or `Me.` (e.g., a parameter, local, etc.) if (instanceOperation.Kind != OperationKind.InstanceReference) { return; } // We shouldn't qualify if it is inside a property pattern if (context.Operation.Parent?.Kind == OperationKind.PropertySubpattern) { return; } // Initializer lists are IInvocationOperation which if passed to GetApplicableOptionFromSymbolKind // will incorrectly fetch the options for method call. // We still want to handle InstanceReferenceKind.ContainingTypeInstance if ((instanceOperation as IInstanceReferenceOperation)?.ReferenceKind == InstanceReferenceKind.ImplicitReceiver) { return; } // If we can't be qualified (e.g., because we're already qualified with `base.`), we're done. if (!CanMemberAccessBeQualified(context.ContainingSymbol, instanceOperation.Syntax)) { return; } // if we can't find a member then we can't do anything. Also, we shouldn't qualify // accesses to static members. if (IsStaticMemberOrIsLocalFunction(operation)) { return; } if (instanceOperation.Syntax is not TSimpleNameSyntax simpleName) { return; } var applicableOption = QualifyMembersHelpers.GetApplicableOptionFromSymbolKind(operation); var optionValue = context.GetOption(applicableOption, context.Operation.Syntax.Language); var shouldOptionBePresent = optionValue.Value; var severity = optionValue.Notification.Severity; if (!shouldOptionBePresent || severity == ReportDiagnostic.Suppress) { return; } if (!IsAlreadyQualifiedMemberAccess(simpleName)) { context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, GetLocation(operation), severity, additionalLocations: null, properties: null)); } }
private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol expressionTypeOpt) { var syntaxTree = context.Operation.Syntax.SyntaxTree; if (!IsSupported(syntaxTree.Options)) { return; } var cancellationToken = context.CancellationToken; var throwOperation = (IThrowOperation)context.Operation; var throwStatementSyntax = throwOperation.Syntax; var semanticModel = context.Operation.SemanticModel; var ifOperation = GetContainingIfOperation( semanticModel, throwOperation, cancellationToken); // This throw statement isn't parented by an if-statement. Nothing to // do here. if (ifOperation == null) { return; } if (ifOperation.WhenFalse != null) { // Can't offer this if the 'if-statement' has an 'else-clause'. return; } var option = context.GetOption(_preferThrowExpressionOption); if (!option.Value) { return; } if (IsInExpressionTree(semanticModel, throwStatementSyntax, expressionTypeOpt, cancellationToken)) { return; } if (!(ifOperation.Parent is IBlockOperation containingBlock)) { return; } if (!TryDecomposeIfCondition(ifOperation, out var localOrParameter)) { return; } if (!TryFindAssignmentExpression(containingBlock, ifOperation, localOrParameter, out var expressionStatement, out var assignmentExpression)) { return; } if (!localOrParameter.GetSymbolType().CanAddNullCheck()) { return; } // We found an assignment using this local/parameter. Now, just make sure there // were no intervening accesses between the check and the assignment. if (ValueIsAccessed( semanticModel, ifOperation, containingBlock, localOrParameter, expressionStatement, assignmentExpression)) { return; } // Ok, there were no intervening writes or accesses. This check+assignment can be simplified. var allLocations = ImmutableArray.Create( ifOperation.Syntax.GetLocation(), throwOperation.Exception.Syntax.GetLocation(), assignmentExpression.Value.Syntax.GetLocation()); context.ReportDiagnostic( DiagnosticHelper.Create(Descriptor, throwStatementSyntax.GetLocation(), option.Notification.Severity, additionalLocations: allLocations, properties: null)); }