public static Diagnostic Create( string id, string category, LocalizableString message, DiagnosticSeverity severity, DiagnosticSeverity defaultSeverity, bool isEnabledByDefault, int warningLevel, bool isSuppressed, LocalizableString?title = null, LocalizableString?description = null, string?helpLink = null, Location?location = null, IEnumerable <Location>?additionalLocations = null, IEnumerable <string>?customTags = null, ImmutableDictionary <string, string>?properties = null) { if (id == null) { throw new ArgumentNullException(nameof(id)); } if (category == null) { throw new ArgumentNullException(nameof(category)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } return(SimpleDiagnostic.Create(id, title ?? string.Empty, category, message, description ?? string.Empty, helpLink ?? string.Empty, severity, defaultSeverity, isEnabledByDefault, warningLevel, location ?? Location.None, additionalLocations, customTags, properties, isSuppressed)); }
/// <summary> /// Creates a <see cref="Diagnostic"/> instance which is localizable. /// </summary> /// <param name="id">An identifier for the diagnostic. For diagnostics generated by the compiler, this will be a numeric code with a prefix such as "CS1001".</param> /// <param name="category">The category of the diagnostic. For diagnostics generated by the compiler, the category will be "Compiler".</param> /// <param name="message">The diagnostic message text.</param> /// <param name="severity">The diagnostic's effective severity.</param> /// <param name="defaultSeverity">The diagnostic's default severity.</param> /// <param name="isEnabledByDefault">True if the diagnostic is enabled by default</param> /// <param name="warningLevel">The warning level, between 1 and 4 if severity is <see cref="DiagnosticSeverity.Warning"/>; otherwise 0.</param> /// <param name="title">An optional short localizable title describing the diagnostic.</param> /// <param name="description">An optional longer localizable description for the diagnostic.</param> /// <param name="helpLink">An optional hyperlink that provides more detailed information regarding the diagnostic.</param> /// <param name="location">An optional primary location of the diagnostic. If null, <see cref="Location"/> will return <see cref="Location.None"/>.</param> /// <param name="additionalLocations"> /// An optional set of additional locations related to the diagnostic. /// Typically, these are locations of other items referenced in the message. /// If null, <see cref="AdditionalLocations"/> will return an empty list. /// </param> /// <param name="customTags"> /// An optional set of custom tags for the diagnostic. See <see cref="WellKnownDiagnosticTags"/> for some well known tags. /// If null, <see cref="CustomTags"/> will return an empty list. /// </param> /// <param name="properties"> /// An optional set of name-value pairs by means of which the analyzer that creates the diagnostic /// can convey more detailed information to the fixer. If null, <see cref="Properties"/> will return /// <see cref="ImmutableDictionary{TKey, TValue}.Empty"/>. /// </param> /// <returns>The <see cref="Diagnostic"/> instance.</returns> public static Diagnostic Create( string id, string category, LocalizableString message, DiagnosticSeverity severity, DiagnosticSeverity defaultSeverity, bool isEnabledByDefault, int warningLevel, LocalizableString?title = null, LocalizableString?description = null, string?helpLink = null, Location?location = null, IEnumerable <Location>?additionalLocations = null, IEnumerable <string>?customTags = null, ImmutableDictionary <string, string?>?properties = null ) { return(Create( id, category, message, severity, defaultSeverity, isEnabledByDefault, warningLevel, false, title, description, helpLink, location, additionalLocations, customTags, properties )); }
internal DiagnosticDescriptor( string id, LocalizableString title, LocalizableString messageFormat, string category, DiagnosticSeverity defaultSeverity, bool isEnabledByDefault, LocalizableString?description, string?helpLinkUri, ImmutableArray <string> customTags) { if (string.IsNullOrWhiteSpace(id)) { throw new ArgumentException("DiagnosticId cannot be null or whitespace", nameof(id)); } Id = id; Title = title ?? throw new ArgumentNullException(nameof(title)); Category = category ?? throw new ArgumentNullException(nameof(category)); MessageFormat = messageFormat ?? throw new ArgumentNullException(nameof(messageFormat)); DefaultSeverity = defaultSeverity; IsEnabledByDefault = isEnabledByDefault; Description = description ?? string.Empty; HelpLinkUri = helpLinkUri ?? string.Empty; CustomTags = customTags; }
public static DiagnosticDescriptor Create( string id, LocalizableString title, LocalizableString messageFormat, string category, RuleLevel ruleLevel, LocalizableString?description, bool isPortedFxCopRule, bool isDataflowRule, bool isEnabledByDefaultInFxCopAnalyzers = true, params string[] additionalCustomTags) { // PERF: Ensure that all DFA rules are disabled by default in NetAnalyzers package. Debug.Assert(!isDataflowRule || ruleLevel == RuleLevel.Disabled || ruleLevel == RuleLevel.CandidateForRemoval); var(defaultSeverity, enabledByDefault) = GetDefaultSeverityAndEnabledByDefault(ruleLevel, isEnabledByDefaultInFxCopAnalyzers); #pragma warning disable CA1308 // Normalize strings to uppercase - use lower case ID in help link var helpLink = $"https://docs.microsoft.com/visualstudio/code-quality/{id.ToLowerInvariant()}"; #pragma warning restore CA1308 // Normalize strings to uppercase var customTags = isPortedFxCopRule ? (isDataflowRule ? FxCopWellKnownDiagnosticTags.PortedFxCopDataflowRule : FxCopWellKnownDiagnosticTags.PortedFxCopRule) : (isDataflowRule ? WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry : WellKnownDiagnosticTagsExtensions.Telemetry); if (additionalCustomTags.Length > 0) { customTags = customTags.Concat(additionalCustomTags).ToArray(); } #pragma warning disable RS0030 // The symbol 'DiagnosticDescriptor.DiagnosticDescriptor.#ctor' is banned in this project: Use 'DiagnosticDescriptorHelper.Create' instead return(new DiagnosticDescriptor(id, title, messageFormat, category, defaultSeverity, enabledByDefault, description, helpLink, customTags));
public static DiagnosticDescriptor Create( string id, LocalizableString title, LocalizableString messageFormat, string category, RuleLevel ruleLevel, LocalizableString?description, bool isPortedFxCopRule, bool isDataflowRule, bool isEnabledByDefaultInFxCopAnalyzers = true, bool isEnabledByDefaultInAggressiveMode = true, params string[] additionalCustomTags) { // PERF: Ensure that all DFA rules are disabled by default in NetAnalyzers package. Debug.Assert(!isDataflowRule || ruleLevel == RuleLevel.Disabled || ruleLevel == RuleLevel.CandidateForRemoval); // Ensure 'isEnabledByDefaultInAggressiveMode' is not false for enabled rules in default mode Debug.Assert(isEnabledByDefaultInAggressiveMode || ruleLevel == RuleLevel.Disabled || ruleLevel == RuleLevel.CandidateForRemoval); var(defaultSeverity, enabledByDefault) = GetDefaultSeverityAndEnabledByDefault(ruleLevel, isEnabledByDefaultInFxCopAnalyzers); #pragma warning disable CA1308 // Normalize strings to uppercase - use lower case ID in help link var helpLink = $"https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/{id.ToLowerInvariant()}"; #pragma warning restore CA1308 // Normalize strings to uppercase var customTags = GetDefaultCustomTags(isPortedFxCopRule, isDataflowRule, isEnabledByDefaultInAggressiveMode); if (additionalCustomTags.Length > 0) { customTags = customTags.Concat(additionalCustomTags).ToArray(); } #pragma warning disable RS0030 // The symbol 'DiagnosticDescriptor.DiagnosticDescriptor.#ctor' is banned in this project: Use 'DiagnosticDescriptorHelper.Create' instead return(new DiagnosticDescriptor(id, title, messageFormat, category, defaultSeverity, enabledByDefault, description, helpLink, customTags));
private static void CheckArgument( ISymbol targetSymbol, IObjectCreationOperation creation, IParameterSymbol parameter, string stringArgument, OperationAnalysisContext context) { bool matchesParameter = MatchesParameter(targetSymbol, creation, stringArgument); LocalizableString?format = null; if (IsMessage(parameter) && matchesParameter) { format = s_localizableMessageIncorrectMessage; } else if (IsParameterName(parameter) && !matchesParameter) { // Allow argument exceptions in accessors to use the associated property symbol name. if (MatchesAssociatedSymbol(targetSymbol, stringArgument)) { return; } format = s_localizableMessageIncorrectParameterName; } if (format != null) { ReportDiagnostic(context, format, targetSymbol.Name, stringArgument, parameter.Name, creation.Type.Name); } }
protected static DiagnosticDescriptor CreateDescriptorWithId( string id, LocalizableString title, LocalizableString messageFormat, bool isUnnecessary = false, bool isConfigurable = true, LocalizableString?description = null, params string[] customTags) => new(
protected static DiagnosticDescriptor CreateDescriptorWithId( string id, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString messageFormat, bool isUnnecessary = false, bool isConfigurable = true, LocalizableString?description = null) => new(
protected static DiagnosticDescriptor CreateDescriptorWithId( string id, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString?messageFormat = null, bool isUnnecessary = false, bool isConfigurable = true, LocalizableString?description = null) #pragma warning disable RS0030 // Do not used banned APIs => new(
protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( string diagnosticId, IPerLanguageOption?option, LocalizableString title, LocalizableString?messageFormat = null, bool configurable = true) : base(diagnosticId, title, messageFormat, configurable) { AddDiagnosticIdToOptionMapping(diagnosticId, option); }
protected static DiagnosticDescriptor CreateDescriptor( string id, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString messageFormat, bool isUnnecessary, bool isEnabledByDefault = true, bool isConfigurable = true, LocalizableString?description = null) #pragma warning disable RS0030 // Do not use banned APIs => new(
/// <summary> /// Constructor for a code style analyzer with a single diagnostic descriptor and /// unique <see cref="IPerLanguageOption"/> code style option. /// </summary> /// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param> /// <param name="enforceOnBuild">Build enforcement recommendation for this analyzer</param> /// <param name="option"> /// Per-language option that can be used to configure the given <paramref name="diagnosticId"/>. /// <see langword="null"/>, if there is no such unique option. /// </param> /// <param name="title">Title for the diagnostic descriptor</param> /// <param name="messageFormat"> /// Message for the diagnostic descriptor. /// <see langword="null"/> if the message is identical to the title. /// </param> /// <param name="isUnnecessary"><see langword="true"/> if the diagnostic is reported on unnecessary code; otherwise, <see langword="false"/>.</param> /// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param> protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( string diagnosticId, EnforceOnBuild enforceOnBuild, IPerLanguageOption?option, LocalizableString title, LocalizableString?messageFormat = null, bool isUnnecessary = false, bool configurable = true) : this(diagnosticId, enforceOnBuild, title, messageFormat, isUnnecessary, configurable) { AddDiagnosticIdToOptionMapping(diagnosticId, option); }
/// <summary> /// Constructor for an unnecessary code style analyzer with a single diagnostic descriptor and /// unique <see cref="IPerLanguageValuedOption"/> code style option. /// </summary> /// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param> /// <param name="enforceOnBuild">Build enforcement recommendation for this analyzer</param> /// <param name="option"> /// Per-language option that can be used to configure the given <paramref name="diagnosticId"/>. /// <see langword="null"/>, if there is no such unique option. /// </param> /// <param name="fadingOption"> /// Per-language fading option that can be used to configure if the diagnostic should be faded in the IDE or not. /// <see langword="null"/>, if there is no such unique fading option. /// </param> /// <param name="title">Title for the diagnostic descriptor</param> /// <param name="messageFormat"> /// Message for the diagnostic descriptor. /// <see langword="null"/> if the message is identical to the title. /// </param> /// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param> protected AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer( string diagnosticId, EnforceOnBuild enforceOnBuild, IPerLanguageValuedOption?option, PerLanguageOption2 <bool>?fadingOption, LocalizableString title, LocalizableString?messageFormat = null, bool configurable = true) : base(diagnosticId, enforceOnBuild, option, title, messageFormat, isUnnecessary: true, configurable) { AddDiagnosticIdToFadingOptionMapping(diagnosticId, fadingOption); }
protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( string diagnosticId, ImmutableHashSet <IPerLanguageOption> options, LocalizableString title, LocalizableString?messageFormat = null, bool configurable = true) : base(diagnosticId, title, messageFormat, configurable) { RoslynDebug.Assert(options != null); Debug.Assert(options.Count > 1); AddDiagnosticIdToOptionMapping(diagnosticId, options); }
/// <summary> /// Constructor for a code style analyzer with a single diagnostic descriptor and /// unique <see cref="ILanguageSpecificOption"/> code style option for the given language. /// </summary> /// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param> /// <param name="option"> /// Language specific option that can be used to configure the given <paramref name="diagnosticId"/>. /// <see langword="null"/>, if there is no such unique option. /// </param> /// <param name="language">Language for the given language-specific <paramref name="option"/>.</param> /// <param name="title">Title for the diagnostic descriptor</param> /// <param name="messageFormat"> /// Message for the diagnostic descriptor. /// <see langword="null"/> if the message is identical to the title. /// </param> /// <param name="isUnnecessary"><see langword="true"/> if the diagnostic is reported on unnecessary code; otherwise, <see langword="false"/>.</param> /// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param> protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( string diagnosticId, ILanguageSpecificOption?option, string language, LocalizableString title, LocalizableString?messageFormat = null, bool isUnnecessary = false, bool configurable = true) : base(diagnosticId, title, messageFormat, isUnnecessary, configurable) { AddDiagnosticIdToOptionMapping(diagnosticId, option, language); }
protected AbstractCodeStyleDiagnosticAnalyzer( string descriptorId, LocalizableString title, LocalizableString?messageFormat = null, bool isUnnecessary = false, bool configurable = true) { DescriptorId = descriptorId; _localizableTitle = title; _localizableMessageFormat = messageFormat ?? title; Descriptor = CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, isUnnecessary: isUnnecessary, isConfigurable: configurable); SupportedDiagnostics = ImmutableArray.Create(Descriptor); }
/// <summary> /// Create a DiagnosticDescriptor, which provides description about a <see cref="Diagnostic"/>. /// </summary> /// <param name="id">A unique identifier for the diagnostic. For example, code analysis diagnostic ID "CA1001".</param> /// <param name="title">A short localizable title describing the diagnostic. For example, for CA1001: "Types that own disposable fields should be disposable".</param> /// <param name="messageFormat">A localizable format message string, which can be passed as the first argument to <see cref="string.Format(string, object[])"/> when creating the diagnostic message with this descriptor. /// For example, for CA1001: "Implement IDisposable on '{0}' because it creates members of the following IDisposable types: '{1}'."</param> /// <param name="category">The category of the diagnostic (like Design, Naming etc.). For example, for CA1001: "Microsoft.Design".</param> /// <param name="defaultSeverity">Default severity of the diagnostic.</param> /// <param name="isEnabledByDefault">True if the diagnostic is enabled by default.</param> /// <param name="description">An optional longer localizable description of the diagnostic.</param> /// <param name="helpLinkUri">An optional hyperlink that provides a more detailed description regarding the diagnostic.</param> /// <param name="customTags">Optional custom tags for the diagnostic. See <see cref="WellKnownDiagnosticTags"/> for some well known tags.</param> /// <remarks>Example descriptor for rule CA1001: /// internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId, /// new LocalizableResourceString(nameof(FxCopRulesResources.TypesThatOwnDisposableFieldsShouldBeDisposable), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)), /// new LocalizableResourceString(nameof(FxCopRulesResources.TypeOwnsDisposableFieldButIsNotDisposable), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)), /// FxCopDiagnosticCategory.Design, /// DiagnosticSeverity.Warning, /// isEnabledByDefault: true, /// helpLinkUri: "http://msdn.microsoft.com/library/ms182172.aspx", /// customTags: DiagnosticCustomTags.Microsoft); /// </remarks> public DiagnosticDescriptor( string id, LocalizableString title, LocalizableString messageFormat, string category, DiagnosticSeverity defaultSeverity, bool isEnabledByDefault, LocalizableString?description = null, string?helpLinkUri = null, params string[] customTags) : this(id, title, messageFormat, category, defaultSeverity, isEnabledByDefault, description, helpLinkUri, customTags.AsImmutableOrEmpty()) { }
/// <summary> /// Constructor for a code style analyzer with a single diagnostic descriptor and /// two or more <see cref="IPerLanguageValuedOption "/> code style options. /// </summary> /// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param> /// <param name="enforceOnBuild">Build enforcement recommendation for this analyzer</param> /// <param name="options"> /// Set of two or more per-language options that can be used to configure the diagnostic severity of the given diagnosticId. /// </param> /// <param name="title">Title for the diagnostic descriptor</param> /// <param name="messageFormat"> /// Message for the diagnostic descriptor. /// Null if the message is identical to the title. /// </param> /// <param name="isUnnecessary"><see langword="true"/> if the diagnostic is reported on unnecessary code; otherwise, <see langword="false"/>.</param> /// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param> protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( string diagnosticId, EnforceOnBuild enforceOnBuild, ImmutableHashSet <IPerLanguageValuedOption> options, LocalizableString title, LocalizableString?messageFormat = null, bool isUnnecessary = false, bool configurable = true) : this(diagnosticId, enforceOnBuild, title, messageFormat, isUnnecessary, configurable) { RoslynDebug.Assert(options != null); Debug.Assert(options.Count > 1); AddDiagnosticIdToOptionMapping(diagnosticId, options); }
private AbstractBuiltInCodeStyleDiagnosticAnalyzer( string descriptorId, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString?messageFormat, bool isUnnecessary, bool configurable) { // 'isUnnecessary' should be true only for sub-types of AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer. Debug.Assert(!isUnnecessary || this is AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer); Descriptor = CreateDescriptorWithId(descriptorId, enforceOnBuild, title, messageFormat ?? title, isUnnecessary: isUnnecessary, isConfigurable: configurable); SupportedDiagnostics = ImmutableArray.Create(Descriptor); }
protected static DiagnosticDescriptor CreateDescriptorWithId( string id, LocalizableString title, LocalizableString messageFormat, bool isUnnecessary = false, bool isConfigurable = true, LocalizableString?description = null, params string[] customTags) => new DiagnosticDescriptor( id, title, messageFormat, DiagnosticCategory.Style, DiagnosticSeverity.Hidden, isEnabledByDefault: true, description: description, customTags: DiagnosticCustomTags.Create(isUnnecessary, isConfigurable, customTags));
private AbstractBuiltInCodeStyleDiagnosticAnalyzer( string descriptorId, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString?messageFormat, bool isUnnecessary, bool configurable) { DescriptorId = descriptorId; _localizableTitle = title; _localizableMessageFormat = messageFormat ?? title; Descriptor = CreateDescriptorWithId(DescriptorId, enforceOnBuild, _localizableTitle, _localizableMessageFormat, isUnnecessary: isUnnecessary, isConfigurable: configurable); SupportedDiagnostics = ImmutableArray.Create(Descriptor); }
protected AbstractCodeStyleDiagnosticAnalyzer( string descriptorId, LocalizableString title, LocalizableString?messageFormat = null, bool configurable = true) { DescriptorId = descriptorId; _localizableTitle = title; _localizableMessageFormat = messageFormat ?? title; Descriptor = CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, isConfigurable: configurable); UnnecessaryWithSuggestionDescriptor = CreateUnnecessaryDescriptor(DescriptorId, configurable); UnnecessaryWithoutSuggestionDescriptor = CreateUnnecessaryDescriptor(descriptorId + "WithoutSuggestion", configurable); SupportedDiagnostics = ImmutableArray.Create( Descriptor, UnnecessaryWithoutSuggestionDescriptor, UnnecessaryWithSuggestionDescriptor); }
private DiagnosticResult( ImmutableArray <DiagnosticLocation> spans, bool suppressMessage, string?message, DiagnosticSeverity severity, string id, LocalizableString?messageFormat, object?[]?messageArguments) { _spans = spans; _suppressMessage = suppressMessage; _message = message; Severity = severity; Id = id; MessageFormat = messageFormat; MessageArguments = messageArguments; }
internal DiagnosticDescriptor( string id, LocalizableString title, LocalizableString messageFormat, string category, DiagnosticSeverity defaultSeverity, bool isEnabledByDefault, LocalizableString?description, string?helpLinkUri, ImmutableArray <string> customTags ) { if (string.IsNullOrWhiteSpace(id)) { throw new ArgumentException( CodeAnalysisResources.DiagnosticIdCantBeNullOrWhitespace, nameof(id) ); } if (messageFormat == null) { throw new ArgumentNullException(nameof(messageFormat)); } if (category == null) { throw new ArgumentNullException(nameof(category)); } if (title == null) { throw new ArgumentNullException(nameof(title)); } this.Id = id; this.Title = title; this.Category = category; this.MessageFormat = messageFormat; this.DefaultSeverity = defaultSeverity; this.IsEnabledByDefault = isEnabledByDefault; this.Description = description ?? string.Empty; this.HelpLinkUri = helpLinkUri ?? string.Empty; this.CustomTags = customTags; }
private AbstractBuiltInCodeStyleDiagnosticAnalyzer( string descriptorId, EnforceOnBuild enforceOnBuild, LocalizableString title, LocalizableString?messageFormat, bool isUnnecessary, bool configurable) { // 'isUnnecessary' should be true only for sub-types of AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer. // NOTE: AbstractParenthesesDiagnosticAnalyzer is an exception as it is a common sub-type for // AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer (unnecessary code analyzer) and // AbstractAddRequiredParenthesesDiagnosticAnalyzer (non-unnecessary code analyzer). Debug.Assert(!isUnnecessary || this is AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer || this is AbstractParenthesesDiagnosticAnalyzer); Descriptor = CreateDescriptorWithId(descriptorId, enforceOnBuild, title, messageFormat ?? title, isUnnecessary: isUnnecessary, isConfigurable: configurable); SupportedDiagnostics = ImmutableArray.Create(Descriptor); }