diff --git a/README.md b/README.md index 70d68841b..f5e294f84 100755 --- a/README.md +++ b/README.md @@ -19,218 +19,218 @@ If you are already using other analyzers, you can check [which rules are duplica -|Id|Category|Description|Severity|Is enabled|Code fix| -|--|--------|-----------|:------:|:--------:|:------:| -|[MA0001](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md)|Usage|StringComparison is missing|ℹ️|✔️|✔️| -|[MA0002](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0002.md)|Usage|IEqualityComparer\ or IComparer\ is missing|⚠️|✔️|✔️| -|[MA0003](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0003.md)|Style|Add parameter name to improve readability|ℹ️|✔️|✔️| -|[MA0004](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md)|Usage|Use Task.ConfigureAwait|⚠️|✔️|✔️| -|[MA0005](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0005.md)|Performance|Use Array.Empty\()|⚠️|✔️|✔️| -|[MA0006](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0006.md)|Usage|Use String.Equals instead of equality operator|⚠️|✔️|✔️| -|[MA0007](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0007.md)|Style|Add a comma after the last value|ℹ️|✔️|✔️| -|[MA0008](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0008.md)|Performance|Add StructLayoutAttribute|⚠️|✔️|✔️| -|[MA0009](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md)|Security|Add regex evaluation timeout|⚠️|✔️|❌| -|[MA0010](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0010.md)|Design|Mark attributes with AttributeUsageAttribute|⚠️|✔️|✔️| -|[MA0011](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md)|Usage|IFormatProvider is missing|⚠️|✔️|✔️| -|[MA0012](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0012.md)|Design|Do not raise reserved exception type|⚠️|✔️|❌| -|[MA0013](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0013.md)|Design|Types should not extend System.ApplicationException|⚠️|✔️|❌| -|[MA0014](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0014.md)|Design|Do not raise System.ApplicationException type|⚠️|✔️|❌| -|[MA0015](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md)|Usage|Specify the parameter name in ArgumentException|⚠️|✔️|❌| -|[MA0016](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0016.md)|Design|Prefer using collection abstraction instead of implementation|⚠️|✔️|❌| -|[MA0017](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0017.md)|Design|Abstract types should not have public or internal constructors|⚠️|✔️|✔️| -|[MA0018](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0018.md)|Design|Do not declare static members on generic types (deprecated; use CA1000 instead)|ℹ️|✔️|❌| -|[MA0019](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0019.md)|Usage|Use EventArgs.Empty|⚠️|✔️|✔️| -|[MA0020](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0020.md)|Performance|Use direct methods instead of LINQ methods|ℹ️|✔️|✔️| -|[MA0021](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0021.md)|Usage|Use StringComparer.GetHashCode instead of string.GetHashCode|⚠️|✔️|✔️| -|[MA0022](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0022.md)|Design|Return Task.FromResult instead of returning null|⚠️|✔️|✔️| -|[MA0023](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0023.md)|Performance|Add RegexOptions.ExplicitCapture|⚠️|✔️|✔️| -|[MA0024](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0024.md)|Usage|Use an explicit StringComparer when possible|⚠️|✔️|✔️| -|[MA0025](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0025.md)|Design|Implement the functionality instead of throwing NotImplementedException|⚠️|✔️|❌| -|[MA0026](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)|Design|Fix TODO comment|⚠️|✔️|❌| -|[MA0027](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0027.md)|Usage|Prefer rethrowing an exception implicitly|⚠️|✔️|✔️| -|[MA0028](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0028.md)|Performance|Optimize StringBuilder usage|ℹ️|✔️|✔️| -|[MA0029](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0029.md)|Performance|Combine LINQ methods|ℹ️|✔️|✔️| -|[MA0030](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0030.md)|Performance|Remove useless OrderBy call|⚠️|✔️|✔️| -|[MA0031](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md)|Performance|Optimize Enumerable.Count() usage|ℹ️|✔️|✔️| -|[MA0032](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0032.md)|Usage|Use an overload with a CancellationToken argument, even when no token is available in scope|ℹ️|❌|❌| -|[MA0033](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0033.md)|Design|Do not tag instance fields with ThreadStaticAttribute|⚠️|✔️|❌| -|[MA0035](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0035.md)|Usage|Do not use dangerous threading methods|⚠️|✔️|❌| -|[MA0036](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0036.md)|Design|Make class static|ℹ️|✔️|✔️| -|[MA0037](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0037.md)|Usage|Remove empty statement|❌|✔️|✔️| -|[MA0038](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0038.md)|Design|Make method static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️| -|[MA0039](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0039.md)|Security|Do not write your own certificate validation method|❌|✔️|❌| -|[MA0040](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0040.md)|Usage|Forward the CancellationToken parameter to methods that take one|ℹ️|✔️|✔️| -|[MA0041](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0041.md)|Design|Make property static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️| -|[MA0042](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0042.md)|Design|Do not use blocking calls when the calling method is async|ℹ️|✔️|✔️| -|[MA0043](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0043.md)|Usage|Use nameof operator in ArgumentException|ℹ️|✔️|✔️| -|[MA0044](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0044.md)|Performance|Remove useless ToString call|ℹ️|✔️|✔️| -|[MA0045](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0045.md)|Design|Do not use blocking calls, even when the calling method must become async|ℹ️|❌|✔️| -|[MA0046](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0046.md)|Design|Use EventHandler\ to declare events|⚠️|✔️|❌| -|[MA0047](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0047.md)|Design|Declare types in namespaces|⚠️|✔️|❌| -|[MA0048](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0048.md)|Design|File name must match type name|⚠️|✔️|❌| -|[MA0049](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0049.md)|Design|Type name should not match containing namespace|❌|✔️|❌| -|[MA0050](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md)|Design|Validate arguments correctly in iterator methods|ℹ️|✔️|✔️| -|[MA0051](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)|Design|Method is too long|⚠️|✔️|❌| -|[MA0052](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0052.md)|Performance|Replace constant Enum.ToString with nameof|ℹ️|✔️|✔️| -|[MA0053](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md)|Design|Make class or record sealed|ℹ️|✔️|✔️| -|[MA0054](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0054.md)|Design|Embed the caught exception as innerException|⚠️|✔️|✔️| -|[MA0055](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md)|Design|Do not use finalizer|⚠️|✔️|❌| -|[MA0056](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0056.md)|Design|Do not call overridable members in constructor|⚠️|✔️|❌| -|[MA0057](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0057.md)|Naming|Class name should end with 'Attribute'|ℹ️|✔️|✔️| -|[MA0058](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0058.md)|Naming|Class name should end with 'Exception'|ℹ️|✔️|✔️| -|[MA0059](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0059.md)|Naming|Class name should end with 'EventArgs'|ℹ️|✔️|✔️| -|[MA0060](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0060.md)|Design|The value returned by Stream.Read/Stream.ReadAsync is not used|⚠️|✔️|❌| -|[MA0061](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0061.md)|Design|Method overrides should not change default values|⚠️|✔️|✔️| -|[MA0062](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0062.md)|Design|Non-flags enums should not be marked with "FlagsAttribute"|⚠️|✔️|✔️| -|[MA0063](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0063.md)|Performance|Use Where before OrderBy|ℹ️|✔️|✔️| -|[MA0064](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0064.md)|Design|Avoid locking on publicly accessible instance|⚠️|✔️|❌| -|[MA0065](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0065.md)|Performance|Default ValueType.Equals or HashCode is used for struct equality|⚠️|✔️|❌| -|[MA0066](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0066.md)|Performance|Hash table unfriendly type is used in a hash table|⚠️|✔️|❌| -|[MA0067](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0067.md)|Design|Use Guid.Empty|ℹ️|✔️|✔️| -|[MA0068](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0068.md)|Design|Invalid parameter name for nullable attribute|⚠️|✔️|❌| -|[MA0069](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0069.md)|Design|Non-constant static fields should not be visible|⚠️|✔️|❌| -|[MA0070](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0070.md)|Design|Obsolete attributes should include explanations|⚠️|✔️|❌| -|[MA0071](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0071.md)|Style|Avoid using redundant else|ℹ️|✔️|✔️| -|[MA0072](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0072.md)|Design|Do not throw from a finally block|⚠️|✔️|❌| -|[MA0073](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0073.md)|Style|Avoid comparison with bool constant|ℹ️|✔️|✔️| -|[MA0074](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0074.md)|Usage|Avoid implicit culture-sensitive methods|⚠️|✔️|✔️| -|[MA0075](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0075.md)|Design|Do not use implicit culture-sensitive ToString|ℹ️|✔️|❌| -|[MA0076](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0076.md)|Design|Do not use implicit culture-sensitive ToString in interpolated strings|ℹ️|✔️|✔️| -|[MA0077](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0077.md)|Design|A class that provides Equals(T) should implement IEquatable\|⚠️|✔️|✔️| -|[MA0078](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0078.md)|Performance|Use 'Cast' instead of 'Select' to cast|ℹ️|✔️|✔️| -|[MA0079](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0079.md)|Usage|Forward the CancellationToken using .WithCancellation()|ℹ️|✔️|✔️| -|[MA0080](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0080.md)|Usage|Use a cancellation token using .WithCancellation()|ℹ️|❌|❌| -|[MA0081](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0081.md)|Design|Method overrides should not omit params keyword|⚠️|✔️|✔️| -|[MA0082](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0082.md)|Design|NaN should not be used in comparisons|⚠️|✔️|✔️| -|[MA0083](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0083.md)|Design|ConstructorArgument parameters should exist in constructors|⚠️|✔️|❌| -|[MA0084](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0084.md)|Design|Local variables should not hide other symbols|⚠️|✔️|❌| -|[MA0085](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0085.md)|Usage|Anonymous delegates should not be used to unsubscribe from Events|⚠️|✔️|❌| -|[MA0086](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0086.md)|Design|Do not throw from a finalizer|⚠️|✔️|❌| -|[MA0087](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0087.md)|Design|Parameters with \[DefaultParameterValue\] attributes should also be marked \[Optional\]|⚠️|✔️|✔️| -|[MA0088](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0088.md)|Design|Use \[DefaultParameterValue\] instead of \[DefaultValue\]|⚠️|✔️|✔️| -|[MA0089](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0089.md)|Performance|Optimize string method usage|ℹ️|✔️|✔️| -|[MA0090](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0090.md)|Design|Remove empty else/finally block|ℹ️|✔️|✔️| -|[MA0091](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0091.md)|Usage|Sender should be 'this' for instance events|⚠️|✔️|✔️| -|[MA0092](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0092.md)|Usage|Sender should be 'null' for static events|⚠️|✔️|❌| -|[MA0093](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0093.md)|Usage|EventArgs should not be null when raising an event|⚠️|✔️|✔️| -|[MA0094](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0094.md)|Design|A class that provides CompareTo(T) should implement IComparable\|⚠️|✔️|✔️| -|[MA0095](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0095.md)|Design|A class that implements IEquatable\ should override Equals(object)|⚠️|✔️|✔️| -|[MA0096](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0096.md)|Design|A class that implements IComparable\ should also implement IEquatable\|⚠️|✔️|✔️| -|[MA0097](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0097.md)|Design|A class that implements IComparable\ or IComparable should override comparison operators|⚠️|✔️|✔️| -|[MA0098](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0098.md)|Performance|Use indexer instead of LINQ methods|ℹ️|✔️|✔️| -|[MA0099](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0099.md)|Usage|Use Explicit enum value instead of 0|⚠️|✔️|✔️| -|[MA0100](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0100.md)|Usage|Await task before disposing of resources|⚠️|✔️|❌| -|[MA0101](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0101.md)|Usage|String contains an implicit end of line character|👻|✔️|✔️| -|[MA0102](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0102.md)|Design|Make member readonly|ℹ️|✔️|✔️| -|[MA0103](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0103.md)|Usage|Use SequenceEqual instead of equality operator|⚠️|✔️|✔️| -|[MA0104](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0104.md)|Design|Do not create a type with a name from the BCL|⚠️|❌|❌| -|[MA0105](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0105.md)|Performance|Use the lambda parameters instead of using a closure|ℹ️|✔️|✔️| -|[MA0106](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0106.md)|Performance|Avoid closure by using an overload with the 'factoryArgument' parameter|ℹ️|✔️|✔️| -|[MA0107](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0107.md)|Design|Do not use object.ToString|ℹ️|❌|❌| -|[MA0108](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0108.md)|Usage|Remove redundant argument value|ℹ️|✔️|✔️| -|[MA0109](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0109.md)|Design|Consider adding an overload with a Span\ or Memory\|ℹ️|❌|❌| -|[MA0110](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md)|Performance|Use the Regex source generator|ℹ️|✔️|✔️| -|[MA0111](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0111.md)|Performance|Use string.Create instead of FormattableString|ℹ️|✔️|✔️| -|[MA0112](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0112.md)|Performance|Use 'Count \> 0' instead of 'Any()'|ℹ️|❌|✔️| -|[MA0113](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0113.md)|Design|Use DateTime.UnixEpoch|ℹ️|✔️|✔️| -|[MA0114](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0114.md)|Design|Use DateTimeOffset.UnixEpoch|ℹ️|✔️|✔️| -|[MA0115](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0115.md)|Usage|Unknown component parameter|⚠️|✔️|❌| -|[MA0116](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0116.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️| -|[MA0117](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0117.md)|Design|Parameters with \[EditorRequired\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️| -|[MA0118](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0118.md)|Design|\[JSInvokable\] methods must be public|⚠️|✔️|✔️| -|[MA0119](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0119.md)|Design|JSRuntime must not be used in OnInitialized or OnInitializedAsync|⚠️|✔️|❌| -|[MA0120](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0120.md)|Performance|Use InvokeVoidAsync when the returned value is not used|ℹ️|✔️|✔️| -|[MA0121](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0121.md)|Design|Do not overwrite parameter value|ℹ️|❌|❌| -|[MA0122](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0122.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes are only valid in routable components (@page)|ℹ️|✔️|❌| -|[MA0123](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0123.md)|Design|Sequence number must be a constant|⚠️|✔️|❌| -|[MA0124](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0124.md)|Design|Microsoft.Extensions.Logging parameter type is not valid|⚠️|✔️|❌| -|[MA0125](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0125.md)|Design|The list of log parameter types contains an invalid type|⚠️|✔️|❌| -|[MA0126](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0126.md)|Design|The list of log parameter types contains a duplicate|⚠️|✔️|❌| -|[MA0127](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0127.md)|Usage|Use String.Equals instead of is pattern|👻|✔️|✔️| -|[MA0128](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0128.md)|Usage|Use 'is' operator instead of SequenceEqual|ℹ️|✔️|✔️| -|[MA0129](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0129.md)|Usage|Await task in using statement|⚠️|✔️|✔️| -|[MA0130](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0130.md)|Usage|GetType() should not be used on System.Type instances|⚠️|✔️|❌| -|[MA0131](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0131.md)|Usage|ArgumentNullException.ThrowIfNull should not be used with non-nullable types|⚠️|✔️|✔️| -|[MA0132](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0132.md)|Design|Do not convert implicitly to DateTimeOffset|⚠️|✔️|❌| -|[MA0133](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0133.md)|Design|Use DateTimeOffset instead of relying on the implicit conversion|ℹ️|✔️|❌| -|[MA0134](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0134.md)|Usage|Observe result of async calls|⚠️|✔️|❌| -|[MA0135](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0135.md)|Design|The log parameter has no configured type|⚠️|❌|❌| -|[MA0136](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0136.md)|Usage|Raw String contains an implicit end of line character|👻|✔️|❌| -|[MA0137](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0137.md)|Design|Use 'Async' suffix when a method returns an awaitable type|⚠️|❌|✔️| -|[MA0138](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0138.md)|Design|Do not use 'Async' suffix when a method does not return an awaitable type|⚠️|❌|✔️| -|[MA0139](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0139.md)|Design|Serilog parameter type is not valid|⚠️|✔️|❌| -|[MA0140](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0140.md)|Design|Both if and else branch have identical code|⚠️|✔️|❌| -|[MA0141](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0141.md)|Usage|Use 'is not null' instead of '!= null'|ℹ️|❌|✔️| -|[MA0142](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0142.md)|Usage|Use 'is null' instead of '== null'|ℹ️|❌|✔️| -|[MA0143](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0143.md)|Design|Primary constructor parameters should be readonly|⚠️|✔️|❌| -|[MA0144](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0144.md)|Performance|Use System.OperatingSystem to check the current OS|⚠️|✔️|✔️| -|[MA0145](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0145.md)|Usage|Signature for \[UnsafeAccessorAttribute\] method is not valid|⚠️|✔️|❌| -|[MA0146](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0146.md)|Usage|Name must be set explicitly on local functions|⚠️|✔️|✔️| -|[MA0147](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0147.md)|Usage|Avoid async void method for delegate|⚠️|✔️|❌| -|[MA0148](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0148.md)|Usage|Use 'is' patterns instead of '==' for constant values|ℹ️|❌|✔️| -|[MA0149](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0149.md)|Usage|Use 'is not' patterns instead of '!=' for constant values|ℹ️|❌|✔️| -|[MA0150](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0150.md)|Design|Do not call ToString() when the type falls back to object.ToString()|⚠️|✔️|❌| -|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|⚠️|✔️|❌| -|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|ℹ️|✔️|✔️| -|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|⚠️|✔️|❌| -|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️|✔️| -|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|⚠️|❌|❌| -|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️| -|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️| -|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|⚠️|✔️|✔️| -|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|ℹ️|✔️|✔️| -|[MA0160](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0160.md)|Performance|Use ContainsKey instead of TryGetValue|ℹ️|✔️|✔️| -|[MA0161](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0161.md)|Usage|UseShellExecute must be explicitly set|ℹ️|❌|✔️| -|[MA0162](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0162.md)|Usage|Use Process.Start overload with ProcessStartInfo|ℹ️|❌|❌| -|[MA0163](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0163.md)|Usage|UseShellExecute must be false when redirecting standard input or output|⚠️|✔️|❌| -|[MA0164](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0164.md)|Style|Use parentheses to make not pattern clearer|⚠️|✔️|✔️| -|[MA0166](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0166.md)|Usage|Forward the TimeProvider to methods that take one|ℹ️|✔️|✔️| -|[MA0167](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0167.md)|Usage|Use an overload with a TimeProvider argument|ℹ️|❌|❌| -|[MA0168](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0168.md)|Performance|Use readonly struct for in or ref readonly parameter|ℹ️|❌|❌| -|[MA0169](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0169.md)|Design|Use Equals method instead of operator|⚠️|✔️|✔️| -|[MA0170](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0170.md)|Design|Type cannot be used as an attribute argument|⚠️|❌|❌| -|[MA0171](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0171.md)|Usage|Use 'is null' / 'is not null' instead of Nullable\.HasValue|ℹ️|❌|✔️| -|[MA0172](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0172.md)|Usage|Both sides of the logical operation are identical|⚠️|❌|❌| -|[MA0173](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0173.md)|Design|Use LazyInitializer.EnsureInitialize|ℹ️|✔️|✔️| -|[MA0174](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0174.md)|Style|Record should use explicit 'class' keyword|ℹ️|❌|✔️| -|[MA0175](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0175.md)|Style|Record should not use explicit 'class' keyword|ℹ️|❌|✔️| -|[MA0176](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0176.md)|Performance|Optimize guid creation|ℹ️|✔️|✔️| -|[MA0177](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0177.md)|Style|Use single-line XML comment syntax when possible|ℹ️|❌|✔️| -|[MA0178](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0178.md)|Design|Use TimeSpan.Zero instead of TimeSpan.FromXXX(0)|ℹ️|✔️|✔️| -|[MA0179](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0179.md)|Performance|Use Attribute.IsDefined instead of GetCustomAttribute(s)|ℹ️|✔️|✔️| -|[MA0180](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0180.md)|Design|ILogger type parameter should match containing type|⚠️|❌|✔️| -|[MA0181](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0181.md)|Style|Do not use cast|ℹ️|❌|❌| -|[MA0182](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0182.md)|Design|Avoid unused internal types|ℹ️|✔️|✔️| -|[MA0183](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0183.md)|Usage|The format string should use placeholders|⚠️|✔️|❌| -|[MA0184](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0184.md)|Style|Do not use interpolated string without parameters|👻|✔️|✔️| -|[MA0185](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0185.md)|Performance|Simplify string.Create when all parameters are culture invariant|ℹ️|✔️|✔️| -|[MA0186](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0186.md)|Design|Equals method should use \[NotNullWhen(true)\] on the parameter|ℹ️|❌|✔️| -|[MA0187](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0187.md)|Design|Use constructor injection instead of \[Inject\] attribute|ℹ️|❌|✔️| -|[MA0188](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0188.md)|Design|Use System.TimeProvider instead of a custom time abstraction|ℹ️|✔️|❌| -|[MA0189](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0189.md)|Design|Use InlineArray instead of fixed-size buffers|ℹ️|✔️|✔️| -|[MA0190](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0190.md)|Design|Use partial property instead of partial method for GeneratedRegex|ℹ️|✔️|✔️| -|[MA0191](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0191.md)|Design|Do not use the null-forgiving operator|⚠️|❌|❌| -|[MA0192](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0192.md)|Usage|Use HasFlag instead of bitwise checks|ℹ️|✔️|✔️| -|[MA0193](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0193.md)|Usage|Use an overload with a MidpointRounding argument|ℹ️|✔️|✔️| -|[MA0194](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0194.md)|Usage|Merge is expressions on the same value|ℹ️|✔️|✔️| -|[MA0195](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0195.md)|Usage|Do not use static fields before they are initialized|⚠️|✔️|❌| -|[MA0196](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0196.md)|Design|Do not use inheritdoc on non-inheriting members|⚠️|✔️|❌| -|[MA0197](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0197.md)|Design|Add dedicated documentation on types|ℹ️|✔️|❌| -|[MA0198](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0198.md)|Design|Specify cref for ambiguous inheritdoc on types|⚠️|✔️|✔️| -|[MA0199](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0199.md)|Design|Do not use inheritdoc on types without inheritance source|⚠️|✔️|❌| -|[MA0200](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0200.md)|Usage|Do not use empty property patterns with non-nullable value types|ℹ️|✔️|✔️| -|[MA0201](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0201.md)|Usage|Do not use zero-valued enum flags in flag checks|⚠️|✔️|❌| -|[MA0202](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0202.md)|Design|Conditional compilation branches have identical code|⚠️|✔️|✔️| -|[MA0203](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0203.md)|Design|Do not use return tag for void method|⚠️|✔️|❌| -|[MA0204](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0204.md)|Design|Remove unnecessary partial modifier|ℹ️|✔️|✔️| -|[MA0205](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0205.md)|Style|Use exclusive or operator|ℹ️|✔️|✔️| -|[MA0206](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0206.md)|Style|Remove unnecessary braces in type declaration|ℹ️|✔️|✔️| -|[MA0207](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0207.md)|Usage|\[FixedAddressValueType\] fields must be static|⚠️|✔️|❌| -|[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| -|[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| -|[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| -|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️| -|[MA0212](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0212.md)|Usage|Use MemoryMarshal.GetReference instead of indexing at 0|⚠️|❌|✔️| +|Id|Category|Description|Severity|Is enabled|Code fix|Configurable| +|--|--------|-----------|:------:|:--------:|:------:|:----------:| +|[MA0001](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md)|Usage|StringComparison is missing|ℹ️|✔️|✔️|❌| +|[MA0002](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0002.md)|Usage|IEqualityComparer\ or IComparer\ is missing|⚠️|✔️|✔️|✔️| +|[MA0003](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0003.md)|Style|Add parameter name to improve readability|ℹ️|✔️|✔️|✔️| +|[MA0004](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md)|Usage|Use Task.ConfigureAwait|⚠️|✔️|✔️|✔️| +|[MA0005](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0005.md)|Performance|Use Array.Empty\()|⚠️|✔️|✔️|❌| +|[MA0006](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0006.md)|Usage|Use String.Equals instead of equality operator|⚠️|✔️|✔️|❌| +|[MA0007](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0007.md)|Style|Add a comma after the last value|ℹ️|✔️|✔️|✔️| +|[MA0008](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0008.md)|Performance|Add StructLayoutAttribute|⚠️|✔️|✔️|❌| +|[MA0009](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md)|Security|Add regex evaluation timeout|⚠️|✔️|❌|❌| +|[MA0010](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0010.md)|Design|Mark attributes with AttributeUsageAttribute|⚠️|✔️|✔️|❌| +|[MA0011](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md)|Usage|IFormatProvider is missing|⚠️|✔️|✔️|✔️| +|[MA0012](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0012.md)|Design|Do not raise reserved exception type|⚠️|✔️|❌|❌| +|[MA0013](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0013.md)|Design|Types should not extend System.ApplicationException|⚠️|✔️|❌|❌| +|[MA0014](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0014.md)|Design|Do not raise System.ApplicationException type|⚠️|✔️|❌|❌| +|[MA0015](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md)|Usage|Specify the parameter name in ArgumentException|⚠️|✔️|❌|✔️| +|[MA0016](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0016.md)|Design|Prefer using collection abstraction instead of implementation|⚠️|✔️|❌|❌| +|[MA0017](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0017.md)|Design|Abstract types should not have public or internal constructors|⚠️|✔️|✔️|❌| +|[MA0018](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0018.md)|Design|Do not declare static members on generic types (deprecated; use CA1000 instead)|ℹ️|✔️|❌|❌| +|[MA0019](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0019.md)|Usage|Use EventArgs.Empty|⚠️|✔️|✔️|❌| +|[MA0020](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0020.md)|Performance|Use direct methods instead of LINQ methods|ℹ️|✔️|✔️|✔️| +|[MA0021](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0021.md)|Usage|Use StringComparer.GetHashCode instead of string.GetHashCode|⚠️|✔️|✔️|❌| +|[MA0022](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0022.md)|Design|Return Task.FromResult instead of returning null|⚠️|✔️|✔️|❌| +|[MA0023](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0023.md)|Performance|Add RegexOptions.ExplicitCapture|⚠️|✔️|✔️|❌| +|[MA0024](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0024.md)|Usage|Use an explicit StringComparer when possible|⚠️|✔️|✔️|❌| +|[MA0025](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0025.md)|Design|Implement the functionality instead of throwing NotImplementedException|⚠️|✔️|❌|❌| +|[MA0026](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)|Design|Fix TODO comment|⚠️|✔️|❌|❌| +|[MA0027](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0027.md)|Usage|Prefer rethrowing an exception implicitly|⚠️|✔️|✔️|❌| +|[MA0028](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0028.md)|Performance|Optimize StringBuilder usage|ℹ️|✔️|✔️|❌| +|[MA0029](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0029.md)|Performance|Combine LINQ methods|ℹ️|✔️|✔️|❌| +|[MA0030](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0030.md)|Performance|Remove useless OrderBy call|⚠️|✔️|✔️|❌| +|[MA0031](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md)|Performance|Optimize Enumerable.Count() usage|ℹ️|✔️|✔️|❌| +|[MA0032](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0032.md)|Usage|Use an overload with a CancellationToken argument, even when no token is available in scope|ℹ️|❌|❌|✔️| +|[MA0033](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0033.md)|Design|Do not tag instance fields with ThreadStaticAttribute|⚠️|✔️|❌|❌| +|[MA0035](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0035.md)|Usage|Do not use dangerous threading methods|⚠️|✔️|❌|❌| +|[MA0036](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0036.md)|Design|Make class static|ℹ️|✔️|✔️|❌| +|[MA0037](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0037.md)|Usage|Remove empty statement|❌|✔️|✔️|❌| +|[MA0038](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0038.md)|Design|Make method static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️|❌| +|[MA0039](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0039.md)|Security|Do not write your own certificate validation method|❌|✔️|❌|❌| +|[MA0040](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0040.md)|Usage|Forward the CancellationToken parameter to methods that take one|ℹ️|✔️|✔️|❌| +|[MA0041](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0041.md)|Design|Make property static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️|❌| +|[MA0042](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0042.md)|Design|Do not use blocking calls when the calling method is async|ℹ️|✔️|✔️|✔️| +|[MA0043](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0043.md)|Usage|Use nameof operator in ArgumentException|ℹ️|✔️|✔️|❌| +|[MA0044](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0044.md)|Performance|Remove useless ToString call|ℹ️|✔️|✔️|❌| +|[MA0045](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0045.md)|Design|Do not use blocking calls, even when the calling method must become async|ℹ️|❌|✔️|✔️| +|[MA0046](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0046.md)|Design|Use EventHandler\ to declare events|⚠️|✔️|❌|❌| +|[MA0047](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0047.md)|Design|Declare types in namespaces|⚠️|✔️|❌|❌| +|[MA0048](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0048.md)|Design|File name must match type name|⚠️|✔️|❌|✔️| +|[MA0049](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0049.md)|Design|Type name should not match containing namespace|❌|✔️|❌|❌| +|[MA0050](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md)|Design|Validate arguments correctly in iterator methods|ℹ️|✔️|✔️|❌| +|[MA0051](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)|Design|Method is too long|⚠️|✔️|❌|✔️| +|[MA0052](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0052.md)|Performance|Replace constant Enum.ToString with nameof|ℹ️|✔️|✔️|❌| +|[MA0053](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md)|Design|Make class or record sealed|ℹ️|✔️|✔️|✔️| +|[MA0054](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0054.md)|Design|Embed the caught exception as innerException|⚠️|✔️|✔️|❌| +|[MA0055](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md)|Design|Do not use finalizer|⚠️|✔️|❌|❌| +|[MA0056](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0056.md)|Design|Do not call overridable members in constructor|⚠️|✔️|❌|❌| +|[MA0057](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0057.md)|Naming|Class name should end with 'Attribute'|ℹ️|✔️|✔️|❌| +|[MA0058](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0058.md)|Naming|Class name should end with 'Exception'|ℹ️|✔️|✔️|❌| +|[MA0059](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0059.md)|Naming|Class name should end with 'EventArgs'|ℹ️|✔️|✔️|❌| +|[MA0060](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0060.md)|Design|The value returned by Stream.Read/Stream.ReadAsync is not used|⚠️|✔️|❌|❌| +|[MA0061](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0061.md)|Design|Method overrides should not change default values|⚠️|✔️|✔️|❌| +|[MA0062](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0062.md)|Design|Non-flags enums should not be marked with "FlagsAttribute"|⚠️|✔️|✔️|✔️| +|[MA0063](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0063.md)|Performance|Use Where before OrderBy|ℹ️|✔️|✔️|❌| +|[MA0064](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0064.md)|Design|Avoid locking on publicly accessible instance|⚠️|✔️|❌|❌| +|[MA0065](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0065.md)|Performance|Default ValueType.Equals or HashCode is used for struct equality|⚠️|✔️|❌|❌| +|[MA0066](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0066.md)|Performance|Hash table unfriendly type is used in a hash table|⚠️|✔️|❌|❌| +|[MA0067](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0067.md)|Design|Use Guid.Empty|ℹ️|✔️|✔️|❌| +|[MA0068](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0068.md)|Design|Invalid parameter name for nullable attribute|⚠️|✔️|❌|❌| +|[MA0069](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0069.md)|Design|Non-constant static fields should not be visible|⚠️|✔️|❌|❌| +|[MA0070](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0070.md)|Design|Obsolete attributes should include explanations|⚠️|✔️|❌|❌| +|[MA0071](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0071.md)|Style|Avoid using redundant else|ℹ️|✔️|✔️|❌| +|[MA0072](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0072.md)|Design|Do not throw from a finally block|⚠️|✔️|❌|❌| +|[MA0073](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0073.md)|Style|Avoid comparison with bool constant|ℹ️|✔️|✔️|❌| +|[MA0074](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0074.md)|Usage|Avoid implicit culture-sensitive methods|⚠️|✔️|✔️|❌| +|[MA0075](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0075.md)|Design|Do not use implicit culture-sensitive ToString|ℹ️|✔️|❌|✔️| +|[MA0076](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0076.md)|Design|Do not use implicit culture-sensitive ToString in interpolated strings|ℹ️|✔️|✔️|✔️| +|[MA0077](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0077.md)|Design|A class that provides Equals(T) should implement IEquatable\|⚠️|✔️|✔️|❌| +|[MA0078](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0078.md)|Performance|Use 'Cast' instead of 'Select' to cast|ℹ️|✔️|✔️|❌| +|[MA0079](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0079.md)|Usage|Forward the CancellationToken using .WithCancellation()|ℹ️|✔️|✔️|❌| +|[MA0080](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0080.md)|Usage|Use a cancellation token using .WithCancellation()|ℹ️|❌|❌|❌| +|[MA0081](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0081.md)|Design|Method overrides should not omit params keyword|⚠️|✔️|✔️|❌| +|[MA0082](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0082.md)|Design|NaN should not be used in comparisons|⚠️|✔️|✔️|❌| +|[MA0083](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0083.md)|Design|ConstructorArgument parameters should exist in constructors|⚠️|✔️|❌|❌| +|[MA0084](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0084.md)|Design|Local variables should not hide other symbols|⚠️|✔️|❌|❌| +|[MA0085](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0085.md)|Usage|Anonymous delegates should not be used to unsubscribe from Events|⚠️|✔️|❌|❌| +|[MA0086](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0086.md)|Design|Do not throw from a finalizer|⚠️|✔️|❌|❌| +|[MA0087](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0087.md)|Design|Parameters with \[DefaultParameterValue\] attributes should also be marked \[Optional\]|⚠️|✔️|✔️|❌| +|[MA0088](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0088.md)|Design|Use \[DefaultParameterValue\] instead of \[DefaultValue\]|⚠️|✔️|✔️|❌| +|[MA0089](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0089.md)|Performance|Optimize string method usage|ℹ️|✔️|✔️|❌| +|[MA0090](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0090.md)|Design|Remove empty else/finally block|ℹ️|✔️|✔️|❌| +|[MA0091](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0091.md)|Usage|Sender should be 'this' for instance events|⚠️|✔️|✔️|❌| +|[MA0092](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0092.md)|Usage|Sender should be 'null' for static events|⚠️|✔️|❌|❌| +|[MA0093](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0093.md)|Usage|EventArgs should not be null when raising an event|⚠️|✔️|✔️|❌| +|[MA0094](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0094.md)|Design|A class that provides CompareTo(T) should implement IComparable\|⚠️|✔️|✔️|❌| +|[MA0095](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0095.md)|Design|A class that implements IEquatable\ should override Equals(object)|⚠️|✔️|✔️|❌| +|[MA0096](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0096.md)|Design|A class that implements IComparable\ should also implement IEquatable\|⚠️|✔️|✔️|❌| +|[MA0097](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0097.md)|Design|A class that implements IComparable\ or IComparable should override comparison operators|⚠️|✔️|✔️|❌| +|[MA0098](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0098.md)|Performance|Use indexer instead of LINQ methods|ℹ️|✔️|✔️|❌| +|[MA0099](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0099.md)|Usage|Use Explicit enum value instead of 0|⚠️|✔️|✔️|✔️| +|[MA0100](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0100.md)|Usage|Await task before disposing of resources|⚠️|✔️|❌|❌| +|[MA0101](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0101.md)|Usage|String contains an implicit end of line character|👻|✔️|✔️|❌| +|[MA0102](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0102.md)|Design|Make member readonly|ℹ️|✔️|✔️|❌| +|[MA0103](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0103.md)|Usage|Use SequenceEqual instead of equality operator|⚠️|✔️|✔️|❌| +|[MA0104](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0104.md)|Design|Do not create a type with a name from the BCL|⚠️|❌|❌|✔️| +|[MA0105](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0105.md)|Performance|Use the lambda parameters instead of using a closure|ℹ️|✔️|✔️|❌| +|[MA0106](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0106.md)|Performance|Avoid closure by using an overload with the 'factoryArgument' parameter|ℹ️|✔️|✔️|❌| +|[MA0107](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0107.md)|Design|Do not use object.ToString|ℹ️|❌|❌|❌| +|[MA0108](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0108.md)|Usage|Remove redundant argument value|ℹ️|✔️|✔️|❌| +|[MA0109](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0109.md)|Design|Consider adding an overload with a Span\ or Memory\|ℹ️|❌|❌|❌| +|[MA0110](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md)|Performance|Use the Regex source generator|ℹ️|✔️|✔️|❌| +|[MA0111](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0111.md)|Performance|Use string.Create instead of FormattableString|ℹ️|✔️|✔️|❌| +|[MA0112](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0112.md)|Performance|Use 'Count \> 0' instead of 'Any()'|ℹ️|❌|✔️|❌| +|[MA0113](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0113.md)|Design|Use DateTime.UnixEpoch|ℹ️|✔️|✔️|❌| +|[MA0114](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0114.md)|Design|Use DateTimeOffset.UnixEpoch|ℹ️|✔️|✔️|❌| +|[MA0115](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0115.md)|Usage|Unknown component parameter|⚠️|✔️|❌|✔️| +|[MA0116](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0116.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️|❌| +|[MA0117](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0117.md)|Design|Parameters with \[EditorRequired\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️|❌| +|[MA0118](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0118.md)|Design|\[JSInvokable\] methods must be public|⚠️|✔️|✔️|❌| +|[MA0119](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0119.md)|Design|JSRuntime must not be used in OnInitialized or OnInitializedAsync|⚠️|✔️|❌|❌| +|[MA0120](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0120.md)|Performance|Use InvokeVoidAsync when the returned value is not used|ℹ️|✔️|✔️|❌| +|[MA0121](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0121.md)|Design|Do not overwrite parameter value|ℹ️|❌|❌|❌| +|[MA0122](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0122.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes are only valid in routable components (@page)|ℹ️|✔️|❌|❌| +|[MA0123](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0123.md)|Design|Sequence number must be a constant|⚠️|✔️|❌|❌| +|[MA0124](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0124.md)|Design|Microsoft.Extensions.Logging parameter type is not valid|⚠️|✔️|❌|✔️| +|[MA0125](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0125.md)|Design|The list of log parameter types contains an invalid type|⚠️|✔️|❌|❌| +|[MA0126](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0126.md)|Design|The list of log parameter types contains a duplicate|⚠️|✔️|❌|❌| +|[MA0127](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0127.md)|Usage|Use String.Equals instead of is pattern|👻|✔️|✔️|❌| +|[MA0128](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0128.md)|Usage|Use 'is' operator instead of SequenceEqual|ℹ️|✔️|✔️|❌| +|[MA0129](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0129.md)|Usage|Await task in using statement|⚠️|✔️|✔️|❌| +|[MA0130](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0130.md)|Usage|GetType() should not be used on System.Type instances|⚠️|✔️|❌|❌| +|[MA0131](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0131.md)|Usage|ArgumentNullException.ThrowIfNull should not be used with non-nullable types|⚠️|✔️|✔️|❌| +|[MA0132](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0132.md)|Design|Do not convert implicitly to DateTimeOffset|⚠️|✔️|❌|❌| +|[MA0133](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0133.md)|Design|Use DateTimeOffset instead of relying on the implicit conversion|ℹ️|✔️|❌|❌| +|[MA0134](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0134.md)|Usage|Observe result of async calls|⚠️|✔️|❌|✔️| +|[MA0135](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0135.md)|Design|The log parameter has no configured type|⚠️|❌|❌|❌| +|[MA0136](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0136.md)|Usage|Raw String contains an implicit end of line character|👻|✔️|❌|❌| +|[MA0137](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0137.md)|Design|Use 'Async' suffix when a method returns an awaitable type|⚠️|❌|✔️|✔️| +|[MA0138](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0138.md)|Design|Do not use 'Async' suffix when a method does not return an awaitable type|⚠️|❌|✔️|❌| +|[MA0139](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0139.md)|Design|Serilog parameter type is not valid|⚠️|✔️|❌|✔️| +|[MA0140](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0140.md)|Design|Both if and else branch have identical code|⚠️|✔️|❌|❌| +|[MA0141](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0141.md)|Usage|Use 'is not null' instead of '!= null'|ℹ️|❌|✔️|❌| +|[MA0142](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0142.md)|Usage|Use 'is null' instead of '== null'|ℹ️|❌|✔️|❌| +|[MA0143](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0143.md)|Design|Primary constructor parameters should be readonly|⚠️|✔️|❌|❌| +|[MA0144](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0144.md)|Performance|Use System.OperatingSystem to check the current OS|⚠️|✔️|✔️|❌| +|[MA0145](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0145.md)|Usage|Signature for \[UnsafeAccessorAttribute\] method is not valid|⚠️|✔️|❌|❌| +|[MA0146](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0146.md)|Usage|Name must be set explicitly on local functions|⚠️|✔️|✔️|❌| +|[MA0147](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0147.md)|Usage|Avoid async void method for delegate|⚠️|✔️|❌|❌| +|[MA0148](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0148.md)|Usage|Use 'is' patterns instead of '==' for constant values|ℹ️|❌|✔️|❌| +|[MA0149](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0149.md)|Usage|Use 'is not' patterns instead of '!=' for constant values|ℹ️|❌|✔️|❌| +|[MA0150](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0150.md)|Design|Do not call ToString() when the type falls back to object.ToString()|⚠️|✔️|❌|❌| +|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|⚠️|✔️|❌|❌| +|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|ℹ️|✔️|✔️|❌| +|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|⚠️|✔️|❌|✔️| +|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️|✔️|❌| +|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|⚠️|❌|❌|❌| +|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️|❌| +|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️|❌| +|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|⚠️|✔️|✔️|❌| +|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|ℹ️|✔️|✔️|❌| +|[MA0160](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0160.md)|Performance|Use ContainsKey instead of TryGetValue|ℹ️|✔️|✔️|❌| +|[MA0161](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0161.md)|Usage|UseShellExecute must be explicitly set|ℹ️|❌|✔️|❌| +|[MA0162](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0162.md)|Usage|Use Process.Start overload with ProcessStartInfo|ℹ️|❌|❌|❌| +|[MA0163](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0163.md)|Usage|UseShellExecute must be false when redirecting standard input or output|⚠️|✔️|❌|❌| +|[MA0164](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0164.md)|Style|Use parentheses to make not pattern clearer|⚠️|✔️|✔️|❌| +|[MA0166](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0166.md)|Usage|Forward the TimeProvider to methods that take one|ℹ️|✔️|✔️|❌| +|[MA0167](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0167.md)|Usage|Use an overload with a TimeProvider argument|ℹ️|❌|❌|❌| +|[MA0168](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0168.md)|Performance|Use readonly struct for in or ref readonly parameter|ℹ️|❌|❌|❌| +|[MA0169](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0169.md)|Design|Use Equals method instead of operator|⚠️|✔️|✔️|❌| +|[MA0170](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0170.md)|Design|Type cannot be used as an attribute argument|⚠️|❌|❌|❌| +|[MA0171](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0171.md)|Usage|Use 'is null' / 'is not null' instead of Nullable\.HasValue|ℹ️|❌|✔️|❌| +|[MA0172](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0172.md)|Usage|Both sides of the logical operation are identical|⚠️|❌|❌|❌| +|[MA0173](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0173.md)|Design|Use LazyInitializer.EnsureInitialize|ℹ️|✔️|✔️|❌| +|[MA0174](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0174.md)|Style|Record should use explicit 'class' keyword|ℹ️|❌|✔️|❌| +|[MA0175](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0175.md)|Style|Record should not use explicit 'class' keyword|ℹ️|❌|✔️|❌| +|[MA0176](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0176.md)|Performance|Optimize guid creation|ℹ️|✔️|✔️|❌| +|[MA0177](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0177.md)|Style|Use single-line XML comment syntax when possible|ℹ️|❌|✔️|❌| +|[MA0178](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0178.md)|Design|Use TimeSpan.Zero instead of TimeSpan.FromXXX(0)|ℹ️|✔️|✔️|❌| +|[MA0179](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0179.md)|Performance|Use Attribute.IsDefined instead of GetCustomAttribute(s)|ℹ️|✔️|✔️|❌| +|[MA0180](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0180.md)|Design|ILogger type parameter should match containing type|⚠️|❌|✔️|❌| +|[MA0181](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0181.md)|Style|Do not use cast|ℹ️|❌|❌|❌| +|[MA0182](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0182.md)|Design|Avoid unused internal types|ℹ️|✔️|✔️|❌| +|[MA0183](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0183.md)|Usage|The format string should use placeholders|⚠️|✔️|❌|❌| +|[MA0184](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0184.md)|Style|Do not use interpolated string without parameters|👻|✔️|✔️|❌| +|[MA0185](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0185.md)|Performance|Simplify string.Create when all parameters are culture invariant|ℹ️|✔️|✔️|❌| +|[MA0186](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0186.md)|Design|Equals method should use \[NotNullWhen(true)\] on the parameter|ℹ️|❌|✔️|❌| +|[MA0187](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0187.md)|Design|Use constructor injection instead of \[Inject\] attribute|ℹ️|❌|✔️|❌| +|[MA0188](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0188.md)|Design|Use System.TimeProvider instead of a custom time abstraction|ℹ️|✔️|❌|❌| +|[MA0189](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0189.md)|Design|Use InlineArray instead of fixed-size buffers|ℹ️|✔️|✔️|❌| +|[MA0190](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0190.md)|Design|Use partial property instead of partial method for GeneratedRegex|ℹ️|✔️|✔️|❌| +|[MA0191](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0191.md)|Design|Do not use the null-forgiving operator|⚠️|❌|❌|❌| +|[MA0192](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0192.md)|Usage|Use HasFlag instead of bitwise checks|ℹ️|✔️|✔️|❌| +|[MA0193](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0193.md)|Usage|Use an overload with a MidpointRounding argument|ℹ️|✔️|✔️|❌| +|[MA0194](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0194.md)|Usage|Merge is expressions on the same value|ℹ️|✔️|✔️|❌| +|[MA0195](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0195.md)|Usage|Do not use static fields before they are initialized|⚠️|✔️|❌|❌| +|[MA0196](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0196.md)|Design|Do not use inheritdoc on non-inheriting members|⚠️|✔️|❌|❌| +|[MA0197](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0197.md)|Design|Add dedicated documentation on types|ℹ️|✔️|❌|❌| +|[MA0198](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0198.md)|Design|Specify cref for ambiguous inheritdoc on types|⚠️|✔️|✔️|❌| +|[MA0199](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0199.md)|Design|Do not use inheritdoc on types without inheritance source|⚠️|✔️|❌|❌| +|[MA0200](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0200.md)|Usage|Do not use empty property patterns with non-nullable value types|ℹ️|✔️|✔️|❌| +|[MA0201](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0201.md)|Usage|Do not use zero-valued enum flags in flag checks|⚠️|✔️|❌|❌| +|[MA0202](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0202.md)|Design|Conditional compilation branches have identical code|⚠️|✔️|✔️|❌| +|[MA0203](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0203.md)|Design|Do not use return tag for void method|⚠️|✔️|❌|❌| +|[MA0204](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0204.md)|Design|Remove unnecessary partial modifier|ℹ️|✔️|✔️|❌| +|[MA0205](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0205.md)|Style|Use exclusive or operator|ℹ️|✔️|✔️|❌| +|[MA0206](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0206.md)|Style|Remove unnecessary braces in type declaration|ℹ️|✔️|✔️|❌| +|[MA0207](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0207.md)|Usage|\[FixedAddressValueType\] fields must be static|⚠️|✔️|❌|❌| +|[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌|❌| +|[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️|❌| +|[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️|❌| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️|❌| +|[MA0212](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0212.md)|Usage|Use MemoryMarshal.GetReference instead of indexing at 0|⚠️|❌|✔️|❌| diff --git a/docs/README.md b/docs/README.md index 00d845e02..a5af1fa94 100755 --- a/docs/README.md +++ b/docs/README.md @@ -1,216 +1,216 @@ # Meziantou.Analyzer's rules -|Id|Category|Description|Severity|Is enabled|Code fix| -|--|--------|-----------|:------:|:--------:|:------:| -|[MA0001](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md)|Usage|StringComparison is missing|ℹ️|✔️|✔️| -|[MA0002](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0002.md)|Usage|IEqualityComparer\ or IComparer\ is missing|⚠️|✔️|✔️| -|[MA0003](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0003.md)|Style|Add parameter name to improve readability|ℹ️|✔️|✔️| -|[MA0004](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md)|Usage|Use Task.ConfigureAwait|⚠️|✔️|✔️| -|[MA0005](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0005.md)|Performance|Use Array.Empty\()|⚠️|✔️|✔️| -|[MA0006](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0006.md)|Usage|Use String.Equals instead of equality operator|⚠️|✔️|✔️| -|[MA0007](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0007.md)|Style|Add a comma after the last value|ℹ️|✔️|✔️| -|[MA0008](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0008.md)|Performance|Add StructLayoutAttribute|⚠️|✔️|✔️| -|[MA0009](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md)|Security|Add regex evaluation timeout|⚠️|✔️|❌| -|[MA0010](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0010.md)|Design|Mark attributes with AttributeUsageAttribute|⚠️|✔️|✔️| -|[MA0011](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md)|Usage|IFormatProvider is missing|⚠️|✔️|✔️| -|[MA0012](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0012.md)|Design|Do not raise reserved exception type|⚠️|✔️|❌| -|[MA0013](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0013.md)|Design|Types should not extend System.ApplicationException|⚠️|✔️|❌| -|[MA0014](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0014.md)|Design|Do not raise System.ApplicationException type|⚠️|✔️|❌| -|[MA0015](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md)|Usage|Specify the parameter name in ArgumentException|⚠️|✔️|❌| -|[MA0016](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0016.md)|Design|Prefer using collection abstraction instead of implementation|⚠️|✔️|❌| -|[MA0017](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0017.md)|Design|Abstract types should not have public or internal constructors|⚠️|✔️|✔️| -|[MA0018](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0018.md)|Design|Do not declare static members on generic types (deprecated; use CA1000 instead)|ℹ️|✔️|❌| -|[MA0019](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0019.md)|Usage|Use EventArgs.Empty|⚠️|✔️|✔️| -|[MA0020](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0020.md)|Performance|Use direct methods instead of LINQ methods|ℹ️|✔️|✔️| -|[MA0021](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0021.md)|Usage|Use StringComparer.GetHashCode instead of string.GetHashCode|⚠️|✔️|✔️| -|[MA0022](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0022.md)|Design|Return Task.FromResult instead of returning null|⚠️|✔️|✔️| -|[MA0023](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0023.md)|Performance|Add RegexOptions.ExplicitCapture|⚠️|✔️|✔️| -|[MA0024](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0024.md)|Usage|Use an explicit StringComparer when possible|⚠️|✔️|✔️| -|[MA0025](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0025.md)|Design|Implement the functionality instead of throwing NotImplementedException|⚠️|✔️|❌| -|[MA0026](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)|Design|Fix TODO comment|⚠️|✔️|❌| -|[MA0027](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0027.md)|Usage|Prefer rethrowing an exception implicitly|⚠️|✔️|✔️| -|[MA0028](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0028.md)|Performance|Optimize StringBuilder usage|ℹ️|✔️|✔️| -|[MA0029](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0029.md)|Performance|Combine LINQ methods|ℹ️|✔️|✔️| -|[MA0030](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0030.md)|Performance|Remove useless OrderBy call|⚠️|✔️|✔️| -|[MA0031](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md)|Performance|Optimize Enumerable.Count() usage|ℹ️|✔️|✔️| -|[MA0032](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0032.md)|Usage|Use an overload with a CancellationToken argument, even when no token is available in scope|ℹ️|❌|❌| -|[MA0033](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0033.md)|Design|Do not tag instance fields with ThreadStaticAttribute|⚠️|✔️|❌| -|[MA0035](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0035.md)|Usage|Do not use dangerous threading methods|⚠️|✔️|❌| -|[MA0036](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0036.md)|Design|Make class static|ℹ️|✔️|✔️| -|[MA0037](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0037.md)|Usage|Remove empty statement||✔️|✔️| -|[MA0038](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0038.md)|Design|Make method static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️| -|[MA0039](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0039.md)|Security|Do not write your own certificate validation method||✔️|❌| -|[MA0040](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0040.md)|Usage|Forward the CancellationToken parameter to methods that take one|ℹ️|✔️|✔️| -|[MA0041](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0041.md)|Design|Make property static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️| -|[MA0042](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0042.md)|Design|Do not use blocking calls when the calling method is async|ℹ️|✔️|✔️| -|[MA0043](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0043.md)|Usage|Use nameof operator in ArgumentException|ℹ️|✔️|✔️| -|[MA0044](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0044.md)|Performance|Remove useless ToString call|ℹ️|✔️|✔️| -|[MA0045](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0045.md)|Design|Do not use blocking calls, even when the calling method must become async|ℹ️|❌|✔️| -|[MA0046](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0046.md)|Design|Use EventHandler\ to declare events|⚠️|✔️|❌| -|[MA0047](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0047.md)|Design|Declare types in namespaces|⚠️|✔️|❌| -|[MA0048](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0048.md)|Design|File name must match type name|⚠️|✔️|❌| -|[MA0049](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0049.md)|Design|Type name should not match containing namespace||✔️|❌| -|[MA0050](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md)|Design|Validate arguments correctly in iterator methods|ℹ️|✔️|✔️| -|[MA0051](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)|Design|Method is too long|⚠️|✔️|❌| -|[MA0052](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0052.md)|Performance|Replace constant Enum.ToString with nameof|ℹ️|✔️|✔️| -|[MA0053](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md)|Design|Make class or record sealed|ℹ️|✔️|✔️| -|[MA0054](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0054.md)|Design|Embed the caught exception as innerException|⚠️|✔️|✔️| -|[MA0055](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md)|Design|Do not use finalizer|⚠️|✔️|❌| -|[MA0056](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0056.md)|Design|Do not call overridable members in constructor|⚠️|✔️|❌| -|[MA0057](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0057.md)|Naming|Class name should end with 'Attribute'|ℹ️|✔️|✔️| -|[MA0058](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0058.md)|Naming|Class name should end with 'Exception'|ℹ️|✔️|✔️| -|[MA0059](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0059.md)|Naming|Class name should end with 'EventArgs'|ℹ️|✔️|✔️| -|[MA0060](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0060.md)|Design|The value returned by Stream.Read/Stream.ReadAsync is not used|⚠️|✔️|❌| -|[MA0061](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0061.md)|Design|Method overrides should not change default values|⚠️|✔️|✔️| -|[MA0062](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0062.md)|Design|Non-flags enums should not be marked with "FlagsAttribute"|⚠️|✔️|✔️| -|[MA0063](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0063.md)|Performance|Use Where before OrderBy|ℹ️|✔️|✔️| -|[MA0064](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0064.md)|Design|Avoid locking on publicly accessible instance|⚠️|✔️|❌| -|[MA0065](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0065.md)|Performance|Default ValueType.Equals or HashCode is used for struct equality|⚠️|✔️|❌| -|[MA0066](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0066.md)|Performance|Hash table unfriendly type is used in a hash table|⚠️|✔️|❌| -|[MA0067](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0067.md)|Design|Use Guid.Empty|ℹ️|✔️|✔️| -|[MA0068](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0068.md)|Design|Invalid parameter name for nullable attribute|⚠️|✔️|❌| -|[MA0069](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0069.md)|Design|Non-constant static fields should not be visible|⚠️|✔️|❌| -|[MA0070](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0070.md)|Design|Obsolete attributes should include explanations|⚠️|✔️|❌| -|[MA0071](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0071.md)|Style|Avoid using redundant else|ℹ️|✔️|✔️| -|[MA0072](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0072.md)|Design|Do not throw from a finally block|⚠️|✔️|❌| -|[MA0073](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0073.md)|Style|Avoid comparison with bool constant|ℹ️|✔️|✔️| -|[MA0074](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0074.md)|Usage|Avoid implicit culture-sensitive methods|⚠️|✔️|✔️| -|[MA0075](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0075.md)|Design|Do not use implicit culture-sensitive ToString|ℹ️|✔️|❌| -|[MA0076](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0076.md)|Design|Do not use implicit culture-sensitive ToString in interpolated strings|ℹ️|✔️|✔️| -|[MA0077](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0077.md)|Design|A class that provides Equals(T) should implement IEquatable\|⚠️|✔️|✔️| -|[MA0078](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0078.md)|Performance|Use 'Cast' instead of 'Select' to cast|ℹ️|✔️|✔️| -|[MA0079](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0079.md)|Usage|Forward the CancellationToken using .WithCancellation()|ℹ️|✔️|✔️| -|[MA0080](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0080.md)|Usage|Use a cancellation token using .WithCancellation()|ℹ️|❌|❌| -|[MA0081](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0081.md)|Design|Method overrides should not omit params keyword|⚠️|✔️|✔️| -|[MA0082](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0082.md)|Design|NaN should not be used in comparisons|⚠️|✔️|✔️| -|[MA0083](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0083.md)|Design|ConstructorArgument parameters should exist in constructors|⚠️|✔️|❌| -|[MA0084](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0084.md)|Design|Local variables should not hide other symbols|⚠️|✔️|❌| -|[MA0085](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0085.md)|Usage|Anonymous delegates should not be used to unsubscribe from Events|⚠️|✔️|❌| -|[MA0086](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0086.md)|Design|Do not throw from a finalizer|⚠️|✔️|❌| -|[MA0087](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0087.md)|Design|Parameters with \[DefaultParameterValue\] attributes should also be marked \[Optional\]|⚠️|✔️|✔️| -|[MA0088](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0088.md)|Design|Use \[DefaultParameterValue\] instead of \[DefaultValue\]|⚠️|✔️|✔️| -|[MA0089](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0089.md)|Performance|Optimize string method usage|ℹ️|✔️|✔️| -|[MA0090](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0090.md)|Design|Remove empty else/finally block|ℹ️|✔️|✔️| -|[MA0091](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0091.md)|Usage|Sender should be 'this' for instance events|⚠️|✔️|✔️| -|[MA0092](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0092.md)|Usage|Sender should be 'null' for static events|⚠️|✔️|❌| -|[MA0093](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0093.md)|Usage|EventArgs should not be null when raising an event|⚠️|✔️|✔️| -|[MA0094](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0094.md)|Design|A class that provides CompareTo(T) should implement IComparable\|⚠️|✔️|✔️| -|[MA0095](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0095.md)|Design|A class that implements IEquatable\ should override Equals(object)|⚠️|✔️|✔️| -|[MA0096](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0096.md)|Design|A class that implements IComparable\ should also implement IEquatable\|⚠️|✔️|✔️| -|[MA0097](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0097.md)|Design|A class that implements IComparable\ or IComparable should override comparison operators|⚠️|✔️|✔️| -|[MA0098](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0098.md)|Performance|Use indexer instead of LINQ methods|ℹ️|✔️|✔️| -|[MA0099](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0099.md)|Usage|Use Explicit enum value instead of 0|⚠️|✔️|✔️| -|[MA0100](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0100.md)|Usage|Await task before disposing of resources|⚠️|✔️|❌| -|[MA0101](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0101.md)|Usage|String contains an implicit end of line character|👻|✔️|✔️| -|[MA0102](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0102.md)|Design|Make member readonly|ℹ️|✔️|✔️| -|[MA0103](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0103.md)|Usage|Use SequenceEqual instead of equality operator|⚠️|✔️|✔️| -|[MA0104](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0104.md)|Design|Do not create a type with a name from the BCL|⚠️|❌|❌| -|[MA0105](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0105.md)|Performance|Use the lambda parameters instead of using a closure|ℹ️|✔️|✔️| -|[MA0106](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0106.md)|Performance|Avoid closure by using an overload with the 'factoryArgument' parameter|ℹ️|✔️|✔️| -|[MA0107](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0107.md)|Design|Do not use object.ToString|ℹ️|❌|❌| -|[MA0108](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0108.md)|Usage|Remove redundant argument value|ℹ️|✔️|✔️| -|[MA0109](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0109.md)|Design|Consider adding an overload with a Span\ or Memory\|ℹ️|❌|❌| -|[MA0110](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md)|Performance|Use the Regex source generator|ℹ️|✔️|✔️| -|[MA0111](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0111.md)|Performance|Use string.Create instead of FormattableString|ℹ️|✔️|✔️| -|[MA0112](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0112.md)|Performance|Use 'Count \> 0' instead of 'Any()'|ℹ️|❌|✔️| -|[MA0113](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0113.md)|Design|Use DateTime.UnixEpoch|ℹ️|✔️|✔️| -|[MA0114](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0114.md)|Design|Use DateTimeOffset.UnixEpoch|ℹ️|✔️|✔️| -|[MA0115](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0115.md)|Usage|Unknown component parameter|⚠️|✔️|❌| -|[MA0116](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0116.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️| -|[MA0117](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0117.md)|Design|Parameters with \[EditorRequired\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️| -|[MA0118](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0118.md)|Design|\[JSInvokable\] methods must be public|⚠️|✔️|✔️| -|[MA0119](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0119.md)|Design|JSRuntime must not be used in OnInitialized or OnInitializedAsync|⚠️|✔️|❌| -|[MA0120](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0120.md)|Performance|Use InvokeVoidAsync when the returned value is not used|ℹ️|✔️|✔️| -|[MA0121](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0121.md)|Design|Do not overwrite parameter value|ℹ️|❌|❌| -|[MA0122](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0122.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes are only valid in routable components (@page)|ℹ️|✔️|❌| -|[MA0123](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0123.md)|Design|Sequence number must be a constant|⚠️|✔️|❌| -|[MA0124](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0124.md)|Design|Microsoft.Extensions.Logging parameter type is not valid|⚠️|✔️|❌| -|[MA0125](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0125.md)|Design|The list of log parameter types contains an invalid type|⚠️|✔️|❌| -|[MA0126](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0126.md)|Design|The list of log parameter types contains a duplicate|⚠️|✔️|❌| -|[MA0127](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0127.md)|Usage|Use String.Equals instead of is pattern|👻|✔️|✔️| -|[MA0128](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0128.md)|Usage|Use 'is' operator instead of SequenceEqual|ℹ️|✔️|✔️| -|[MA0129](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0129.md)|Usage|Await task in using statement|⚠️|✔️|✔️| -|[MA0130](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0130.md)|Usage|GetType() should not be used on System.Type instances|⚠️|✔️|❌| -|[MA0131](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0131.md)|Usage|ArgumentNullException.ThrowIfNull should not be used with non-nullable types|⚠️|✔️|✔️| -|[MA0132](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0132.md)|Design|Do not convert implicitly to DateTimeOffset|⚠️|✔️|❌| -|[MA0133](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0133.md)|Design|Use DateTimeOffset instead of relying on the implicit conversion|ℹ️|✔️|❌| -|[MA0134](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0134.md)|Usage|Observe result of async calls|⚠️|✔️|❌| -|[MA0135](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0135.md)|Design|The log parameter has no configured type|⚠️|❌|❌| -|[MA0136](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0136.md)|Usage|Raw String contains an implicit end of line character|👻|✔️|❌| -|[MA0137](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0137.md)|Design|Use 'Async' suffix when a method returns an awaitable type|⚠️|❌|✔️| -|[MA0138](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0138.md)|Design|Do not use 'Async' suffix when a method does not return an awaitable type|⚠️|❌|✔️| -|[MA0139](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0139.md)|Design|Serilog parameter type is not valid|⚠️|✔️|❌| -|[MA0140](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0140.md)|Design|Both if and else branch have identical code|⚠️|✔️|❌| -|[MA0141](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0141.md)|Usage|Use 'is not null' instead of '!= null'|ℹ️|❌|✔️| -|[MA0142](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0142.md)|Usage|Use 'is null' instead of '== null'|ℹ️|❌|✔️| -|[MA0143](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0143.md)|Design|Primary constructor parameters should be readonly|⚠️|✔️|❌| -|[MA0144](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0144.md)|Performance|Use System.OperatingSystem to check the current OS|⚠️|✔️|✔️| -|[MA0145](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0145.md)|Usage|Signature for \[UnsafeAccessorAttribute\] method is not valid|⚠️|✔️|❌| -|[MA0146](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0146.md)|Usage|Name must be set explicitly on local functions|⚠️|✔️|✔️| -|[MA0147](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0147.md)|Usage|Avoid async void method for delegate|⚠️|✔️|❌| -|[MA0148](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0148.md)|Usage|Use 'is' patterns instead of '==' for constant values|ℹ️|❌|✔️| -|[MA0149](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0149.md)|Usage|Use 'is not' patterns instead of '!=' for constant values|ℹ️|❌|✔️| -|[MA0150](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0150.md)|Design|Do not call ToString() when the type falls back to object.ToString()|⚠️|✔️|❌| -|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|⚠️|✔️|❌| -|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|ℹ️|✔️|✔️| -|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|⚠️|✔️|❌| -|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️|✔️| -|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|⚠️|❌|❌| -|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️| -|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️| -|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|⚠️|✔️|✔️| -|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|ℹ️|✔️|✔️| -|[MA0160](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0160.md)|Performance|Use ContainsKey instead of TryGetValue|ℹ️|✔️|✔️| -|[MA0161](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0161.md)|Usage|UseShellExecute must be explicitly set|ℹ️|❌|✔️| -|[MA0162](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0162.md)|Usage|Use Process.Start overload with ProcessStartInfo|ℹ️|❌|❌| -|[MA0163](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0163.md)|Usage|UseShellExecute must be false when redirecting standard input or output|⚠️|✔️|❌| -|[MA0164](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0164.md)|Style|Use parentheses to make not pattern clearer|⚠️|✔️|✔️| -|[MA0166](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0166.md)|Usage|Forward the TimeProvider to methods that take one|ℹ️|✔️|✔️| -|[MA0167](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0167.md)|Usage|Use an overload with a TimeProvider argument|ℹ️|❌|❌| -|[MA0168](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0168.md)|Performance|Use readonly struct for in or ref readonly parameter|ℹ️|❌|❌| -|[MA0169](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0169.md)|Design|Use Equals method instead of operator|⚠️|✔️|✔️| -|[MA0170](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0170.md)|Design|Type cannot be used as an attribute argument|⚠️|❌|❌| -|[MA0171](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0171.md)|Usage|Use 'is null' / 'is not null' instead of Nullable\.HasValue|ℹ️|❌|✔️| -|[MA0172](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0172.md)|Usage|Both sides of the logical operation are identical|⚠️|❌|❌| -|[MA0173](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0173.md)|Design|Use LazyInitializer.EnsureInitialize|ℹ️|✔️|✔️| -|[MA0174](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0174.md)|Style|Record should use explicit 'class' keyword|ℹ️|❌|✔️| -|[MA0175](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0175.md)|Style|Record should not use explicit 'class' keyword|ℹ️|❌|✔️| -|[MA0176](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0176.md)|Performance|Optimize guid creation|ℹ️|✔️|✔️| -|[MA0177](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0177.md)|Style|Use single-line XML comment syntax when possible|ℹ️|❌|✔️| -|[MA0178](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0178.md)|Design|Use TimeSpan.Zero instead of TimeSpan.FromXXX(0)|ℹ️|✔️|✔️| -|[MA0179](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0179.md)|Performance|Use Attribute.IsDefined instead of GetCustomAttribute(s)|ℹ️|✔️|✔️| -|[MA0180](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0180.md)|Design|ILogger type parameter should match containing type|⚠️|❌|✔️| -|[MA0181](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0181.md)|Style|Do not use cast|ℹ️|❌|❌| -|[MA0182](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0182.md)|Design|Avoid unused internal types|ℹ️|✔️|✔️| -|[MA0183](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0183.md)|Usage|The format string should use placeholders|⚠️|✔️|❌| -|[MA0184](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0184.md)|Style|Do not use interpolated string without parameters|👻|✔️|✔️| -|[MA0185](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0185.md)|Performance|Simplify string.Create when all parameters are culture invariant|ℹ️|✔️|✔️| -|[MA0186](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0186.md)|Design|Equals method should use \[NotNullWhen(true)\] on the parameter|ℹ️|❌|✔️| -|[MA0187](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0187.md)|Design|Use constructor injection instead of \[Inject\] attribute|ℹ️|❌|✔️| -|[MA0188](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0188.md)|Design|Use System.TimeProvider instead of a custom time abstraction|ℹ️|✔️|❌| -|[MA0189](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0189.md)|Design|Use InlineArray instead of fixed-size buffers|ℹ️|✔️|✔️| -|[MA0190](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0190.md)|Design|Use partial property instead of partial method for GeneratedRegex|ℹ️|✔️|✔️| -|[MA0191](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0191.md)|Design|Do not use the null-forgiving operator|⚠️|❌|❌| -|[MA0192](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0192.md)|Usage|Use HasFlag instead of bitwise checks|ℹ️|✔️|✔️| -|[MA0193](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0193.md)|Usage|Use an overload with a MidpointRounding argument|ℹ️|✔️|✔️| -|[MA0194](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0194.md)|Usage|Merge is expressions on the same value|ℹ️|✔️|✔️| -|[MA0195](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0195.md)|Usage|Do not use static fields before they are initialized|⚠️|✔️|❌| -|[MA0196](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0196.md)|Design|Do not use inheritdoc on non-inheriting members|⚠️|✔️|❌| -|[MA0197](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0197.md)|Design|Add dedicated documentation on types|ℹ️|✔️|❌| -|[MA0198](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0198.md)|Design|Specify cref for ambiguous inheritdoc on types|⚠️|✔️|✔️| -|[MA0199](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0199.md)|Design|Do not use inheritdoc on types without inheritance source|⚠️|✔️|❌| -|[MA0200](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0200.md)|Usage|Do not use empty property patterns with non-nullable value types|ℹ️|✔️|✔️| -|[MA0201](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0201.md)|Usage|Do not use zero-valued enum flags in flag checks|⚠️|✔️|❌| -|[MA0202](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0202.md)|Design|Conditional compilation branches have identical code|⚠️|✔️|✔️| -|[MA0203](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0203.md)|Design|Do not use return tag for void method|⚠️|✔️|❌| -|[MA0204](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0204.md)|Design|Remove unnecessary partial modifier|ℹ️|✔️|✔️| -|[MA0205](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0205.md)|Style|Use exclusive or operator|ℹ️|✔️|✔️| -|[MA0206](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0206.md)|Style|Remove unnecessary braces in type declaration|ℹ️|✔️|✔️| -|[MA0207](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0207.md)|Usage|\[FixedAddressValueType\] fields must be static|⚠️|✔️|❌| -|[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌| -|[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️| -|[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️| -|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️| -|[MA0212](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0212.md)|Usage|Use MemoryMarshal.GetReference instead of indexing at 0|⚠️|❌|✔️| +|Id|Category|Description|Severity|Is enabled|Code fix|Configurable| +|--|--------|-----------|:------:|:--------:|:------:|:----------:| +|[MA0001](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md)|Usage|StringComparison is missing|ℹ️|✔️|✔️|❌| +|[MA0002](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0002.md)|Usage|IEqualityComparer\ or IComparer\ is missing|⚠️|✔️|✔️|✔️| +|[MA0003](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0003.md)|Style|Add parameter name to improve readability|ℹ️|✔️|✔️|✔️| +|[MA0004](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md)|Usage|Use Task.ConfigureAwait|⚠️|✔️|✔️|✔️| +|[MA0005](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0005.md)|Performance|Use Array.Empty\()|⚠️|✔️|✔️|❌| +|[MA0006](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0006.md)|Usage|Use String.Equals instead of equality operator|⚠️|✔️|✔️|❌| +|[MA0007](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0007.md)|Style|Add a comma after the last value|ℹ️|✔️|✔️|✔️| +|[MA0008](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0008.md)|Performance|Add StructLayoutAttribute|⚠️|✔️|✔️|❌| +|[MA0009](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md)|Security|Add regex evaluation timeout|⚠️|✔️|❌|❌| +|[MA0010](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0010.md)|Design|Mark attributes with AttributeUsageAttribute|⚠️|✔️|✔️|❌| +|[MA0011](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md)|Usage|IFormatProvider is missing|⚠️|✔️|✔️|✔️| +|[MA0012](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0012.md)|Design|Do not raise reserved exception type|⚠️|✔️|❌|❌| +|[MA0013](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0013.md)|Design|Types should not extend System.ApplicationException|⚠️|✔️|❌|❌| +|[MA0014](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0014.md)|Design|Do not raise System.ApplicationException type|⚠️|✔️|❌|❌| +|[MA0015](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md)|Usage|Specify the parameter name in ArgumentException|⚠️|✔️|❌|✔️| +|[MA0016](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0016.md)|Design|Prefer using collection abstraction instead of implementation|⚠️|✔️|❌|❌| +|[MA0017](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0017.md)|Design|Abstract types should not have public or internal constructors|⚠️|✔️|✔️|❌| +|[MA0018](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0018.md)|Design|Do not declare static members on generic types (deprecated; use CA1000 instead)|ℹ️|✔️|❌|❌| +|[MA0019](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0019.md)|Usage|Use EventArgs.Empty|⚠️|✔️|✔️|❌| +|[MA0020](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0020.md)|Performance|Use direct methods instead of LINQ methods|ℹ️|✔️|✔️|✔️| +|[MA0021](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0021.md)|Usage|Use StringComparer.GetHashCode instead of string.GetHashCode|⚠️|✔️|✔️|❌| +|[MA0022](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0022.md)|Design|Return Task.FromResult instead of returning null|⚠️|✔️|✔️|❌| +|[MA0023](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0023.md)|Performance|Add RegexOptions.ExplicitCapture|⚠️|✔️|✔️|❌| +|[MA0024](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0024.md)|Usage|Use an explicit StringComparer when possible|⚠️|✔️|✔️|❌| +|[MA0025](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0025.md)|Design|Implement the functionality instead of throwing NotImplementedException|⚠️|✔️|❌|❌| +|[MA0026](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)|Design|Fix TODO comment|⚠️|✔️|❌|❌| +|[MA0027](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0027.md)|Usage|Prefer rethrowing an exception implicitly|⚠️|✔️|✔️|❌| +|[MA0028](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0028.md)|Performance|Optimize StringBuilder usage|ℹ️|✔️|✔️|❌| +|[MA0029](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0029.md)|Performance|Combine LINQ methods|ℹ️|✔️|✔️|❌| +|[MA0030](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0030.md)|Performance|Remove useless OrderBy call|⚠️|✔️|✔️|❌| +|[MA0031](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md)|Performance|Optimize Enumerable.Count() usage|ℹ️|✔️|✔️|❌| +|[MA0032](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0032.md)|Usage|Use an overload with a CancellationToken argument, even when no token is available in scope|ℹ️|❌|❌|✔️| +|[MA0033](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0033.md)|Design|Do not tag instance fields with ThreadStaticAttribute|⚠️|✔️|❌|❌| +|[MA0035](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0035.md)|Usage|Do not use dangerous threading methods|⚠️|✔️|❌|❌| +|[MA0036](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0036.md)|Design|Make class static|ℹ️|✔️|✔️|❌| +|[MA0037](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0037.md)|Usage|Remove empty statement||✔️|✔️|❌| +|[MA0038](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0038.md)|Design|Make method static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️|❌| +|[MA0039](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0039.md)|Security|Do not write your own certificate validation method||✔️|❌|❌| +|[MA0040](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0040.md)|Usage|Forward the CancellationToken parameter to methods that take one|ℹ️|✔️|✔️|❌| +|[MA0041](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0041.md)|Design|Make property static (deprecated, use CA1822 instead)|ℹ️|✔️|✔️|❌| +|[MA0042](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0042.md)|Design|Do not use blocking calls when the calling method is async|ℹ️|✔️|✔️|✔️| +|[MA0043](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0043.md)|Usage|Use nameof operator in ArgumentException|ℹ️|✔️|✔️|❌| +|[MA0044](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0044.md)|Performance|Remove useless ToString call|ℹ️|✔️|✔️|❌| +|[MA0045](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0045.md)|Design|Do not use blocking calls, even when the calling method must become async|ℹ️|❌|✔️|✔️| +|[MA0046](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0046.md)|Design|Use EventHandler\ to declare events|⚠️|✔️|❌|❌| +|[MA0047](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0047.md)|Design|Declare types in namespaces|⚠️|✔️|❌|❌| +|[MA0048](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0048.md)|Design|File name must match type name|⚠️|✔️|❌|✔️| +|[MA0049](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0049.md)|Design|Type name should not match containing namespace||✔️|❌|❌| +|[MA0050](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md)|Design|Validate arguments correctly in iterator methods|ℹ️|✔️|✔️|❌| +|[MA0051](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)|Design|Method is too long|⚠️|✔️|❌|✔️| +|[MA0052](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0052.md)|Performance|Replace constant Enum.ToString with nameof|ℹ️|✔️|✔️|❌| +|[MA0053](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md)|Design|Make class or record sealed|ℹ️|✔️|✔️|✔️| +|[MA0054](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0054.md)|Design|Embed the caught exception as innerException|⚠️|✔️|✔️|❌| +|[MA0055](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md)|Design|Do not use finalizer|⚠️|✔️|❌|❌| +|[MA0056](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0056.md)|Design|Do not call overridable members in constructor|⚠️|✔️|❌|❌| +|[MA0057](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0057.md)|Naming|Class name should end with 'Attribute'|ℹ️|✔️|✔️|❌| +|[MA0058](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0058.md)|Naming|Class name should end with 'Exception'|ℹ️|✔️|✔️|❌| +|[MA0059](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0059.md)|Naming|Class name should end with 'EventArgs'|ℹ️|✔️|✔️|❌| +|[MA0060](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0060.md)|Design|The value returned by Stream.Read/Stream.ReadAsync is not used|⚠️|✔️|❌|❌| +|[MA0061](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0061.md)|Design|Method overrides should not change default values|⚠️|✔️|✔️|❌| +|[MA0062](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0062.md)|Design|Non-flags enums should not be marked with "FlagsAttribute"|⚠️|✔️|✔️|✔️| +|[MA0063](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0063.md)|Performance|Use Where before OrderBy|ℹ️|✔️|✔️|❌| +|[MA0064](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0064.md)|Design|Avoid locking on publicly accessible instance|⚠️|✔️|❌|❌| +|[MA0065](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0065.md)|Performance|Default ValueType.Equals or HashCode is used for struct equality|⚠️|✔️|❌|❌| +|[MA0066](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0066.md)|Performance|Hash table unfriendly type is used in a hash table|⚠️|✔️|❌|❌| +|[MA0067](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0067.md)|Design|Use Guid.Empty|ℹ️|✔️|✔️|❌| +|[MA0068](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0068.md)|Design|Invalid parameter name for nullable attribute|⚠️|✔️|❌|❌| +|[MA0069](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0069.md)|Design|Non-constant static fields should not be visible|⚠️|✔️|❌|❌| +|[MA0070](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0070.md)|Design|Obsolete attributes should include explanations|⚠️|✔️|❌|❌| +|[MA0071](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0071.md)|Style|Avoid using redundant else|ℹ️|✔️|✔️|❌| +|[MA0072](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0072.md)|Design|Do not throw from a finally block|⚠️|✔️|❌|❌| +|[MA0073](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0073.md)|Style|Avoid comparison with bool constant|ℹ️|✔️|✔️|❌| +|[MA0074](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0074.md)|Usage|Avoid implicit culture-sensitive methods|⚠️|✔️|✔️|❌| +|[MA0075](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0075.md)|Design|Do not use implicit culture-sensitive ToString|ℹ️|✔️|❌|✔️| +|[MA0076](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0076.md)|Design|Do not use implicit culture-sensitive ToString in interpolated strings|ℹ️|✔️|✔️|✔️| +|[MA0077](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0077.md)|Design|A class that provides Equals(T) should implement IEquatable\|⚠️|✔️|✔️|❌| +|[MA0078](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0078.md)|Performance|Use 'Cast' instead of 'Select' to cast|ℹ️|✔️|✔️|❌| +|[MA0079](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0079.md)|Usage|Forward the CancellationToken using .WithCancellation()|ℹ️|✔️|✔️|❌| +|[MA0080](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0080.md)|Usage|Use a cancellation token using .WithCancellation()|ℹ️|❌|❌|❌| +|[MA0081](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0081.md)|Design|Method overrides should not omit params keyword|⚠️|✔️|✔️|❌| +|[MA0082](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0082.md)|Design|NaN should not be used in comparisons|⚠️|✔️|✔️|❌| +|[MA0083](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0083.md)|Design|ConstructorArgument parameters should exist in constructors|⚠️|✔️|❌|❌| +|[MA0084](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0084.md)|Design|Local variables should not hide other symbols|⚠️|✔️|❌|❌| +|[MA0085](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0085.md)|Usage|Anonymous delegates should not be used to unsubscribe from Events|⚠️|✔️|❌|❌| +|[MA0086](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0086.md)|Design|Do not throw from a finalizer|⚠️|✔️|❌|❌| +|[MA0087](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0087.md)|Design|Parameters with \[DefaultParameterValue\] attributes should also be marked \[Optional\]|⚠️|✔️|✔️|❌| +|[MA0088](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0088.md)|Design|Use \[DefaultParameterValue\] instead of \[DefaultValue\]|⚠️|✔️|✔️|❌| +|[MA0089](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0089.md)|Performance|Optimize string method usage|ℹ️|✔️|✔️|❌| +|[MA0090](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0090.md)|Design|Remove empty else/finally block|ℹ️|✔️|✔️|❌| +|[MA0091](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0091.md)|Usage|Sender should be 'this' for instance events|⚠️|✔️|✔️|❌| +|[MA0092](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0092.md)|Usage|Sender should be 'null' for static events|⚠️|✔️|❌|❌| +|[MA0093](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0093.md)|Usage|EventArgs should not be null when raising an event|⚠️|✔️|✔️|❌| +|[MA0094](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0094.md)|Design|A class that provides CompareTo(T) should implement IComparable\|⚠️|✔️|✔️|❌| +|[MA0095](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0095.md)|Design|A class that implements IEquatable\ should override Equals(object)|⚠️|✔️|✔️|❌| +|[MA0096](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0096.md)|Design|A class that implements IComparable\ should also implement IEquatable\|⚠️|✔️|✔️|❌| +|[MA0097](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0097.md)|Design|A class that implements IComparable\ or IComparable should override comparison operators|⚠️|✔️|✔️|❌| +|[MA0098](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0098.md)|Performance|Use indexer instead of LINQ methods|ℹ️|✔️|✔️|❌| +|[MA0099](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0099.md)|Usage|Use Explicit enum value instead of 0|⚠️|✔️|✔️|✔️| +|[MA0100](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0100.md)|Usage|Await task before disposing of resources|⚠️|✔️|❌|❌| +|[MA0101](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0101.md)|Usage|String contains an implicit end of line character|👻|✔️|✔️|❌| +|[MA0102](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0102.md)|Design|Make member readonly|ℹ️|✔️|✔️|❌| +|[MA0103](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0103.md)|Usage|Use SequenceEqual instead of equality operator|⚠️|✔️|✔️|❌| +|[MA0104](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0104.md)|Design|Do not create a type with a name from the BCL|⚠️|❌|❌|✔️| +|[MA0105](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0105.md)|Performance|Use the lambda parameters instead of using a closure|ℹ️|✔️|✔️|❌| +|[MA0106](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0106.md)|Performance|Avoid closure by using an overload with the 'factoryArgument' parameter|ℹ️|✔️|✔️|❌| +|[MA0107](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0107.md)|Design|Do not use object.ToString|ℹ️|❌|❌|❌| +|[MA0108](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0108.md)|Usage|Remove redundant argument value|ℹ️|✔️|✔️|❌| +|[MA0109](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0109.md)|Design|Consider adding an overload with a Span\ or Memory\|ℹ️|❌|❌|❌| +|[MA0110](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md)|Performance|Use the Regex source generator|ℹ️|✔️|✔️|❌| +|[MA0111](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0111.md)|Performance|Use string.Create instead of FormattableString|ℹ️|✔️|✔️|❌| +|[MA0112](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0112.md)|Performance|Use 'Count \> 0' instead of 'Any()'|ℹ️|❌|✔️|❌| +|[MA0113](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0113.md)|Design|Use DateTime.UnixEpoch|ℹ️|✔️|✔️|❌| +|[MA0114](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0114.md)|Design|Use DateTimeOffset.UnixEpoch|ℹ️|✔️|✔️|❌| +|[MA0115](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0115.md)|Usage|Unknown component parameter|⚠️|✔️|❌|✔️| +|[MA0116](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0116.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️|❌| +|[MA0117](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0117.md)|Design|Parameters with \[EditorRequired\] attributes should also be marked as \[Parameter\]|⚠️|✔️|✔️|❌| +|[MA0118](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0118.md)|Design|\[JSInvokable\] methods must be public|⚠️|✔️|✔️|❌| +|[MA0119](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0119.md)|Design|JSRuntime must not be used in OnInitialized or OnInitializedAsync|⚠️|✔️|❌|❌| +|[MA0120](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0120.md)|Performance|Use InvokeVoidAsync when the returned value is not used|ℹ️|✔️|✔️|❌| +|[MA0121](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0121.md)|Design|Do not overwrite parameter value|ℹ️|❌|❌|❌| +|[MA0122](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0122.md)|Design|Parameters with \[SupplyParameterFromQuery\] attributes are only valid in routable components (@page)|ℹ️|✔️|❌|❌| +|[MA0123](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0123.md)|Design|Sequence number must be a constant|⚠️|✔️|❌|❌| +|[MA0124](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0124.md)|Design|Microsoft.Extensions.Logging parameter type is not valid|⚠️|✔️|❌|✔️| +|[MA0125](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0125.md)|Design|The list of log parameter types contains an invalid type|⚠️|✔️|❌|❌| +|[MA0126](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0126.md)|Design|The list of log parameter types contains a duplicate|⚠️|✔️|❌|❌| +|[MA0127](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0127.md)|Usage|Use String.Equals instead of is pattern|👻|✔️|✔️|❌| +|[MA0128](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0128.md)|Usage|Use 'is' operator instead of SequenceEqual|ℹ️|✔️|✔️|❌| +|[MA0129](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0129.md)|Usage|Await task in using statement|⚠️|✔️|✔️|❌| +|[MA0130](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0130.md)|Usage|GetType() should not be used on System.Type instances|⚠️|✔️|❌|❌| +|[MA0131](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0131.md)|Usage|ArgumentNullException.ThrowIfNull should not be used with non-nullable types|⚠️|✔️|✔️|❌| +|[MA0132](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0132.md)|Design|Do not convert implicitly to DateTimeOffset|⚠️|✔️|❌|❌| +|[MA0133](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0133.md)|Design|Use DateTimeOffset instead of relying on the implicit conversion|ℹ️|✔️|❌|❌| +|[MA0134](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0134.md)|Usage|Observe result of async calls|⚠️|✔️|❌|✔️| +|[MA0135](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0135.md)|Design|The log parameter has no configured type|⚠️|❌|❌|❌| +|[MA0136](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0136.md)|Usage|Raw String contains an implicit end of line character|👻|✔️|❌|❌| +|[MA0137](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0137.md)|Design|Use 'Async' suffix when a method returns an awaitable type|⚠️|❌|✔️|✔️| +|[MA0138](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0138.md)|Design|Do not use 'Async' suffix when a method does not return an awaitable type|⚠️|❌|✔️|❌| +|[MA0139](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0139.md)|Design|Serilog parameter type is not valid|⚠️|✔️|❌|✔️| +|[MA0140](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0140.md)|Design|Both if and else branch have identical code|⚠️|✔️|❌|❌| +|[MA0141](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0141.md)|Usage|Use 'is not null' instead of '!= null'|ℹ️|❌|✔️|❌| +|[MA0142](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0142.md)|Usage|Use 'is null' instead of '== null'|ℹ️|❌|✔️|❌| +|[MA0143](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0143.md)|Design|Primary constructor parameters should be readonly|⚠️|✔️|❌|❌| +|[MA0144](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0144.md)|Performance|Use System.OperatingSystem to check the current OS|⚠️|✔️|✔️|❌| +|[MA0145](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0145.md)|Usage|Signature for \[UnsafeAccessorAttribute\] method is not valid|⚠️|✔️|❌|❌| +|[MA0146](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0146.md)|Usage|Name must be set explicitly on local functions|⚠️|✔️|✔️|❌| +|[MA0147](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0147.md)|Usage|Avoid async void method for delegate|⚠️|✔️|❌|❌| +|[MA0148](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0148.md)|Usage|Use 'is' patterns instead of '==' for constant values|ℹ️|❌|✔️|❌| +|[MA0149](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0149.md)|Usage|Use 'is not' patterns instead of '!=' for constant values|ℹ️|❌|✔️|❌| +|[MA0150](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0150.md)|Design|Do not call ToString() when the type falls back to object.ToString()|⚠️|✔️|❌|❌| +|[MA0151](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md)|Usage|DebuggerDisplay must contain valid members|⚠️|✔️|❌|❌| +|[MA0152](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md)|Performance|Use Unwrap instead of using await twice|ℹ️|✔️|✔️|❌| +|[MA0153](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md)|Design|Do not log symbols decorated with DataClassificationAttribute directly|⚠️|✔️|❌|✔️| +|[MA0154](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md)|Design|Use langword in XML comment|ℹ️|✔️|✔️|❌| +|[MA0155](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md)|Design|Do not use async void methods|⚠️|❌|❌|❌| +|[MA0156](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md)|Design|Use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️|❌| +|[MA0157](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md)|Design|Do not use 'Async' suffix when a method returns IAsyncEnumerable\|⚠️|❌|✔️|❌| +|[MA0158](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md)|Performance|Use System.Threading.Lock|⚠️|✔️|✔️|❌| +|[MA0159](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md)|Performance|Use 'Order' instead of 'OrderBy'|ℹ️|✔️|✔️|❌| +|[MA0160](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0160.md)|Performance|Use ContainsKey instead of TryGetValue|ℹ️|✔️|✔️|❌| +|[MA0161](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0161.md)|Usage|UseShellExecute must be explicitly set|ℹ️|❌|✔️|❌| +|[MA0162](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0162.md)|Usage|Use Process.Start overload with ProcessStartInfo|ℹ️|❌|❌|❌| +|[MA0163](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0163.md)|Usage|UseShellExecute must be false when redirecting standard input or output|⚠️|✔️|❌|❌| +|[MA0164](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0164.md)|Style|Use parentheses to make not pattern clearer|⚠️|✔️|✔️|❌| +|[MA0166](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0166.md)|Usage|Forward the TimeProvider to methods that take one|ℹ️|✔️|✔️|❌| +|[MA0167](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0167.md)|Usage|Use an overload with a TimeProvider argument|ℹ️|❌|❌|❌| +|[MA0168](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0168.md)|Performance|Use readonly struct for in or ref readonly parameter|ℹ️|❌|❌|❌| +|[MA0169](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0169.md)|Design|Use Equals method instead of operator|⚠️|✔️|✔️|❌| +|[MA0170](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0170.md)|Design|Type cannot be used as an attribute argument|⚠️|❌|❌|❌| +|[MA0171](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0171.md)|Usage|Use 'is null' / 'is not null' instead of Nullable\.HasValue|ℹ️|❌|✔️|❌| +|[MA0172](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0172.md)|Usage|Both sides of the logical operation are identical|⚠️|❌|❌|❌| +|[MA0173](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0173.md)|Design|Use LazyInitializer.EnsureInitialize|ℹ️|✔️|✔️|❌| +|[MA0174](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0174.md)|Style|Record should use explicit 'class' keyword|ℹ️|❌|✔️|❌| +|[MA0175](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0175.md)|Style|Record should not use explicit 'class' keyword|ℹ️|❌|✔️|❌| +|[MA0176](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0176.md)|Performance|Optimize guid creation|ℹ️|✔️|✔️|❌| +|[MA0177](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0177.md)|Style|Use single-line XML comment syntax when possible|ℹ️|❌|✔️|❌| +|[MA0178](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0178.md)|Design|Use TimeSpan.Zero instead of TimeSpan.FromXXX(0)|ℹ️|✔️|✔️|❌| +|[MA0179](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0179.md)|Performance|Use Attribute.IsDefined instead of GetCustomAttribute(s)|ℹ️|✔️|✔️|❌| +|[MA0180](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0180.md)|Design|ILogger type parameter should match containing type|⚠️|❌|✔️|❌| +|[MA0181](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0181.md)|Style|Do not use cast|ℹ️|❌|❌|❌| +|[MA0182](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0182.md)|Design|Avoid unused internal types|ℹ️|✔️|✔️|❌| +|[MA0183](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0183.md)|Usage|The format string should use placeholders|⚠️|✔️|❌|❌| +|[MA0184](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0184.md)|Style|Do not use interpolated string without parameters|👻|✔️|✔️|❌| +|[MA0185](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0185.md)|Performance|Simplify string.Create when all parameters are culture invariant|ℹ️|✔️|✔️|❌| +|[MA0186](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0186.md)|Design|Equals method should use \[NotNullWhen(true)\] on the parameter|ℹ️|❌|✔️|❌| +|[MA0187](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0187.md)|Design|Use constructor injection instead of \[Inject\] attribute|ℹ️|❌|✔️|❌| +|[MA0188](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0188.md)|Design|Use System.TimeProvider instead of a custom time abstraction|ℹ️|✔️|❌|❌| +|[MA0189](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0189.md)|Design|Use InlineArray instead of fixed-size buffers|ℹ️|✔️|✔️|❌| +|[MA0190](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0190.md)|Design|Use partial property instead of partial method for GeneratedRegex|ℹ️|✔️|✔️|❌| +|[MA0191](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0191.md)|Design|Do not use the null-forgiving operator|⚠️|❌|❌|❌| +|[MA0192](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0192.md)|Usage|Use HasFlag instead of bitwise checks|ℹ️|✔️|✔️|❌| +|[MA0193](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0193.md)|Usage|Use an overload with a MidpointRounding argument|ℹ️|✔️|✔️|❌| +|[MA0194](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0194.md)|Usage|Merge is expressions on the same value|ℹ️|✔️|✔️|❌| +|[MA0195](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0195.md)|Usage|Do not use static fields before they are initialized|⚠️|✔️|❌|❌| +|[MA0196](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0196.md)|Design|Do not use inheritdoc on non-inheriting members|⚠️|✔️|❌|❌| +|[MA0197](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0197.md)|Design|Add dedicated documentation on types|ℹ️|✔️|❌|❌| +|[MA0198](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0198.md)|Design|Specify cref for ambiguous inheritdoc on types|⚠️|✔️|✔️|❌| +|[MA0199](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0199.md)|Design|Do not use inheritdoc on types without inheritance source|⚠️|✔️|❌|❌| +|[MA0200](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0200.md)|Usage|Do not use empty property patterns with non-nullable value types|ℹ️|✔️|✔️|❌| +|[MA0201](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0201.md)|Usage|Do not use zero-valued enum flags in flag checks|⚠️|✔️|❌|❌| +|[MA0202](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0202.md)|Design|Conditional compilation branches have identical code|⚠️|✔️|✔️|❌| +|[MA0203](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0203.md)|Design|Do not use return tag for void method|⚠️|✔️|❌|❌| +|[MA0204](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0204.md)|Design|Remove unnecessary partial modifier|ℹ️|✔️|✔️|❌| +|[MA0205](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0205.md)|Style|Use exclusive or operator|ℹ️|✔️|✔️|❌| +|[MA0206](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0206.md)|Style|Remove unnecessary braces in type declaration|ℹ️|✔️|✔️|❌| +|[MA0207](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0207.md)|Usage|\[FixedAddressValueType\] fields must be static|⚠️|✔️|❌|❌| +|[MA0208](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0208.md)|Usage|\[FixedAddressValueType\] fields must be value types|⚠️|✔️|❌|❌| +|[MA0209](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0209.md)|Performance|Use in keyword for in parameter|ℹ️|❌|✔️|❌| +|[MA0210](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0210.md)|Performance|Use in keyword to call the in overload|ℹ️|❌|✔️|❌| +|[MA0211](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0211.md)|Style|Use multi-line syntax for XML summary comments|ℹ️|❌|✔️|❌| +|[MA0212](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0212.md)|Usage|Use MemoryMarshal.GetReference instead of indexing at 0|⚠️|❌|✔️|❌| |Id|Suppressed rule|Justification| |--|---------------|-------------| diff --git a/docs/Rules/MA0045.md b/docs/Rules/MA0045.md index f541b530d..7dbd2716e 100644 --- a/docs/Rules/MA0045.md +++ b/docs/Rules/MA0045.md @@ -47,11 +47,11 @@ It also shares the same Db\* await-using special-cases as MA0042 by default for: ```` # .editorconfig file # Enable SQLite special-cases for MA0042/MA0045. default: true -MA0042.enable_sqlite_special_cases = true +MA0045.enable_sqlite_special_cases = true # Assume DbConnection/DbCommand/DbDataReader/DbTransaction/DbBatch hierarchies are sealed # for await-using analysis. default: true -MA0042.enable_db_special_cases = true +MA0045.enable_db_special_cases = true ```` You can also exclude specific method/property diagnostics for MA0042/MA0045 using assembly-level annotations. diff --git a/docs/Rules/MA0124.md b/docs/Rules/MA0124.md index 3f5548290..57ca7dbb1 100644 --- a/docs/Rules/MA0124.md +++ b/docs/Rules/MA0124.md @@ -5,6 +5,15 @@ Source: [LoggerParameterTypeAnalyzer.cs](https://github.com/meziantou/Meziantou. This rule ensures the parameters for Microsoft.Extensions.Logging's logger are of the expected types. You can configure the expected types using a configuration file. +## Configuration + +You can configure whether non-constant format strings are allowed: + +```` +# .editorconfig file +MA0124.allow_non_constant_formats = true +```` + To configure the rule, you need to create a file named `LoggerParameterTypes.txt` or `LoggerParameterTypes.*.txt`. - Each line is of the form `PropertyName;ExpectedType1;ExpectedType2;ExpectedType3;...` - A type is represented by its CLR metadata name or [XML Comment ID reference](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/documentation-comments.md) diff --git a/docs/Rules/MA0139.md b/docs/Rules/MA0139.md index 52128c635..6ca84d5ed 100644 --- a/docs/Rules/MA0139.md +++ b/docs/Rules/MA0139.md @@ -5,6 +5,15 @@ Source: [LoggerParameterTypeAnalyzer.cs](https://github.com/meziantou/Meziantou. This rule ensures the parameters for Serilog's logger are of the expected types. You can configure the expected types using a configuration file. +## Configuration + +You can configure whether non-constant format strings are allowed: + +```` +# .editorconfig file +MA0139.allow_non_constant_formats = true +```` + To configure the rule, you need to create a file named `LoggerParameterTypes.txt` or `LoggerParameterTypes.*.txt`. - Each line is of the form `PropertyName;ExpectedType1;ExpectedType2;ExpectedType3;...` - A type is represented by its CLR metadata name or [XML Comment ID reference](https://github.com/dotnet/csharpstandard/blob/standard-v6/standard/documentation-comments.md) diff --git a/src/DocumentationGenerator/Program.cs b/src/DocumentationGenerator/Program.cs index 3ac43725f..152c6bdce 100644 --- a/src/DocumentationGenerator/Program.cs +++ b/src/DocumentationGenerator/Program.cs @@ -2,8 +2,11 @@ #pragma warning disable CA1849 #pragma warning disable MA0004 #pragma warning disable MA0009 +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Text.Encodings.Web; using System.Text.RegularExpressions; +using Meziantou.Analyzer.Configurations; using Meziantou.Framework; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; @@ -16,6 +19,7 @@ return 1; } var fileWritten = 0; +var documentationValidationErrorCount = 0; var assemblies = new[] { typeof(Meziantou.Analyzer.Rules.CommaAnalyzer).Assembly, typeof(Meziantou.Analyzer.Rules.CommaFixer).Assembly }; var diagnosticAnalyzers = assemblies.SelectMany(assembly => assembly.GetExportedTypes()) @@ -38,9 +42,11 @@ .Select(type => (DiagnosticSuppressor)Activator.CreateInstance(type)!) .ToList(); +var ruleConfigurationKeys = GetRuleConfigurationKeys(assemblies); + var sb = new StringBuilder(); sb.Append("# ").Append(assemblies[0].GetName().Name).Append("'s rules\n"); -var rulesTable = GenerateRulesTable(diagnosticAnalyzers, codeFixProviders); +var rulesTable = GenerateRulesTable(diagnosticAnalyzers, codeFixProviders, ruleConfigurationKeys); sb.Append(rulesTable); var suppressorsTable = GenerateSuppressorsTable(diagnosticSuppressors); @@ -59,7 +65,7 @@ // nuget.org's markdown support is limited. Raw html in table is not supported. var readmePath = outputFolder / "README.md"; var readmeContent = await File.ReadAllTextAsync(readmePath); - var newContent = Regex.Replace(readmeContent, "(?<=\\r?\\n).*(?=)", "\n" + GenerateRulesTable(diagnosticAnalyzers, codeFixProviders, addTitle: false) + "\n", RegexOptions.Singleline); + var newContent = Regex.Replace(readmeContent, "(?<=\\r?\\n).*(?=)", "\n" + GenerateRulesTable(diagnosticAnalyzers, codeFixProviders, ruleConfigurationKeys, addTitle: false) + "\n", RegexOptions.Singleline); newContent = Regex.Replace(newContent, "(?<=\\r?\\n).*(?=)", "\n" + GenerateSuppressorsTable(diagnosticSuppressors) + "\n", RegexOptions.Singleline); newContent = Regex.Replace(newContent, "(?<=\\r?\\n).*(?=)", "\n" + GenerateRefactoringsTable(codeRefactoringProviders) + "\n", RegexOptions.Singleline); WriteFileIfChanged(readmePath, newContent); @@ -74,6 +80,21 @@ // Update title in rule pages and add links to source code { + void ValidateRuleDocumentationContainsConfigurationKeys(FullPath path, string ruleId, string content) + { + if (!ruleConfigurationKeys.TryGetValue(ruleId, out var configurationKeys)) + return; + + foreach (var configurationKey in configurationKeys) + { + if (content.Contains(configurationKey, StringComparison.Ordinal)) + continue; + + documentationValidationErrorCount++; + Console.Error.WriteLine($"Missing configuration key '{configurationKey}' in {path.MakePathRelativeTo(outputFolder)}"); + } + } + var rules = new HashSet(StringComparer.Ordinal); foreach (var diagnosticAnalyzer in diagnosticAnalyzers) { @@ -151,11 +172,13 @@ void AddLink(string name) sourceLinks.Sort(StringComparer.Ordinal); newContent = Regex.Replace(newContent, "(?<=\\r?\\n).*(?=)", (sourceLinks.Count == 1 ? "Source: " : "Sources: ") + string.Join(", ", sourceLinks) + "\n", RegexOptions.Singleline); + ValidateRuleDocumentationContainsConfigurationKeys(detailPath, diagnostic.Id, newContent); WriteFileIfChanged(detailPath, newContent); } else { WriteFileIfChanged(detailPath, title); + ValidateRuleDocumentationContainsConfigurationKeys(detailPath, diagnostic.Id, title); } } } @@ -203,6 +226,13 @@ void GenerateFile(FullPath outputPath, Action code) process.BeginErrorReadLine(); await process.WaitForExitAsync(); } + +if (documentationValidationErrorCount > 0) +{ + Console.Error.WriteLine($"{documentationValidationErrorCount} documentation validation error(s) found."); + return 1; +} + return fileWritten; void WriteFileIfChanged(FullPath path, string content) @@ -227,11 +257,11 @@ void WriteFileIfChanged(FullPath path, string content) } } -static string GenerateRulesTable(List diagnosticAnalyzers, List codeFixProviders, bool addTitle = true) +static string GenerateRulesTable(List diagnosticAnalyzers, List codeFixProviders, IReadOnlyDictionary> ruleConfigurationKeys, bool addTitle = true) { var sb = new StringBuilder(); - sb.Append("|Id|Category|Description|Severity|Is enabled|Code fix|\n"); - sb.Append("|--|--------|-----------|:------:|:--------:|:------:|\n"); + sb.Append("|Id|Category|Description|Severity|Is enabled|Code fix|Configurable|\n"); + sb.Append("|--|--------|-----------|:------:|:--------:|:------:|:----------:|\n"); foreach (var diagnostic in diagnosticAnalyzers.SelectMany(diagnosticAnalyzer => diagnosticAnalyzer.SupportedDiagnostics).DistinctBy(diag => diag.Id).OrderBy(diag => diag.Id, StringComparer.Ordinal)) { @@ -263,12 +293,30 @@ static string GenerateRulesTable(List diagnosticAnalyzers, L sb.Append(GetSeverity(diagnostic.DefaultSeverity)); } + ruleConfigurationKeys.TryGetValue(diagnostic.Id, out var configurationKeys); + configurationKeys ??= []; + sb.Append('|') .Append(GetBoolean(diagnostic.IsEnabledByDefault)) .Append('|') .Append(GetBoolean(hasCodeFix)) - .Append('|') - .Append('\n'); + .Append('|'); + + if (configurationKeys.Count > 0 && addTitle) + { + sb.Append("") + .Append(GetBoolean(true)) + .Append(""); + } + else + { + sb.Append(GetBoolean(configurationKeys.Count > 0)); + } + + sb.Append('|') + .Append('\n'); } return sb.ToString(); @@ -410,3 +458,68 @@ static string GetBoolean(bool value) { return value ? "✔️" : "❌"; } + +static IReadOnlyDictionary> GetRuleConfigurationKeys(IEnumerable assemblies) +{ + var configurationDefinitionType = typeof(ConfigurationDefinition).GetGenericTypeDefinition(); + var keyPropertyName = nameof(ConfigurationDefinition.Key); + var isHiddenPropertyName = nameof(ConfigurationDefinition.IsHidden); + var result = new Dictionary>(StringComparer.Ordinal); + + foreach (var type in assemblies.SelectMany(assembly => assembly.GetTypes())) + { + foreach (var field in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) + { + if (!field.FieldType.IsGenericType || field.FieldType.GetGenericTypeDefinition() != configurationDefinitionType) + continue; + + var fieldValue = field.GetValue(null); + if (fieldValue is null) + continue; + + if (field.FieldType.GetProperty(isHiddenPropertyName)?.GetValue(fieldValue) is bool isHidden && isHidden) + continue; + + if (field.FieldType.GetProperty(keyPropertyName)?.GetValue(fieldValue) is not string key) + continue; + + if (TryGetRuleIdPrefix(key, out var ruleId) is false) + continue; + + if (!result.TryGetValue(ruleId, out var keys)) + { + keys = []; + result.Add(ruleId, keys); + } + + keys.Add(key); + } + } + + var output = new Dictionary>(StringComparer.Ordinal); + foreach (var item in result) + { + output[item.Key] = [.. item.Value.Order(StringComparer.Ordinal)]; + } + + return output; +} + +static bool TryGetRuleIdPrefix(string key, [NotNullWhen(true)] out string? ruleId) +{ + ruleId = null; + if (key.Length < 6) + return false; + + if (key[0] != 'M' || key[1] != 'A') + return false; + + if (!char.IsAsciiDigit(key[2]) || !char.IsAsciiDigit(key[3]) || !char.IsAsciiDigit(key[4]) || !char.IsAsciiDigit(key[5])) + return false; + + if (key.Length > 6 && key[6] != '.') + return false; + + ruleId = key.Substring(0, 6); + return true; +} diff --git a/src/Meziantou.Analyzer/Configurations/AnalyzerOptionsExtensions.cs b/src/Meziantou.Analyzer/Configurations/AnalyzerOptionsExtensions.cs index 4c81147e1..e1694848d 100644 --- a/src/Meziantou.Analyzer/Configurations/AnalyzerOptionsExtensions.cs +++ b/src/Meziantou.Analyzer/Configurations/AnalyzerOptionsExtensions.cs @@ -5,92 +5,64 @@ namespace Meziantou.Analyzer.Configurations; public static class AnalyzerOptionsExtensions { - public static string GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, string key, string defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, ConfigurationDefinition configuration) { - var configuration = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - if (configuration.TryGetValue(key, out var value)) - return value; + if (!configuration.HasDefaultValue) + throw new InvalidOperationException($"Configuration value for '{configuration.Key}' is not set and has no default value."); - return defaultValue; - } + if (TryGetConfigurationValue(options, syntaxTree, configuration.Key, out var value)) + { + return ChangeType(value, configuration); + } - public static string GetConfigurationValue(this AnalyzerOptions options, SyntaxNode syntaxNode, string key, string defaultValue) - { - return GetConfigurationValue(options, syntaxNode.SyntaxTree, key, defaultValue); + return configuration.DefaultValue; } - public static string GetConfigurationValue(this AnalyzerOptions options, IOperation operation, string key, string defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, ConfigurationDefinition configuration, T defaultValue) { - return GetConfigurationValue(options, operation.Syntax.SyntaxTree, key, defaultValue); - } - - public static bool GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, string key, bool defaultValue) - { - var configuration = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - if (configuration.TryGetValue(key, out var value)) - return ChangeType(value, defaultValue); + if (TryGetConfigurationValue(options, syntaxTree, configuration.Key, out var value)) + return ChangeType(value, configuration.Key, defaultValue); return defaultValue; } - [return: NotNullIfNotNull(nameof(defaultValue))] - public static bool? GetConfigurationValue(this AnalyzerOptions options, SyntaxNode syntaxNode, string key, bool? defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, SyntaxNode syntaxNode, ConfigurationDefinition configuration) { - return GetConfigurationValue(options, syntaxNode.SyntaxTree, key, defaultValue); + return GetConfigurationValue(options, syntaxNode.SyntaxTree, configuration); } - [return: NotNullIfNotNull(nameof(defaultValue))] - public static bool? GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, string key, bool? defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, IOperation operation, ConfigurationDefinition configuration) { - var configuration = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - if (configuration.TryGetValue(key, out var value)) - return ChangeType(value, defaultValue); - - return defaultValue; + return GetConfigurationValue(options, operation.Syntax.SyntaxTree, configuration); } - public static int GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, string key, int defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, IOperation operation, ConfigurationDefinition configuration, T defaultValue) { - var configuration = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - if (configuration.TryGetValue(key, out var value)) - return ChangeType(value, defaultValue); - - return defaultValue; + return GetConfigurationValue(options, operation.Syntax.SyntaxTree, configuration, defaultValue); } - [return: NotNullIfNotNull(nameof(defaultValue))] - public static ReportDiagnostic? GetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, string key, ReportDiagnostic? defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, ConfigurationDefinition configuration) { - var configuration = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - if (configuration.TryGetValue(key, out var value)) - { - if (value is not null && Enum.TryParse(value, ignoreCase: true, out var result)) - return result; - } - - return defaultValue; - } + if (!configuration.HasDefaultValue) + throw new InvalidOperationException($"Configuration value for '{configuration.Key}' is not set and has no default value."); - [return: NotNullIfNotNull(nameof(defaultValue))] - public static string? GetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, string key, string? defaultValue) - { foreach (var location in symbol.Locations) { var syntaxTree = location.SourceTree; - if (syntaxTree is not null && options.TryGetConfigurationValue(syntaxTree, key, out var str)) - return str; + if (syntaxTree is not null && options.TryGetConfigurationValue(syntaxTree, configuration.Key, out var value)) + return ChangeType(value, configuration); } - return defaultValue; + return configuration.DefaultValue; } - public static bool GetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, string key, bool defaultValue) + public static T GetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, ConfigurationDefinition configuration, T defaultValue) { foreach (var location in symbol.Locations) { var syntaxTree = location.SourceTree; - if (syntaxTree is not null && options.TryGetConfigurationValue(syntaxTree, key, out var str)) - return ChangeType(str, defaultValue); + if (syntaxTree is not null && options.TryGetConfigurationValue(syntaxTree, configuration.Key, out var value)) + return ChangeType(value, configuration.Key, defaultValue); } return defaultValue; @@ -102,25 +74,30 @@ public static bool TryGetConfigurationValue(this AnalyzerOptions options, Syntax return configuration.TryGetValue(key, out value); } - public static bool TryGetConfigurationValue(this AnalyzerOptions options, IOperation operation, string key, [NotNullWhen(true)] out string? value) + public static bool TryGetConfigurationValue(this AnalyzerOptions options, SyntaxTree syntaxTree, ConfigurationDefinition configuration, [NotNullWhen(true)] out string? value) { - return TryGetConfigurationValue(options, operation.Syntax.SyntaxTree, key, out value); + return TryGetConfigurationValue(options, syntaxTree, configuration.Key, out value); } - public static bool GetConfigurationValue(this AnalyzerOptions options, IOperation operation, string key, bool defaultValue) + public static bool TryGetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, ConfigurationDefinition configuration, [NotNullWhen(true)] out string? value) { - return GetConfigurationValue(options, operation.Syntax.SyntaxTree, key, defaultValue); + return TryGetConfigurationValue(options, symbol, configuration.Key, out value); } - private static bool ChangeType(string value, bool defaultValue) + public static bool TryGetConfigurationValue(this AnalyzerOptions options, ISymbol symbol, string key, [NotNullWhen(true)] out string? value) { - if (value is not null && bool.TryParse(value, out var result)) - return result; + foreach (var location in symbol.Locations) + { + var syntaxTree = location.SourceTree; + if (syntaxTree is not null && options.TryGetConfigurationValue(syntaxTree, key, out value)) + return true; + } - return defaultValue; + value = null; + return false; } - private static bool? ChangeType(string value, bool? defaultValue) + private static bool ChangeType(string value, bool defaultValue) { if (value is not null && bool.TryParse(value, out var result)) return result; @@ -135,4 +112,46 @@ private static int ChangeType(string value, int defaultValue) return defaultValue; } + + private static T ChangeType(string value, ConfigurationDefinition configuration) + { + if (!configuration.HasDefaultValue) + throw new InvalidOperationException($"Configuration value for '{configuration.Key}' is not set and has no default value."); + + return ChangeType(value, configuration.Key, configuration.DefaultValue); + } + + private static T ChangeType(string value, string configurationKey, T defaultValue) + { + if (typeof(T) == typeof(bool)) + { + if (defaultValue is bool boolDefaultValue) + return (T)(object)ChangeType(value, boolDefaultValue); + + throw new InvalidOperationException($"Configuration value for '{configurationKey}' has an invalid default value."); + } + + if (typeof(T) == typeof(int)) + { + if (defaultValue is int intDefaultValue) + return (T)(object)ChangeType(value, intDefaultValue); + + throw new InvalidOperationException($"Configuration value for '{configurationKey}' has an invalid default value."); + } + + if (typeof(T) == typeof(string)) + { + return (T)(object)value; + } + + if (typeof(T) == typeof(ReportDiagnostic?)) + { + if (value is not null && Enum.TryParse(value, ignoreCase: true, out var result)) + return (T)(object)result; + + return defaultValue; + } + + throw new NotSupportedException($"Configuration value for '{configurationKey}' has an unsupported type '{typeof(T)}'."); + } } diff --git a/src/Meziantou.Analyzer/Configurations/ConfigurationDefinition.cs b/src/Meziantou.Analyzer/Configurations/ConfigurationDefinition.cs new file mode 100644 index 000000000..900a595a7 --- /dev/null +++ b/src/Meziantou.Analyzer/Configurations/ConfigurationDefinition.cs @@ -0,0 +1,24 @@ +using Microsoft.CodeAnalysis.Operations; + +namespace Meziantou.Analyzer.Configurations; + +public sealed class ConfigurationDefinition +{ + public ConfigurationDefinition(string key) + { + Key = key; + HasDefaultValue = false; + } + + public ConfigurationDefinition(string key, T defaultValue) + { + Key = key; + DefaultValue = defaultValue; + HasDefaultValue = true; + } + + public string Key { get; } + public bool HasDefaultValue { get; } + public T DefaultValue { get; } = default!; + public bool IsHidden { get; set; } +} \ No newline at end of file diff --git a/src/Meziantou.Analyzer/Rules/ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs b/src/Meziantou.Analyzer/Rules/ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs index ea304e246..aa9c95110 100644 --- a/src/Meziantou.Analyzer/Rules/ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs @@ -31,6 +31,8 @@ public sealed partial class ArgumentExceptionShouldSpecifyArgumentNameAnalyzer : description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseNameofOperator)); + private static readonly ConfigurationDefinition ConsiderMemberAccessAsParameterConfiguration = new(RuleIdentifiers.ArgumentExceptionShouldSpecifyArgumentName + ".consider_member_access_as_parameter", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule, NameofRule); public override void Initialize(AnalysisContext context) @@ -208,7 +210,7 @@ public void AnalyzeInvocation(OperationAnalysisContext context) } private static bool ConsiderMemberAccessAsParameter(OperationAnalysisContext context, IOperation operation) - => context.Options.GetConfigurationValue(operation, RuleIdentifiers.ArgumentExceptionShouldSpecifyArgumentName + ".consider_member_access_as_parameter", defaultValue: false); + => context.Options.GetConfigurationValue(operation, ConsiderMemberAccessAsParameterConfiguration); private static void ValidateParamNameArgument(OperationAnalysisContext context, IArgumentOperation paramNameArgument) { diff --git a/src/Meziantou.Analyzer/Rules/AwaitAwaitableMethodInSyncMethodAnalyzer.cs b/src/Meziantou.Analyzer/Rules/AwaitAwaitableMethodInSyncMethodAnalyzer.cs index 162dfa9fb..ad04bfe2a 100644 --- a/src/Meziantou.Analyzer/Rules/AwaitAwaitableMethodInSyncMethodAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/AwaitAwaitableMethodInSyncMethodAnalyzer.cs @@ -10,7 +10,7 @@ namespace Meziantou.Analyzer.Rules; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class AwaitAwaitableMethodInSyncMethodAnalyzer : DiagnosticAnalyzer { - private const string ReportDiscardedConfigurationKey = RuleIdentifiers.AwaitAwaitableMethodInSyncMethod + ".report_discarded"; + private static readonly ConfigurationDefinition ReportDiscardedConfiguration = new(RuleIdentifiers.AwaitAwaitableMethodInSyncMethod + ".report_discarded", defaultValue: false); private static readonly DiagnosticDescriptor Rule = new( RuleIdentifiers.AwaitAwaitableMethodInSyncMethod, @@ -42,7 +42,7 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeOperation(OperationAnalysisContext context, OperationUtilities operationUtilities, AwaitableTypes awaitableTypes) { var operation = (IInvocationOperation)context.Operation; - var reportDiscarded = context.Options.GetConfigurationValue(operation, ReportDiscardedConfigurationKey, defaultValue: false); + var reportDiscarded = context.Options.GetConfigurationValue(operation, ReportDiscardedConfiguration); var parent = operation.Parent; diff --git a/src/Meziantou.Analyzer/Rules/ClassMustBeSealedAnalyzer.cs b/src/Meziantou.Analyzer/Rules/ClassMustBeSealedAnalyzer.cs index 02e3c014b..23244ba9f 100644 --- a/src/Meziantou.Analyzer/Rules/ClassMustBeSealedAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/ClassMustBeSealedAnalyzer.cs @@ -19,6 +19,11 @@ public sealed class ClassMustBeSealedAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.ClassMustBeSealed)); + private static readonly ConfigurationDefinition ExceptionsShouldBeSealedConfiguration = new(RuleIdentifiers.ClassMustBeSealed + ".exceptions_should_be_sealed", defaultValue: false); + private static readonly ConfigurationDefinition PublicClassShouldBeSealedConfiguration = new(RuleIdentifiers.ClassMustBeSealed + ".public_class_should_be_sealed", defaultValue: false); + private static readonly ConfigurationDefinition ClassWithVirtualMemberShoudBeSealedConfiguration = new(RuleIdentifiers.ClassMustBeSealed + ".class_with_virtual_member_shoud_be_sealed", defaultValue: false) { IsHidden = true }; + private static readonly ConfigurationDefinition ClassWithVirtualMemberShouldBeSealedConfiguration = new(RuleIdentifiers.ClassMustBeSealed + ".class_with_virtual_member_should_be_sealed", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -119,18 +124,18 @@ private bool IsPotentialSealed(AnalyzerOptions options, INamedTypeSymbol symbol, private static bool ExceptionClassShouldBeSealed(AnalyzerOptions options, ISymbol symbol) { - return options.GetConfigurationValue(symbol, RuleIdentifiers.ClassMustBeSealed + ".exceptions_should_be_sealed", defaultValue: false); + return options.GetConfigurationValue(symbol, ExceptionsShouldBeSealedConfiguration); } private static bool PublicClassShouldBeSealed(AnalyzerOptions options, ISymbol symbol) { - return options.GetConfigurationValue(symbol, RuleIdentifiers.ClassMustBeSealed + ".public_class_should_be_sealed", defaultValue: false); + return options.GetConfigurationValue(symbol, PublicClassShouldBeSealedConfiguration); } private static bool SealedClassWithVirtualMember(AnalyzerOptions options, ISymbol symbol) { - var defaultValue = options.GetConfigurationValue(symbol, RuleIdentifiers.ClassMustBeSealed + ".class_with_virtual_member_shoud_be_sealed", defaultValue: false); - return options.GetConfigurationValue(symbol, RuleIdentifiers.ClassMustBeSealed + ".class_with_virtual_member_should_be_sealed", defaultValue); + var defaultValue = options.GetConfigurationValue(symbol, ClassWithVirtualMemberShoudBeSealedConfiguration); + return options.GetConfigurationValue(symbol, ClassWithVirtualMemberShouldBeSealedConfiguration, defaultValue); } } } diff --git a/src/Meziantou.Analyzer/Rules/CommaAnalyzer.cs b/src/Meziantou.Analyzer/Rules/CommaAnalyzer.cs index cea33d14c..417d5ebd4 100644 --- a/src/Meziantou.Analyzer/Rules/CommaAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/CommaAnalyzer.cs @@ -21,6 +21,8 @@ public sealed class CommaAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.MissingCommaInObjectInitializer)); + private static readonly ConfigurationDefinition IgnoreCatchAllArmConfiguration = new(Rule.Id + ".IgnoreCatchAllArm", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); private static readonly ImmutableArray ObjectInitializerKinds = ImmutableArray.Create(SyntaxKind.ObjectInitializerExpression, SyntaxKind.ArrayInitializerExpression, SyntaxKind.CollectionInitializerExpression); @@ -75,7 +77,7 @@ private void HandleCollectionExpression(SyntaxNodeAnalysisContext context) private void HandleSwitchExpression(SyntaxNodeAnalysisContext context) { var node = (SwitchExpressionSyntax)context.Node; - var options = context.Options.GetConfigurationValue(node, Rule.Id + ".IgnoreCatchAllArm", defaultValue: false); + var options = context.Options.GetConfigurationValue(node, IgnoreCatchAllArmConfiguration); if (options is true) { var last = node.Arms.LastOrDefault(); diff --git a/src/Meziantou.Analyzer/Rules/DoNotLogClassifiedDataAnalyzer.cs b/src/Meziantou.Analyzer/Rules/DoNotLogClassifiedDataAnalyzer.cs index 78cb5dc25..3f583328b 100644 --- a/src/Meziantou.Analyzer/Rules/DoNotLogClassifiedDataAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/DoNotLogClassifiedDataAnalyzer.cs @@ -20,6 +20,8 @@ public sealed class DoNotLogClassifiedDataAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotLogClassifiedData)); + private static readonly ConfigurationDefinition ReportTypesWithDataClassificationAttributesConfiguration = new(RuleIdentifiers.DoNotLogClassifiedData + ".report_types_with_data_classification_attributes", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -62,7 +64,7 @@ public void AnalyzeInvocationDeclaration(OperationAnalysisContext context) var operation = (IInvocationOperation)context.Operation; if (operation.TargetMethod.ContainingType.IsEqualTo(LoggerExtensionsSymbol) && FindLogParameters(operation.TargetMethod, out var argumentsParameter)) { - var reportTypesWithDataClassification = context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotLogClassifiedData + ".report_types_with_data_classification_attributes", defaultValue: false); + var reportTypesWithDataClassification = context.Options.GetConfigurationValue(operation, ReportTypesWithDataClassificationAttributesConfiguration); foreach (var argument in operation.Arguments) { diff --git a/src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs b/src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs index 7cc0de523..1c74f01ee 100755 --- a/src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/DoNotUseBlockingCallInAsyncContextAnalyzer.cs @@ -31,6 +31,11 @@ public sealed class DoNotUseBlockingCallInAsyncContextAnalyzer : DiagnosticAnaly description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotUseBlockingCall)); + private static readonly ConfigurationDefinition EnableSqliteSpecialCasesInAsyncContextConfiguration = new(RuleIdentifiers.DoNotUseBlockingCallInAsyncContext + ".enable_sqlite_special_cases", defaultValue: true); + private static readonly ConfigurationDefinition EnableSqliteSpecialCasesConfiguration = new(RuleIdentifiers.DoNotUseBlockingCall + ".enable_sqlite_special_cases", defaultValue: true); + private static readonly ConfigurationDefinition EnableDbSpecialCasesInAsyncContextConfiguration = new(RuleIdentifiers.DoNotUseBlockingCallInAsyncContext + ".enable_db_special_cases", defaultValue: true); + private static readonly ConfigurationDefinition EnableDbSpecialCasesConfiguration = new(RuleIdentifiers.DoNotUseBlockingCall + ".enable_db_special_cases", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule, Rule2); public override void Initialize(AnalysisContext context) @@ -332,14 +337,14 @@ private bool HasAsyncEquivalent(IInvocationOperation operation, bool sqliteSpeci private static bool IsSqliteSpecialCasesEnabled(OperationAnalysisContext context, IOperation operation) { - var defaultValue = context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseBlockingCallInAsyncContext + ".enable_sqlite_special_cases", defaultValue: true); - return context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseBlockingCall + ".enable_sqlite_special_cases", defaultValue); + var defaultValue = context.Options.GetConfigurationValue(operation, EnableSqliteSpecialCasesInAsyncContextConfiguration); + return context.Options.GetConfigurationValue(operation, EnableSqliteSpecialCasesConfiguration, defaultValue); } private static bool IsDbSpecialCasesEnabled(OperationAnalysisContext context, IOperation operation) { - var defaultValue = context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseBlockingCallInAsyncContext + ".enable_db_special_cases", defaultValue: true); - return context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseBlockingCall + ".enable_db_special_cases", defaultValue); + var defaultValue = context.Options.GetConfigurationValue(operation, EnableDbSpecialCasesInAsyncContextConfiguration); + return context.Options.GetConfigurationValue(operation, EnableDbSpecialCasesConfiguration, defaultValue); } private static HashSet CreateExcludedDiagnosticSymbols(Compilation compilation) diff --git a/src/Meziantou.Analyzer/Rules/DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs b/src/Meziantou.Analyzer/Rules/DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs index 6010717e3..be7d7c570 100644 --- a/src/Meziantou.Analyzer/Rules/DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs @@ -41,6 +41,11 @@ public sealed class DoNotUseImplicitCultureSensitiveToStringAnalyzer : Diagnosti description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotUseCultureSensitiveObjectToString)); + private static readonly ConfigurationDefinition StringConcatConsiderNullableTypesConfiguration = new(RuleIdentifiers.DoNotUseImplicitCultureSensitiveToString + ".consider_nullable_types", defaultValue: true); + private static readonly ConfigurationDefinition StringInterpolationConsiderNullableTypesConfiguration = new(RuleIdentifiers.DoNotUseImplicitCultureSensitiveToStringInterpolation + ".consider_nullable_types", defaultValue: true); + private static readonly ConfigurationDefinition ExcludeToStringMethodsConfiguration = new(RuleIdentifiers.DoNotUseImplicitCultureSensitiveToString + ".exclude_tostring_methods", defaultValue: true); + private static readonly ConfigurationDefinition ExcludeToStringMethodsInterpolationConfiguration = new(RuleIdentifiers.DoNotUseImplicitCultureSensitiveToStringInterpolation + ".exclude_tostring_methods", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(StringConcatRule, StringInterpolationRule, ObjectToStringRule); public override void Initialize(AnalysisContext context) @@ -66,7 +71,7 @@ private sealed class AnalyzerContext(Compilation compilation) public static void AnalyzeInvocation(OperationAnalysisContext context) { var operation = (IInvocationOperation)context.Operation; - if (IsExcludedMethod(context, ObjectToStringRule, operation)) + if (IsExcludedMethod(context, ExcludeToStringMethodsConfiguration, operation)) return; if (operation.TargetMethod.Name == "ToString" && operation.TargetMethod.ContainingType.IsObject() && operation.TargetMethod.Parameters.Length == 0) @@ -90,7 +95,7 @@ public void AnalyzeBinaryOperation(OperationAnalysisContext context) if (operation.ConstantValue.HasValue) return; - if (IsExcludedMethod(context, StringConcatRule, operation)) + if (IsExcludedMethod(context, ExcludeToStringMethodsConfiguration, operation)) return; if (!IsNonCultureSensitiveOperand(context, StringConcatRule, operation.LeftOperand)) @@ -112,7 +117,7 @@ public void AnalyzeInterpolatedString(OperationAnalysisContext context) if (operation.ConstantValue.HasValue) return; - if (IsExcludedMethod(context, StringInterpolationRule, operation)) + if (IsExcludedMethod(context, ExcludeToStringMethodsInterpolationConfiguration, operation)) return; var options = MustUnwrapNullableTypes(context, StringInterpolationRule, operation) ? CultureSensitiveOptions.UnwrapNullableOfT : CultureSensitiveOptions.None; @@ -139,12 +144,12 @@ public void AnalyzeInterpolatedString(OperationAnalysisContext context) } } - private static bool IsExcludedMethod(OperationAnalysisContext context, DiagnosticDescriptor descriptor, IOperation operation) + private static bool IsExcludedMethod(OperationAnalysisContext context, ConfigurationDefinition configuration, IOperation operation) { // ToString show culture-sensitive data by default if (operation?.GetContainingMethod(context.CancellationToken)?.Name == "ToString") { - return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, descriptor.Id + ".exclude_tostring_methods", defaultValue: true); + return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, configuration); } return false; @@ -173,12 +178,12 @@ private static bool MustUnwrapNullableTypes(OperationAnalysisContext context, Di if (StringConcatRule.Equals(rule)) { Debug.Assert(rule.Id == RuleIdentifiers.DoNotUseImplicitCultureSensitiveToString); - return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, RuleIdentifiers.DoNotUseImplicitCultureSensitiveToString + ".consider_nullable_types", defaultValue: true); + return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, StringConcatConsiderNullableTypesConfiguration); } else if (StringInterpolationRule.Equals(rule)) { Debug.Assert(rule.Id == RuleIdentifiers.DoNotUseImplicitCultureSensitiveToStringInterpolation); - return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, RuleIdentifiers.DoNotUseImplicitCultureSensitiveToStringInterpolation + ".consider_nullable_types", defaultValue: true); + return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, StringInterpolationConsiderNullableTypesConfiguration); } return false; diff --git a/src/Meziantou.Analyzer/Rules/DoNotUseUnknownParameterForRazorComponentAnalyzer.cs b/src/Meziantou.Analyzer/Rules/DoNotUseUnknownParameterForRazorComponentAnalyzer.cs index c176ed5f4..0a90b2f3b 100644 --- a/src/Meziantou.Analyzer/Rules/DoNotUseUnknownParameterForRazorComponentAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/DoNotUseUnknownParameterForRazorComponentAnalyzer.cs @@ -21,6 +21,8 @@ public sealed class DoNotUseUnknownParameterForRazorComponentAnalyzer : Diagnost description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotUseUnknownParameterForRazorComponent)); + private static readonly ConfigurationDefinition ReportPascalCaseUnmatchedParameterConfiguration = new("MA0115.ReportPascalCaseUnmatchedParameter", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -81,7 +83,7 @@ public void AnalyzeBlockOptions(OperationAnalysisContext context) var value = invocation.Arguments[1].Value.ConstantValue; if (value.HasValue && value.Value is string parameterName) { - var reportPascalCaseUnmatchedParameter = context.Options.GetConfigurationValue(operation, "MA0115.ReportPascalCaseUnmatchedParameter", defaultValue: true); + var reportPascalCaseUnmatchedParameter = context.Options.GetConfigurationValue(operation, ReportPascalCaseUnmatchedParameterConfiguration); if (!IsValidAttribute(currentComponent, parameterName, reportPascalCaseUnmatchedParameter)) { var availableParameters = string.Join(", ", GetComponentDescriptor(currentComponent).Parameters.Order(StringComparer.Ordinal)); diff --git a/src/Meziantou.Analyzer/Rules/DoNotUseZeroToInitializeAnEnumValue.cs b/src/Meziantou.Analyzer/Rules/DoNotUseZeroToInitializeAnEnumValue.cs index 2265c8ef4..50916a0b0 100644 --- a/src/Meziantou.Analyzer/Rules/DoNotUseZeroToInitializeAnEnumValue.cs +++ b/src/Meziantou.Analyzer/Rules/DoNotUseZeroToInitializeAnEnumValue.cs @@ -21,6 +21,9 @@ public class DoNotUseZeroToInitializeAnEnumValue : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DoNotUseZeroToInitializeAnEnumValue)); + private static readonly ConfigurationDefinition ReportOnConfiguration = new(RuleIdentifiers.DoNotUseZeroToInitializeAnEnumValue + ".report_on", defaultValue: "all"); + private static readonly ConfigurationDefinition ExcludeEnumWithoutZeroMemberConfiguration = new(RuleIdentifiers.DoNotUseZeroToInitializeAnEnumValue + ".exclude_enum_without_zero_member", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -54,14 +57,14 @@ private static void AnalyzeConversion(OperationAnalysisContext context) if (operation.ConstantValue is not { HasValue: true, Value: not null and var value } || !IsZero(enumType, value)) return; - var reportOn = context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseZeroToInitializeAnEnumValue + ".report_on", defaultValue: "all"); + var reportOn = context.Options.GetConfigurationValue(operation, ReportOnConfiguration); if (string.Equals(reportOn, "argument", StringComparison.OrdinalIgnoreCase)) { if (operation.Parent is not IArgumentOperation) return; } - var excludeEnumWithoutZeroMember = context.Options.GetConfigurationValue(operation, RuleIdentifiers.DoNotUseZeroToInitializeAnEnumValue + ".exclude_enum_without_zero_member", defaultValue: false); + var excludeEnumWithoutZeroMember = context.Options.GetConfigurationValue(operation, ExcludeEnumWithoutZeroMemberConfiguration); if (excludeEnumWithoutZeroMember && !HasZeroMember(enumSymbol, enumType)) return; diff --git a/src/Meziantou.Analyzer/Rules/DotNotUseNameFromBCLAnalyzer.cs b/src/Meziantou.Analyzer/Rules/DotNotUseNameFromBCLAnalyzer.cs index deb854e4c..c10718506 100644 --- a/src/Meziantou.Analyzer/Rules/DotNotUseNameFromBCLAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/DotNotUseNameFromBCLAnalyzer.cs @@ -20,6 +20,11 @@ public class DotNotUseNameFromBCLAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.DotNotUseNameFromBCL)); + private static readonly ConfigurationDefinition OnlyConsiderPublicSymbolsConfiguration = new(RuleIdentifiers.DotNotUseNameFromBCL + ".only_consider_public_symbols", defaultValue: true); + private static readonly ConfigurationDefinition UsePreviewTypesConfiguration = new(RuleIdentifiers.DotNotUseNameFromBCL + ".use_preview_types", defaultValue: false); + private static readonly ConfigurationDefinition NamespacesRegexConfiguration = new(RuleIdentifiers.DotNotUseNameFromBCL + ".namespaces_regex", defaultValue: "^System($|\\.)"); + private static readonly ConfigurationDefinition LegacyNamepacesRegexConfiguration = new(RuleIdentifiers.DotNotUseNameFromBCL + ".namepaces_regex", defaultValue: "^System($|\\.)") { IsHidden = true }; + private static Dictionary>? s_types; private static Dictionary>? s_typesPreview; @@ -44,15 +49,20 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) if (!symbol.IsVisibleOutsideOfAssembly()) { - if (context.Options.GetConfigurationValue(symbol, RuleIdentifiers.DotNotUseNameFromBCL + ".only_consider_public_symbols", defaultValue: true)) + if (context.Options.GetConfigurationValue(symbol, OnlyConsiderPublicSymbolsConfiguration)) return; } - var usePreviewTypes = context.Options.GetConfigurationValue(symbol, RuleIdentifiers.DotNotUseNameFromBCL + ".use_preview_types", defaultValue: false); + var usePreviewTypes = context.Options.GetConfigurationValue(symbol, UsePreviewTypesConfiguration); var types = usePreviewTypes ? s_typesPreview : s_types; if (types!.TryGetValue(symbol.MetadataName, out var namespaces)) { - var regex = context.Options.GetConfigurationValue(symbol, RuleIdentifiers.DotNotUseNameFromBCL + ".namespaces_regex", context.Options.GetConfigurationValue(symbol, RuleIdentifiers.DotNotUseNameFromBCL + ".namepaces_regex", "^System($|\\.)")); + var regex = context.Options.GetConfigurationValue(symbol, LegacyNamepacesRegexConfiguration); + if (context.Options.TryGetConfigurationValue(symbol, NamespacesRegexConfiguration, out var configuredRegex)) + { + regex = configuredRegex; + } + var namespaceRegex = RegexCache.GetOrCreate(regex, RegexOptions.None, Timeout.InfiniteTimeSpan); foreach (var ns in namespaces) { diff --git a/src/Meziantou.Analyzer/Rules/FileNameMustMatchTypeNameAnalyzer.cs b/src/Meziantou.Analyzer/Rules/FileNameMustMatchTypeNameAnalyzer.cs index d340eded3..7b6052438 100644 --- a/src/Meziantou.Analyzer/Rules/FileNameMustMatchTypeNameAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/FileNameMustMatchTypeNameAnalyzer.cs @@ -30,6 +30,16 @@ private enum TypeNameMatchMode description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.FileNameMustMatchTypeName)); + private static readonly ConfigurationDefinition ExcludedSymbolNamesConfiguration = new("dotnet_diagnostic." + Rule.Id + ".excluded_symbol_names", defaultValue: string.Empty); +#if ROSLYN_4_4_OR_GREATER + private static readonly ConfigurationDefinition ExcludeFileLocalTypesConfiguration = new(Rule.Id + ".exclude_file_local_types", defaultValue: true); +#endif + private static readonly ConfigurationDefinition OnlyValidateFirstTypeConfiguration = new(Rule.Id + ".only_validate_first_type", defaultValue: false); + private static readonly ConfigurationDefinition AllowOfTForAllGenericTypesConfiguration = new(Rule.Id + ".allow_oft_for_all_generic_types", defaultValue: false); + private static readonly ConfigurationDefinition ModeConfiguration = new(Rule.Id + ".mode", defaultValue: string.Empty); + private static readonly ConfigurationDefinition AllowTypeNamePrefixConfiguration = new(Rule.Id + ".allow_type_name_prefix", defaultValue: false); + private static readonly ConfigurationDefinition UseLongestTypeNamePrefixConfiguration = new(Rule.Id + ".use_longest_type_name_prefix", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -58,14 +68,14 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) var typeNameMatchMode = GetTypeNameMatchMode(context, location.SourceTree); #if ROSLYN_4_4_OR_GREATER - if (symbol.IsFileLocal && context.Options.GetConfigurationValue(location.SourceTree, Rule.Id + ".exclude_file_local_types", defaultValue: true)) + if (symbol.IsFileLocal && context.Options.GetConfigurationValue(location.SourceTree, ExcludeFileLocalTypesConfiguration)) continue; #endif var symbolName = symbol.Name; // dotnet_diagnostic.MA0048.excluded_symbol_names - var excludedSymbolNames = context.Options.GetConfigurationValue(location.SourceTree, "dotnet_diagnostic." + Rule.Id + ".excluded_symbol_names", defaultValue: string.Empty); + var excludedSymbolNames = context.Options.GetConfigurationValue(location.SourceTree, ExcludedSymbolNamesConfiguration); if (!string.IsNullOrEmpty(excludedSymbolNames)) { var symbolDeclarationId = DocumentationCommentId.CreateDeclarationId(symbol); @@ -84,7 +94,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) } // MA0048.only_validate_first_type - if (context.Options.GetConfigurationValue(location.SourceTree, Rule.Id + ".only_validate_first_type", defaultValue: false)) + if (context.Options.GetConfigurationValue(location.SourceTree, OnlyValidateFirstTypeConfiguration)) { var root = location.SourceTree.GetRoot(context.CancellationToken); var symbolNode = root.FindNode(location.SourceSpan); @@ -130,7 +140,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) continue; } - if (symbol.Arity == 1 || (symbol.Arity > 1 && context.Options.GetConfigurationValue(location.SourceTree, Rule.Id + ".allow_oft_for_all_generic_types", defaultValue: false))) + if (symbol.Arity == 1 || (symbol.Arity > 1 && context.Options.GetConfigurationValue(location.SourceTree, AllowOfTForAllGenericTypesConfiguration))) { // TypeOfT if (fileName.Equals((symbolName + "OfT").AsSpan(), StringComparison.OrdinalIgnoreCase)) @@ -158,7 +168,7 @@ private static ReadOnlySpan GetFileName(ReadOnlySpan filePath) private static TypeNameMatchMode GetTypeNameMatchMode(SymbolAnalysisContext context, SyntaxTree sourceTree) { - var mode = context.Options.GetConfigurationValue(sourceTree, Rule.Id + ".mode", defaultValue: string.Empty); + var mode = context.Options.GetConfigurationValue(sourceTree, ModeConfiguration); if (mode.Equals(nameof(TypeNameMatchMode.Exact), StringComparison.OrdinalIgnoreCase)) return TypeNameMatchMode.Exact; @@ -169,10 +179,10 @@ private static TypeNameMatchMode GetTypeNameMatchMode(SymbolAnalysisContext cont return TypeNameMatchMode.LongestCommonPrefix; // Backward compatibility - if (!context.Options.GetConfigurationValue(sourceTree, Rule.Id + ".allow_type_name_prefix", defaultValue: false)) + if (!context.Options.GetConfigurationValue(sourceTree, AllowTypeNamePrefixConfiguration)) return TypeNameMatchMode.Exact; - return context.Options.GetConfigurationValue(sourceTree, Rule.Id + ".use_longest_type_name_prefix", defaultValue: false) + return context.Options.GetConfigurationValue(sourceTree, UseLongestTypeNamePrefixConfiguration) ? TypeNameMatchMode.LongestCommonPrefix : TypeNameMatchMode.Prefix; } @@ -218,7 +228,7 @@ private static bool IsLongestTypeNamePrefix(SymbolAnalysisContext context, Synta List? typeNames = null; #if ROSLYN_4_4_OR_GREATER - var excludeFileLocalTypes = context.Options.GetConfigurationValue(sourceTree, Rule.Id + ".exclude_file_local_types", defaultValue: true); + var excludeFileLocalTypes = context.Options.GetConfigurationValue(sourceTree, ExcludeFileLocalTypesConfiguration); #endif foreach (var node in root.DescendantNodesAndSelf(descendIntoChildren: static node => !IsTypeDeclaration(node))) diff --git a/src/Meziantou.Analyzer/Rules/LoggerParameterTypeAnalyzer.cs b/src/Meziantou.Analyzer/Rules/LoggerParameterTypeAnalyzer.cs index 2bb71b0a2..0d8f70d81 100644 --- a/src/Meziantou.Analyzer/Rules/LoggerParameterTypeAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/LoggerParameterTypeAnalyzer.cs @@ -63,6 +63,9 @@ public sealed class LoggerParameterTypeAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.LoggerParameterType_MissingConfiguration)); + private static readonly ConfigurationDefinition AllowNonConstantFormatConfiguration = new(Rule.Id + ".allow_non_constant_formats", defaultValue: true); + private static readonly ConfigurationDefinition AllowNonConstantFormatSerilogConfiguration = new(RuleSerilog.Id + ".allow_non_constant_formats", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule, RuleSerilog, RuleInvalid, RuleDuplicate, RuleMissingConfiguration); public override void Initialize(AnalysisContext context) @@ -442,9 +445,8 @@ static int FindIndexOfTemplate(ImmutableArray arguments) if (formatExpression is not null && argumentTypes is not null) { - var diagnosticDescriptor = isSerilog ? RuleSerilog : Rule; - - var allowNonConstantFormat = context.Options.GetConfigurationValue(formatExpression, diagnosticDescriptor.Id + ".allow_non_constant_formats", defaultValue: true); + var configuration = isSerilog ? AllowNonConstantFormatSerilogConfiguration : AllowNonConstantFormatConfiguration; + var allowNonConstantFormat = context.Options.GetConfigurationValue(formatExpression, configuration); var format = TryGetFormatText(formatExpression, allowNonConstantFormat); if (format is null) return; diff --git a/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs b/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs index 9b30e3bd2..d707a4bee 100644 --- a/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/MethodShouldNotBeTooLongAnalyzer.cs @@ -21,6 +21,10 @@ public sealed class MethodShouldNotBeTooLongAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.MethodShouldNotBeTooLong)); + private static readonly ConfigurationDefinition SkipLocalFunctionsConfiguration = new(Rule.Id + ".skip_local_functions", defaultValue: false); + private static readonly ConfigurationDefinition MaximumStatementsPerMethodConfiguration = new(Rule.Id + ".maximum_statements_per_method", defaultValue: 40); + private static readonly ConfigurationDefinition MaximumLinesPerMethodConfiguration = new(Rule.Id + ".maximum_lines_per_method", defaultValue: 60); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -169,7 +173,7 @@ static bool IsCountableStatement(StatementSyntax statement) private static bool GetSkipLocalFunctions(SyntaxNodeAnalysisContext context) { var syntaxTree = context.Node?.SyntaxTree; - if (syntaxTree is not null && context.Options is not null && context.Options.GetConfigurationValue(syntaxTree, $"{Rule.Id}.skip_local_functions", defaultValue: false)) + if (syntaxTree is not null && context.Options is not null && context.Options.GetConfigurationValue(syntaxTree, SkipLocalFunctionsConfiguration)) return true; return false; @@ -178,12 +182,12 @@ private static bool GetSkipLocalFunctions(SyntaxNodeAnalysisContext context) private static int GetMaximumNumberOfStatements(SyntaxNodeAnalysisContext context) { var syntaxTree = context.Node.SyntaxTree; - return context.Options.GetConfigurationValue(syntaxTree, $"{Rule.Id}.maximum_statements_per_method", defaultValue: 40); + return context.Options.GetConfigurationValue(syntaxTree, MaximumStatementsPerMethodConfiguration); } private static int GetMaximumNumberOfLines(SyntaxNodeAnalysisContext context) { var syntaxTree = context.Node.SyntaxTree; - return context.Options.GetConfigurationValue(syntaxTree, $"{Rule.Id}.maximum_lines_per_method", 60); + return context.Options.GetConfigurationValue(syntaxTree, MaximumLinesPerMethodConfiguration); } } diff --git a/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs b/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs index 94c2bb567..d191c3937 100644 --- a/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyzer.cs @@ -50,6 +50,9 @@ public sealed class MethodsReturningAnAwaitableTypeMustHaveTheAsyncSuffixAnalyze description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.MethodsNotReturningIAsyncEnumerableMustNotHaveTheAsyncSuffix)); + private static readonly ConfigurationDefinition ExcludeTestMethodsConfiguration = new("MA0137.exclude_test_methods", defaultValue: true); + private static readonly ConfigurationDefinition ExcludePropertyAccessorsConfiguration = new("MA0137.exclude_property_accessors", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(AsyncSuffixRule, NotAsyncSuffixRule, AsyncSuffixRuleAsyncEnumerable, NotAsyncSuffixRuleAsyncEnumerable); public override void Initialize(AnalysisContext context) @@ -158,13 +161,13 @@ private bool MustIgnoreSymbol(AnalyzerOptions options, IMethodSymbol symbol) if (symbol.HasAttribute(_benchmarkSymbol)) return true; - var excludeTestMethods = options.GetConfigurationValue(symbol, "MA0137.exclude_test_methods", defaultValue: true); + var excludeTestMethods = options.GetConfigurationValue(symbol, ExcludeTestMethodsConfiguration); if (excludeTestMethods && symbol.IsUnitTestMethod()) return true; if (symbol.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove) { - var excludePropertyAccessors = options.GetConfigurationValue(symbol, "MA0137.exclude_property_accessors", defaultValue: true); + var excludePropertyAccessors = options.GetConfigurationValue(symbol, ExcludePropertyAccessorsConfiguration); if (excludePropertyAccessors) return true; } diff --git a/src/Meziantou.Analyzer/Rules/NamedParameterAnalyzer.cs b/src/Meziantou.Analyzer/Rules/NamedParameterAnalyzer.cs index 5aeb795c8..163353013 100644 --- a/src/Meziantou.Analyzer/Rules/NamedParameterAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/NamedParameterAnalyzer.cs @@ -15,10 +15,6 @@ namespace Meziantou.Analyzer.Rules; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed partial class NamedParameterAnalyzer : DiagnosticAnalyzer { - private const string ExcludedMethodsRegexConfigurationKey = RuleIdentifiers.UseNamedParameter + ".excluded_methods_regex"; - private const string ExcludedMethodsConfigurationKey = RuleIdentifiers.UseNamedParameter + ".excluded_methods"; - private const string MinimumMethodParametersConfigurationKey = RuleIdentifiers.UseNamedParameter + ".minimum_method_parameters"; - private const string ExpressionKindsConfigurationKey = RuleIdentifiers.UseNamedParameter + ".expression_kinds"; private const ArgumentExpressionKinds DefaultExpressionKinds = ArgumentExpressionKinds.Null | ArgumentExpressionKinds.Boolean; private static readonly DiagnosticDescriptor Rule = new( @@ -31,6 +27,11 @@ public sealed partial class NamedParameterAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseNamedParameter)); + private static readonly ConfigurationDefinition ExcludedMethodsRegexConfiguration = new(RuleIdentifiers.UseNamedParameter + ".excluded_methods_regex"); + private static readonly ConfigurationDefinition ExcludedMethodsConfiguration = new(RuleIdentifiers.UseNamedParameter + ".excluded_methods"); + private static readonly ConfigurationDefinition MinimumMethodParametersConfiguration = new(RuleIdentifiers.UseNamedParameter + ".minimum_method_parameters", defaultValue: string.Empty); + private static readonly ConfigurationDefinition ExpressionKindsConfiguration = new(RuleIdentifiers.UseNamedParameter + ".expression_kinds", defaultValue: string.Empty); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -279,7 +280,7 @@ bool IsParams(SyntaxNode node) if (operation is not null && !operation.GetCSharpLanguageVersion().IsCSharp14OrAbove() && operationUtilities.IsInExpressionContext(operation)) return; - if (syntaxContext.Options.TryGetConfigurationValue(expression.SyntaxTree, ExcludedMethodsRegexConfigurationKey, out var excludedMethodsRegex)) + if (syntaxContext.Options.TryGetConfigurationValue(expression.SyntaxTree, ExcludedMethodsRegexConfiguration, out var excludedMethodsRegex)) { var declarationId = DocumentationCommentId.CreateDeclarationId(invokedMethodSymbol); if (declarationId is not null) @@ -290,7 +291,7 @@ bool IsParams(SyntaxNode node) } } - if (syntaxContext.Options.TryGetConfigurationValue(expression.SyntaxTree, ExcludedMethodsConfigurationKey, out var excludedMethods)) + if (syntaxContext.Options.TryGetConfigurationValue(expression.SyntaxTree, ExcludedMethodsConfiguration, out var excludedMethods)) { var declarationId = DocumentationCommentId.CreateDeclarationId(invokedMethodSymbol); if (declarationId is not null) @@ -330,8 +331,8 @@ private static bool IsMethod(ISymbol? method, ITypeSymbol? containingType, strin private static int GetMinimumMethodArgumentsConfiguration(AnalyzerOptions analyzerOptions, SyntaxNode node) { - var options = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(node.SyntaxTree); - if (options.TryGetValue(MinimumMethodParametersConfigurationKey, out var value)) + var value = analyzerOptions.GetConfigurationValue(node.SyntaxTree, MinimumMethodParametersConfiguration); + if (!string.IsNullOrEmpty(value)) { if (int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var result)) return result; @@ -342,8 +343,8 @@ private static int GetMinimumMethodArgumentsConfiguration(AnalyzerOptions analyz private static ArgumentExpressionKinds GetExpressionKindsConfiguration(AnalyzerOptions analyzerOptions, SyntaxNode node) { - var options = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(node.SyntaxTree); - if (options.TryGetValue(ExpressionKindsConfigurationKey, out var value)) + var value = analyzerOptions.GetConfigurationValue(node.SyntaxTree, ExpressionKindsConfiguration); + if (!string.IsNullOrEmpty(value)) { var result = ArgumentExpressionKinds.None; foreach (var rawExpressionKind in value.Split([',', '|'], StringSplitOptions.RemoveEmptyEntries)) diff --git a/src/Meziantou.Analyzer/Rules/NonFlagsEnumsShouldNotBeMarkedWithFlagsAttributeAnalyzer.cs b/src/Meziantou.Analyzer/Rules/NonFlagsEnumsShouldNotBeMarkedWithFlagsAttributeAnalyzer.cs index b53a3f7d8..69608e028 100644 --- a/src/Meziantou.Analyzer/Rules/NonFlagsEnumsShouldNotBeMarkedWithFlagsAttributeAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/NonFlagsEnumsShouldNotBeMarkedWithFlagsAttributeAnalyzer.cs @@ -19,6 +19,8 @@ public sealed class NonFlagsEnumsShouldNotBeMarkedWithFlagsAttributeAnalyzer : D description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.NonFlagsEnumsShouldNotBeMarkedWithFlagsAttribute)); + private static readonly ConfigurationDefinition AllowAllBitsSetValueConfiguration = new(RuleIdentifiers.NonFlagsEnumsShouldNotBeMarkedWithFlagsAttribute + ".allow_all_bits_set_value", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -58,7 +60,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, ITypeSymbol fla if (member.IsSingleBitSet || member.IsZero) continue; - if (IsAllBitsSet(member.member.ConstantValue) && context.Options.GetConfigurationValue(member.member, RuleIdentifiers.NonFlagsEnumsShouldNotBeMarkedWithFlagsAttribute + ".allow_all_bits_set_value", defaultValue: false)) + if (IsAllBitsSet(member.member.ConstantValue) && context.Options.GetConfigurationValue(member.member, AllowAllBitsSetValueConfiguration)) continue; var value = member.member.ConstantValue!; diff --git a/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs b/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs index c60bffc84..12181af90 100755 --- a/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs @@ -102,6 +102,8 @@ public sealed class OptimizeLinqUsageAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.OptimizeEnumerable_UseOrder)); + private static readonly ConfigurationDefinition ReportWhenConversionNeededConfiguration = new(ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create( ListMethodsRule, IndexerInsteadOfElementAtRule, @@ -329,7 +331,7 @@ private void UseFindInsteadOfFirstOrDefault(OperationAnalysisContext context, II } else { - if (!context.Options.GetConfigurationValue(operation, ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false)) + if (!context.Options.GetConfigurationValue(operation, ReportWhenConversionNeededConfiguration)) return; properties = CreateProperties(OptimizeLinqUsageData.UseFindMethodWithConversion); @@ -360,7 +362,7 @@ private void UseTrueForAllInsteadOfAll(OperationAnalysisContext context, IInvoca } else { - if (!context.Options.GetConfigurationValue(operation, ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false)) + if (!context.Options.GetConfigurationValue(operation, ReportWhenConversionNeededConfiguration)) return; properties = CreateProperties(OptimizeLinqUsageData.UseTrueForAllMethodWithConversion); @@ -392,7 +394,7 @@ private void UseExistsInsteadOfAny(OperationAnalysisContext context, IInvocation } else { - if (!context.Options.GetConfigurationValue(operation, ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false)) + if (!context.Options.GetConfigurationValue(operation, ReportWhenConversionNeededConfiguration)) return; properties = CreateProperties(OptimizeLinqUsageData.UseExistsMethodWithConversion); diff --git a/src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasCancellationTokenAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasCancellationTokenAnalyzer.cs index dda8d39dc..bbbe578d1 100644 --- a/src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasCancellationTokenAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseAnOverloadThatHasCancellationTokenAnalyzer.cs @@ -54,6 +54,8 @@ public sealed class UseAnOverloadThatHasCancellationTokenAnalyzer : DiagnosticAn description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.FlowCancellationTokenInAwaitForEachWhenACancellationTokenIsAvailable)); + private static readonly ConfigurationDefinition AllowOverloadsWithOptionalParametersConfiguration = new("MA0032.allowOverloadsWithOptionalParameters", defaultValue: false); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(UseAnOverloadThatHasCancellationTokenRule, UseAnOverloadThatHasCancellationTokenWhenACancellationTokenIsAvailableRule, FlowCancellationTokenInAwaitForEachRule, FlowCancellationTokenInAwaitForEachRuleWhenACancellationTokenIsAvailableRule); public override void Initialize(AnalysisContext context) @@ -109,7 +111,7 @@ private bool HasAnOverloadWithCancellationToken(OperationAnalysisContext context if (IsArgumentImplicitlyDeclared(operation, CancellationTokenSymbol, out parameterInfo)) return true; - var allowOptionalParameters = context.Options.GetConfigurationValue(operation, "MA0032.allowOverloadsWithOptionalParameters", defaultValue: false); + var allowOptionalParameters = context.Options.GetConfigurationValue(operation, AllowOverloadsWithOptionalParametersConfiguration); var overload = _overloadFinder.FindOverloadWithAdditionalParameterOfType(operation, new OverloadOptions(AllowOptionalParameters: allowOptionalParameters), [CancellationTokenSymbol]); if (overload is not null) { diff --git a/src/Meziantou.Analyzer/Rules/UseConfigureAwaitAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseConfigureAwaitAnalyzer.cs index 95a204bc6..70909f308 100644 --- a/src/Meziantou.Analyzer/Rules/UseConfigureAwaitAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseConfigureAwaitAnalyzer.cs @@ -22,6 +22,8 @@ public sealed class UseConfigureAwaitAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseConfigureAwaitFalse)); + private static readonly ConfigurationDefinition ReportModeConfiguration = new(RuleIdentifiers.UseConfigureAwaitFalse + ".report", defaultValue: ""); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -211,7 +213,7 @@ private void AnalyzeVariableDeclarationGroupOperation(OperationAnalysisContext c private bool MustUseConfigureAwait(SemanticModel semanticModel, AnalyzerOptions options, SyntaxNode node, CancellationToken cancellationToken) { - var modeValue = options.GetConfigurationValue(node.SyntaxTree, RuleIdentifiers.UseConfigureAwaitFalse + ".report", ""); + var modeValue = options.GetConfigurationValue(node.SyntaxTree, ReportModeConfiguration); if (Enum.TryParse(modeValue, ignoreCase: true, out var mode)) { if (mode == ReportMode.Always) diff --git a/src/Meziantou.Analyzer/Rules/UseIFormatProviderAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseIFormatProviderAnalyzer.cs index 8793fceec..7415dbe4e 100644 --- a/src/Meziantou.Analyzer/Rules/UseIFormatProviderAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseIFormatProviderAnalyzer.cs @@ -21,6 +21,9 @@ public sealed class UseIFormatProviderAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseIFormatProviderParameter)); + private static readonly ConfigurationDefinition ExcludeToStringMethodsConfiguration = new(RuleIdentifiers.UseIFormatProviderParameter + ".exclude_tostring_methods", defaultValue: true); + private static readonly ConfigurationDefinition ConsiderNullableTypesConfiguration = new(RuleIdentifiers.UseIFormatProviderParameter + ".consider_nullable_types", defaultValue: true); + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -118,7 +121,7 @@ private static bool IsExcludedMethod(OperationAnalysisContext context, IInvocati // ToString show culture-sensitive data by default if (operation.GetContainingMethod(context.CancellationToken)?.Name == "ToString") { - return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, "MA0011.exclude_tostring_methods", defaultValue: true); + return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, ExcludeToStringMethodsConfiguration); } return false; @@ -126,7 +129,7 @@ private static bool IsExcludedMethod(OperationAnalysisContext context, IInvocati private static bool MustUnwrapNullableTypes(OperationAnalysisContext context, IOperation operation) { - return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, "MA0011.consider_nullable_types", defaultValue: true); + return context.Options.GetConfigurationValue(operation.Syntax.SyntaxTree, ConsiderNullableTypesConfiguration); } } } diff --git a/src/Meziantou.Analyzer/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzer.cs index c54fe9a67..61d4195a6 100644 --- a/src/Meziantou.Analyzer/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseInlineXmlCommentSyntaxWhenPossibleAnalyzer.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Meziantou.Analyzer.Configurations; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -8,6 +9,8 @@ namespace Meziantou.Analyzer.Rules; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class UseInlineXmlCommentSyntaxWhenPossibleAnalyzer : DiagnosticAnalyzer { + private static readonly ConfigurationDefinition MaxLineLengthConfiguration = new("max_line_length"); + private static readonly DiagnosticDescriptor Rule = new( RuleIdentifiers.UseSingleLineXmlCommentSyntaxWhenPossible, title: "Use single-line XML comment syntax when possible", @@ -117,8 +120,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) private static bool WouldFitInMaxLineLength(SymbolAnalysisContext context, XmlElementSyntax elementSyntax) { // Get max_line_length from .editorconfig - var options = context.Options.AnalyzerConfigOptionsProvider.GetOptions(elementSyntax.SyntaxTree); - if (!options.TryGetValue("max_line_length", out var maxLineLengthValue)) + if (!context.Options.TryGetConfigurationValue(elementSyntax.SyntaxTree, MaxLineLengthConfiguration, out var maxLineLengthValue)) return true; // No limit configured, allow the change if (!int.TryParse(maxLineLengthValue, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out var maxLineLength) || maxLineLength <= 0) diff --git a/src/Meziantou.Analyzer/Rules/UseStringComparerAnalyzer.cs b/src/Meziantou.Analyzer/Rules/UseStringComparerAnalyzer.cs index 42dfacca8..fe5bdef48 100644 --- a/src/Meziantou.Analyzer/Rules/UseStringComparerAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/UseStringComparerAnalyzer.cs @@ -52,6 +52,11 @@ public sealed class UseStringComparerAnalyzer : DiagnosticAnalyzer description: "", helpLinkUri: RuleIdentifiers.GetHelpUri(RuleIdentifiers.UseStringComparer)); + private static readonly ConfigurationDefinition ExcludeQueryOperatorSyntaxesConfiguration = new(Rule.Id + ".exclude_query_operator_syntaxes", defaultValue: false); +#if ROSLYN_4_14_OR_GREATER + private static readonly ConfigurationDefinition ReportCollectionExpressionsConfiguration = new(Rule.Id + ".report_collection_expressions", defaultValue: false); +#endif + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) @@ -126,7 +131,7 @@ public void AnalyzeInvocation(OperationAnalysisContext ctx) return; } - if (operation.IsImplicit && IsQueryOperator(operation) && ctx.Options.GetConfigurationValue(operation, Rule.Id + ".exclude_query_operator_syntaxes", defaultValue: false)) + if (operation.IsImplicit && IsQueryOperator(operation) && ctx.Options.GetConfigurationValue(operation, ExcludeQueryOperatorSyntaxesConfiguration)) return; // Queryable comparer overloads are often not translatable by providers. @@ -207,7 +212,7 @@ public void AnalyzeCollectionExpression(OperationAnalysisContext ctx) static bool ShouldReportCollectionExpression(OperationAnalysisContext context, IOperation operation) { var defaultValue = operation.GetCSharpLanguageVersion().IsCSharp15OrAbove(); - return context.Options.GetConfigurationValue(operation, Rule.Id + ".report_collection_expressions", defaultValue); + return context.Options.GetConfigurationValue(operation, ReportCollectionExpressionsConfiguration, defaultValue); } } #endif