private static void AnalyzeIfEnabled <TContext>( TCodeStyleProvider provider, TContext context, Action <TContext, CodeStyleOption <TOptionKind> > analyze, AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken) { var optionSet = options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return; } var optionValue = optionSet.GetOption(provider._option); var severity = GetOptionSeverity(optionValue); switch (severity) { case ReportDiagnostic.Error: case ReportDiagnostic.Warn: case ReportDiagnostic.Info: break; default: // don't analyze if it's any other value. return; } analyze(context, optionValue); }
private bool TryGetOptions( SyntaxTree syntaxTree, string language, AnalyzerOptions analyzerOptions, CancellationToken cancellationToken, out Options options) { options = null; var optionSet = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return(false); } var unusedParametersOption = optionSet.GetOption(CodeStyleOptions.UnusedParameters, language); var(unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity) = GetPreferenceAndSeverity(UnusedValueExpressionStatementOption); var(unusedValueAssignmentPreference, unusedValueAssignmentSeverity) = GetPreferenceAndSeverity(UnusedValueAssignmentOption); if (unusedParametersOption.Notification.Severity == ReportDiagnostic.Suppress && unusedValueExpressionStatementSeverity == ReportDiagnostic.Suppress && unusedValueAssignmentSeverity == ReportDiagnostic.Suppress) { return(false); } options = new Options(unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity, unusedValueAssignmentPreference, unusedValueAssignmentSeverity, unusedParametersOption.Value, unusedParametersOption.Notification.Severity); return(true); // Local functions. (UnusedValuePreference preference, ReportDiagnostic severity) GetPreferenceAndSeverity( Option <CodeStyleOption <UnusedValuePreference> > codeStyleOption) { var option = optionSet.GetOption(codeStyleOption); var preferenceOpt = option?.Value; if (preferenceOpt == null || option.Notification.Severity == ReportDiagnostic.Suppress) { // Prefer does not matter as the severity is suppressed - we will never report this diagnostic. return(default(UnusedValuePreference), ReportDiagnostic.Suppress); } // If language or language version does not support discard, fall back to prefer unused local variable. if (preferenceOpt.Value == UnusedValuePreference.DiscardVariable && !SupportsDiscard(syntaxTree)) { preferenceOpt = UnusedValuePreference.UnusedLocalVariable; } return(preferenceOpt.Value, option.Notification.Severity); } }
private static async ValueTask <NamingStylePreferences> GetNamingStylePreferencesAsync( Compilation compilation, ISymbol symbol, AnalyzerOptions options, CancellationToken cancellationToken) { var sourceTree = symbol.Locations.FirstOrDefault()?.SourceTree; if (sourceTree == null) { return(null); } var optionSet = await options.GetDocumentOptionSetAsync(sourceTree, cancellationToken).ConfigureAwait(false); return(optionSet?.GetOption(SimplificationOptions.NamingPreferences, compilation.Language)); }
private void ReportUnusedParameterDiagnostic( IParameterSymbol parameter, bool hasReference, Action <Diagnostic> reportDiagnostic, AnalyzerOptions analyzerOptions, CancellationToken cancellationToken) { if (!IsUnusedParameterCandidate(parameter)) { return; } var location = parameter.Locations[0]; var optionSet = analyzerOptions.GetDocumentOptionSetAsync(location.SourceTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return; } var option = optionSet.GetOption(CodeStyleOptions.UnusedParameters, parameter.Language); if (option.Notification.Severity == ReportDiagnostic.Suppress || !ShouldReportUnusedParameters(parameter.ContainingSymbol, option.Value, option.Notification.Severity)) { return; } var message = GetMessageForUnusedParameterDiagnostic( parameter.Name, hasReference, isPublicApiParameter: parameter.ContainingSymbol.HasPublicResultantVisibility(), isLocalFunctionParameter: parameter.ContainingSymbol.IsLocalFunction()); var diagnostic = DiagnosticHelper.CreateWithMessage(s_unusedParameterRule, location, option.Notification.Severity, additionalLocations: null, properties: null, message); reportDiagnostic(diagnostic); }
protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken) { diagnostic = default; var syntaxTree = node.SyntaxTree; var optionSet = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return(false); } if (!CanSimplifyTypeNameExpressionCore( model, node, optionSet, out var issueSpan, out var diagnosticId, out var inDeclaration, cancellationToken)) { return(false); } if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken)) { return(false); } PerLanguageOption <CodeStyleOption <bool> > option; DiagnosticDescriptor descriptor; ReportDiagnostic severity; switch (diagnosticId) { case IDEDiagnosticIds.SimplifyNamesDiagnosticId: descriptor = s_descriptorSimplifyNames; severity = descriptor.DefaultSeverity.ToReportDiagnostic(); break; case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId: descriptor = s_descriptorSimplifyMemberAccess; severity = descriptor.DefaultSeverity.ToReportDiagnostic(); break; case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId: option = inDeclaration ? CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration : CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess; descriptor = s_descriptorPreferBuiltinOrFrameworkType; var optionValue = optionSet.GetOption(option, GetLanguageName()); severity = optionValue.Notification.Severity; break; default: throw ExceptionUtilities.UnexpectedValue(diagnosticId); } if (descriptor == null) { return(false); } var tree = model.SyntaxTree; var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder["OptionName"] = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one builder["OptionLanguage"] = model.Language; diagnostic = DiagnosticHelper.Create(descriptor, tree.GetLocation(issueSpan), severity, additionalLocations: null, builder.ToImmutable()); return(true); }
protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken) { diagnostic = default; var syntaxTree = node.SyntaxTree; var optionSet = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return(false); } if (!CanSimplifyTypeNameExpressionCore( model, node, optionSet, out var issueSpan, out var diagnosticId, out var inDeclaration, cancellationToken)) { return(false); } if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken)) { return(false); } PerLanguageOption <CodeStyleOption <bool> > option; DiagnosticDescriptor descriptor; ReportDiagnostic severity; switch (diagnosticId) { case IDEDiagnosticIds.SimplifyNamesDiagnosticId: descriptor = s_descriptorSimplifyNames; severity = descriptor.DefaultSeverity.ToReportDiagnostic(); break; case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId: descriptor = s_descriptorSimplifyMemberAccess; severity = descriptor.DefaultSeverity.ToReportDiagnostic(); break; case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId: option = inDeclaration ? CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration : CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess; descriptor = s_descriptorPreferBuiltinOrFrameworkType; var optionValue = optionSet.GetOption(option, GetLanguageName()); severity = optionValue.Notification.Severity; break; default: throw ExceptionUtilities.UnexpectedValue(diagnosticId); } if (descriptor == null) { return(false); } var tree = model.SyntaxTree; var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder["OptionName"] = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one builder["OptionLanguage"] = model.Language; diagnostic = DiagnosticHelper.Create(descriptor, tree.GetLocation(issueSpan), severity, additionalLocations: null, builder.ToImmutable()); #if LOG var sourceText = tree.GetText(cancellationToken); sourceText.GetLineAndOffset(issueSpan.Start, out var startLineNumber, out var startOffset); sourceText.GetLineAndOffset(issueSpan.End, out var endLineNumber, out var endOffset); var logLine = tree.FilePath + "," + startLineNumber + "\t" + diagnosticId + "\t" + inDeclaration + "\t"; var leading = sourceText.ToString(TextSpan.FromBounds( sourceText.Lines[startLineNumber].Start, issueSpan.Start)); var mid = sourceText.ToString(issueSpan); var trailing = sourceText.ToString(TextSpan.FromBounds( issueSpan.End, sourceText.Lines[endLineNumber].End)); var contents = leading + "[|" + s_newlinePattern.Replace(mid, " ") + "|]" + trailing; logLine += contents + "\r\n"; lock (_logGate) { File.AppendAllText(_logFile, logLine); } #endif return(true); }
protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken) { diagnostic = default(Diagnostic); var syntaxTree = node.SyntaxTree; var optionSet = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return(false); } if (!CanSimplifyTypeNameExpressionCore(model, node, optionSet, out var issueSpan, out string diagnosticId, cancellationToken)) { return(false); } if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken)) { return(false); } PerLanguageOption <CodeStyleOption <bool> > option; DiagnosticDescriptor descriptor; switch (diagnosticId) { case IDEDiagnosticIds.SimplifyNamesDiagnosticId: descriptor = s_descriptorSimplifyNames; break; case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId: descriptor = s_descriptorSimplifyMemberAccess; break; case IDEDiagnosticIds.RemoveQualificationDiagnosticId: descriptor = GetRemoveQualificationDiagnosticDescriptor(model, node, optionSet, cancellationToken); break; case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId: option = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration; descriptor = GetApplicablePredefinedTypeDiagnosticDescriptor( IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId, option, optionSet); break; case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId: option = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess; descriptor = GetApplicablePredefinedTypeDiagnosticDescriptor( IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId, option, optionSet); break; default: throw ExceptionUtilities.Unreachable; } if (descriptor == null) { return(false); } var tree = model.SyntaxTree; var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder["OptionName"] = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one builder["OptionLanguage"] = model.Language; diagnostic = Diagnostic.Create(descriptor, tree.GetLocation(issueSpan), builder.ToImmutable()); return(true); }