https://keepachangelog.com/en/1.0.0/
ElementaryMethodsOfTypeInCollectionNotOverridden
: Include.Distinct()
and.ToHashSet()
, courtesy of @Advitalitum
ConcurrentDictionaryEmptyCheck
: Correctly constrain the LINQ methods toConcurrentDictionary
- Reverted an earlier dependency bump which caused the analyzers to become incompatible with Visual Studio
ConcurrentDictionaryEmptyCheck
: AConcurrentDictionary
is checked for emptiness without using.IsEmpty
EnumWithoutDefaultValue
: No longer crashes when using an enum that is notint
, courtesy of @Genbox
- All analysers will no longer report diagnostics in generated code
UnnecessaryEnumerableMaterialization
: If the instance is of typeIQueryable
then the analyzer will no longer trigger
GetHashCodeRefersToMutableMember
: No longer triggers oninit
property setters
AsyncOverloadsAvailable
: Will no longer pass through theCancellationToken
if it's inside a static local functionAsyncOverloadsAvailable
: Will correctly identify overloads if the synchronous variant returns aTask
-like type
StringConcatenatedInLoop
: No longer triggers a warning if the string is retrieved through an indexer (e.g.myList[i]
)DisposeAsyncDisposable
: Preserves leading and trailing trivia when the code fix is appliedTestMethodWithoutTestAttribute
: Will no longer consider methods withTask<T>
andValueTask<T>
return types as potential test methods
DisposeAsyncDisposable
: An object implementsIAsyncDisposable
and can be disposed of asynchronously in the context it is usedPointlessCollectionToString
:ImmutableDictionary
is also includedTestMethodWithoutTestAttribute
: Reduced false negatives by extending the diagnostic to methods that have certain attributes (Xunit.ClassData
,Xunit.InlineData
,Microsoft.DataRow
,NUnit.TestCase
,NUnit.TestCaseSource
)
ComparingStringsWithoutStringComparison
: Don't trigger when the same symbol is referenced in both operandsSwitchDoesNotHandleAllEnumOptions
: When adefault
clause is present, the analyzer will become an INFO diagnostic rather than a WARN
ThreadSleepInAsyncMethod
: Fixed aNullReferenceException
if symbols weren't loaded
StringConcatenatedInLoop
: No longer triggers if concatenation is immediately followed by areturn
orbreak
clauseAsyncOverloadsAvailable
: Doesn't trigger inside a synchronous local functionSynchronousTaskWait
: Now also supports anonymous functionsThreadSleepInAsyncMethod
: Now also supports anonymous functions
StructWithoutElementaryMethodsOverridden
: Generates anEquals(object? o)
method when nullable reference types are enabledEqualsAndGetHashcodeNotImplementedTogether
: Generates anEquals(object? o)
method when nullable reference types are enabled
StringConcatenatedInLoop
: Assignments without a concatenation referencing the assigned field won't trigger a warningStaticInitializerAccessedBeforeInitialization
: No longer triggers if the referenced symbol is used an argument to a method callSwitchIsMissingDefaultLabel
: Restricted the IDE warning to theswitch
value instead of the entire statementEqualsAndGetHashcodeNotImplementedTogether
,RethrowExceptionWithoutLosingStacktrace
andStringPlaceHoldersInWrongOrder
: Minor improvements to code fixes to return individual documents instead of a solution
StringConcatenatedInLoop
: Concatenations inside object creation expressions no longer trigger a warningStringConcatenatedInLoop
: Does not trigger when assigning to the loop variableUnnecessaryEnumerableMaterialization
: Now correctly parses the two subsequent invocations, avoiding issues when they are nested within a method call themselvesSwitchDoesNotHandleAllEnumOptions
: Code Fix generates more predictable code when simplification is possibleSwitchDoesNotHandleAllEnumOptions
: Performance of Code Fix has been improved
LoopedRandomInstantiation
: No longer triggers when a seed is passed to the constructorRecursiveOperatorOverload
: No longer triggers multiple identical warnings if the operator is invoked multiple times in the bodyExceptionThrownFromProhibitedContext
,StaticInitializerAccessedBeforeInitialization
,SynchronousTaskWait
,UnusedResultOnImmutableObject
,GetHashCodeRefersToMutableMember
,RecursiveOperatorOverload
,StringDotFormatWithDifferentAmountOfArguments
andEnumWithoutDefaultValue
tests useVerifyCS
AsyncOverloadsAvailable
: Correctly generate the fixed code when conditional access is used, i.e.writer?.Write()
ElementaryMethodsOfTypeInCollectionNotOverridden
: Now takes overrides in base types into considerationParameterAssignedInConstructor
: Don't trigger when the referenced member is a constantStringPlaceholdersInWrongOrder
: Code fix generates correct code when there are more than 10 placeholders in the format stringUnboundedStackalloc
: Does not trigger when using pointers, e.g.int*
ThreadSleepInAsyncMethod
: Fixed a rare scenario in which an empty code fix would be offeredElementaryMethodsOfTypeInCollectionNotOverridden
,LoopedRandomInstantiation
,OnPropertyChangedWithoutNameOfOperator
andStringPlaceholdersInWrongOrder
tests useVerifyCS
StringConcatenatedInLoop
: No longer triggers for regular assignmentsUnnecessaryEnumerableMaterialization
: Now supports conditional access, i.e.values?.ToArray().ToList()
AsyncOverloadsAvailable
: No longer triggers when contained within alock
bodyAsyncOverloadsAvailable
: Better maintains whitespace, indentation and comments when the code fix is appliedAsyncOverloadsAvailable
: Improved the detection of overloads when an optionalCancellationToken
is acceptedExplicitEnumValues
andEnumWithoutDefaultValue
: Downgraded from warning to info to reduce their prevalenceExceptionThrownFromProhibitedContext
: No longer triggers forPlatformNotSupportedException
ComparingStringsWithoutStringComparison
: Correctly maintains trailing whitespace when the code fix is appliedStringPlaceholdersInWrongOrder
andUnnecessaryEnumerableMaterialization
: Rewritten to useIOperation
UnnecessaryEnumerableMaterialization
tests useVerifyCS
LinqTraversalBeforeFilter
: Fixed typo in diagnostic message
StringConcatenatedInLoop
: Astring
was concatenated in a loop which introduces intermediate allocations. Consider using aStringBuilder
or pre-allocatedstring
instead.LinqTraversalBeforeFilter
,LockingOnDiscouragedObject
andLockingOnMutableReference
useVerifyCS
CollectionManipulatedDuringTraversal
: A collection was modified while it was being iterated over. Make a copy first or avoid iterations while the loop is in progress to avoid anInvalidOperationException
exception at runtimeAccessingTaskResultWithoutAwait
: Now also shows a warning when the method is notasync
but returns aTask
PointlessCollectionToString
: Supports immutable collectionsStructWithoutElementaryMethodsOverridden
: No longer generates the elementary methods in both declarations if it is apartial struct
StructWithoutElementaryMethodsOverridden
: Rewritten to useISymbol
PointlessCollectionToString
,ThrowNull
,ExplicitEnumValues
,RethrowExceptionWithoutLosingStracktrace
,SwitchDoesNotHandleAllEnumOptions
,ThreadSleepInAsyncMethodTests
,ParameterAssignedInConstructorTests
,EqualsAndGetHashcodeNotImplemented
,TestMethodWithoutPublicModifier
,FlagsEnumValuesAreNotPowersOfTwoTests
,StructWithoutElementaryMethodsOverridden
andUnboundedStackalloc
tests useVerifyCS
FormReadSynchronously
: Synchronously accessedHttpRequest.Form
which uses sync-over-async. UseHttpRequest.ReadFormAsync()
insteadSwitchIsMissingDefaultLabel
: Rewritten usingIOperation
and tests useVerifyCS
NewtonsoftMixedWithSystemTextJson
tests useVerifyCS
MultipleOrderByCalls
: SuccessiveOrderBy()
calls will maintain only the last specified sort order. UseThenBy()
to combine themTestMethodWithoutTestAttribute
: No longer fires for test constructorsTestMethodWithoutTestAttribute
: No longer fires for overridden methodsTestMethodWithoutTestAttribute
tests useVerifyCS
- Switched several test files over to the
VerifyCS
approach
AsyncMethodWithVoidReturnType
will not trigger forEventArgs
from other frameworks such as WinUI- Code fixes that introduce
using
statements will now take "Global Usings" into account and format theusing
statement better
AsyncOverloadsAvailable
: In a chain of method calls, the code fix no longer replaces the wrong invocationComparingStringsWithoutStringComparison
: No longer triggers when a culture is passed to.ToLower()
or.ToUpper()
ComparingStringsWithoutStringComparison
: Chained method invocations are now supportedComparingStringsWithoutStringComparison
: Rewritten to useIOperation
FlagsEnumValuesAreNotPowersOfTwo
: Code fix now formats correctly and doesn't copy commentsHttpContextStoredInField
: Only triggers if a reference toMicrosoft.AspNetCore.Http.IHttpContextAccessor
existsLockingOnMutableReference
: Now includes the name of the field in the error message- Simplified
GetSyntaxRootAsync
calls in code fixes UnusedResultOnImmutableObject
: Now usesIOperation
SynchronousTaskWait
: Now works for top-level statementsSynchronousTaskWait
: Rewritten to useIOperation
SynchronousTaskWait
: Preserves leading trivia when applying the code fixSynchronousTaskWait
: Doesn't offer a code fix when a timeout is passed toTask.Wait(timeoutMs)
ComparingStringsWithoutStringComparison
: Preserves leading trivia when applying the code fixThreadSleepInAsyncMethod
: Rewritten to useIOperation
ThreadSleepInAsyncMethod
: Supportsasync
lambdas
ElementaryMethodsOfTypeInCollectionNotOverridden
: Fixed an issue where aNullReferenceException
would be thrownHttpClientInstantiatedDirectly
: Only triggers if a reference toMicrosoft.Extensions.Http
exists andIHttpClientFactory
is within scopeAsyncMethodWithVoidReturnType
: Does not trigger forinterface
andabstract class
implementationsTestMethodWithoutTestAttribute
: Now excludes lifetime hooks such asXunit.IAsyncLifetime
TestMethodWithoutTestAttribute
: No longer incorrectly triggers for[Fact]
attributes inside astruct
TestMethodWithoutTestAttribute
: Also accepts test methods that returnValueTask
andValueTask<T>
TestMethodWithoutTestAttribute
: Rewritten to useISymbol
NewtonsoftMixedWithSystemTextJson
: An attempt is made to (de-)serialize an object which combinesSystem.Text.Json
andNewtonsoft.Json
. Attributes from one won't be adhered to in the other and should not be mixed.
- Added
ConfigureAwait(false)
to all codefixes
StaticInitializerAccessedBeforeInitialization
: Doesn't trigger an error if a member with the same name but in a different type is referencedTestMethodWithoutPublicModifier
: Now supports custom attributes that inherit from a test attribute
ElementaryMethodsOfTypeInCollectionNotOverridden
: Fixed aNullReferenceException
when analysingextern
declarations
AsyncOverloadsAvailableAnalyzer
: Analyzer is rewritten to useIOperation
- Unit tests target .NET 7 and test framework dependencies have been updated
- Vsix build tools dependency is updated
DivideIntegerByIntegerAnalyzer
: Analyzer is rewritten to useIOperation
EnumWithoutDefaultValueAnalyzer
: Analyzer is rewritten to useISymbol
EqualsAndGetHashcodeNotImplementedTogetherAnalyzer
: Analyzer is rewritten to useISymbol
LockingOnDiscouragedObjectAnalyzer
: Analyzer is rewritten to useIOperation
LockingOnMutableReferenceAnalyzer
: Analyzer is rewritten to useIOperation
UnnecessaryEnumerableMaterializationAnalyzer
: Use array instead of hash set for searching for small number of elements
TestMethodWithoutPublicModifier
: Analyzer is rewritten to useIOperation
DateTimeNow
: Correctly handles static imports
- Internal code cleanup
LinqTraversalBeforeFilter
: Analyzer is rewritten to useIOperation
LinqTraversalBeforeFilter
: Now supports LINQ query syntax
- Project is updated to C# 11
- Simplified the implementation of all codefixes
AccessingTaskResultWithoutAwait
: Analyzer is rewritten to useIOperation
InstanceFieldWithThreadStatic
: Simplified theIsStatic
check
OnPropertyChangedWithoutNameOf
: Analyzer is rewritten to useIOperation
ThrowNull
: Correctly triggers when a constant or castednull
value is being thrown
ThreadStaticWithInitializer
andInstanceFieldWithThreadStatic
: Analyzer is rewritten to useIOperation
- Removed unused test project dependencies
- Split up Test and Build workflows
DateTimeNow
: No longer incorrectly triggers fornameof(DateTime.Now)
invocationsPointlessCollectionToString
: Correctly handles longer chains with nullable annotations, e.g.SomeClass.SomeCollection?.ToString()
NewGuid
,DateTimeNow
,HttpClientInstantiatedDirectly
,HttpContextStoredInField
,ThrowNull
,PointlessCollectionToString
,MultipleFromBodyParameters
,LoopedRandomInstantiation
andElementaryMethodsOfTypeInCollectionNotOverridden
: Analyzer is rewritten to useIOperation
ParameterAssignedInConstructor
: Analyzer is rewritten to useIOperation
AsyncMethodWithVoidReturnType
andAttributeMustSpecifyAttributeUsage
: Analyzer is rewritten to useIOperation
SwitchDoesNotHandleAllEnumOptions
: Analyzer is rewritten to useIOperation
StaticInitializerAccessedBeforeInitialization
: Complete rewrite of the analyzer to useIOperation
. No functional difference but might be more performant
PointlessCollectionToString
:.ToString()
was called on a collection which results in impractical output. Considering usingstring.Join()
to display the values instead.
ThreadStaticWithInitializer
: A field is marked as[ThreadStatic]
so it cannot contain an initializer. The field initializer is only executed for the first thread.StaticInitializerAccessedBeforeInitialization
: When a reference is part of a lambda expression we no longer incorrectly mark it as an error
AccessingTaskResultWithoutAwait
: Now also works for top-level functionsAccessingTaskResultWithoutAwait
: In null-conditional access scenarios such asfile?.ReadAsync().Result
, invalid code will no longer be suggested by the code fix
LockingOnMutableReference
: A lock was obtained on a mutable field which can lead to deadlocks when a new value is assigned. Mark the field asreadonly
to prevent re-assignment after a lock is taken.ComparingStringsWithoutStringComparison
: Only suggest one code fix at a timeUnusedResultOnImmutableObject
: Don't trigger for custom extension methods on thestring
type
AsyncOverloadsAvailable
: Correctly suggests passing through aCancellationToken
if the sync overload accepts one as well
AsyncOverloadsAvailable
: Now passes through aCancellationToken
if there is one available in the current contextAttributeMustSpecifyAttributeUsage
: Takes definitions on base classes into accountElementaryMethodsOfTypeInCollectionNotOverridden
: SupportsHashSet.Add()
andDictionary.Add()
ParameterAssignedInConstructor
: A parameter was assigned in a constructor
- Fixed an issue where in some scenarios, necessary
using
statements were not getting added StaticInitializerAccessedBeforeInitialization
: no longer triggers when passing a method reference
SwitchIsMissingDefaultLabel
: code fix now works in top-level statementsAttributeMustSpecifyAttributeUsage
: correctly fires when the type is defined in the netstandard assembly
ComparingStringsWithoutStringComparison
: Astring
is being compared through allocating a newstring
, e.g. usingToLower()
orToUpperInvariant()
. Use a case-insensitive comparison instead which does not allocate.UnnecessaryEnumerableMaterialization
: supports!.
operatorElementaryMethodsOfTypeInCollectionNotOverridden
: supports?.
and!.
operatorsStaticInitializerAccessedBeforeInitialization
: no longer triggers when referencing itself
StaticInitializerAccessedBeforeInitialization
: supports implicit object creation expressionsNewGuid
: supports implicit object creation expressionsHttpClientInstantiatedDirectly
: supports implicit object creation expressions
- All analyzers and code fixes now have help codes that link back to the individual documentation
StaticInitializerAccessedBeforeInitialization
: don't trigger if the referenced field is marked asconst
StaticInitializerAccessedBeforeInitialization
: no longer triggers forLazy<T>
invocations when a method is passed as argument- Added documentation for all analyzers to the repo
- Internal code cleanup: all warning messages in the tests are now hardcoded
StaticInitializerAccessedBeforeInitialization
: now takesnameof()
usage into accountStaticInitializerAccessedBeforeInitialization
: no longer triggers for invocations ofstatic
functionsStaticInitializerAccessedBeforeInitialization
: no longer triggers when the field is of typeAction
orFunc
- Internal code cleanup to remove -Async suffixes on tests
LinqTraversalBeforeFilter
: AnIEnumerable
extension method was used to traverse the collection and subsequently filtered usingWhere()
. If theWhere()
filter is executed first, the traversal will have to iterate over fewer items which will result in better performance.LockingOnDiscouragedObject
: Alock
was taken using an instance of a discouraged type.System.String
,System.Type
andthis
references can all lead to deadlocks and should be replaced with aSystem.Object
instance instead.
StaticInitializerAccessedBeforeInitialization
: Astatic
field relies on the value of anotherstatic
field which is defined in the same type.static
fields are initialized in order of appearance.UnboundedStackalloc
: An array is stack allocated without checking whether the length is within reasonable bounds. This can result in performance degradations and security risks
AttributeMustSpecifyAttributeUsage
: correctly identify when the attribute has been added so it doesn't continue suggesting the change
StructWithoutElementaryMethodsOverridden
: takepartial struct
definitions into account where the methods are implemented across separate filesTestMethodWithoutTestAttribute
: more accurately excludeDispose()
methods
FlagsEnumValuesAreNotPowersOfTwo
has been rewritten to reduce the scope of its warning. Now it will only warn if a non-negative decimal literal is found which is not a power of two. A code fix will be available if a binary OR expression can be constructed with other enum membersFlagsEnumValuesDontFit
will no longer fire as this was inaccurate and already covered by the default CA analyzersFlagsEnumValuesAreNotPowersOfTwo
will now mention the enum member that triggered the violation
AttributeMustSpecifyAttributeUsage
: warn when an attribute is defined without specifying the[AttributeUsage]
- All internal code now uses nullable reference types
MultipleFromBodyParameters
: warn when an API was defined with multiple[FromBody]
parameters that attempt to deserialize the request body- Include README in nuget package
- CI will ensure the version has been updated appropriately before releasing a new package
- CI will run its
dotnet format
check much faster
TestMethodWithoutTestAttribute
: improved the accuracy of discoveringTestClass
andTestFixture
attributes
InstanceFieldWithThreadStatic
: warn when[ThreadStatic]
is applied to an instance field- Removed
StructShouldNotMutateSelf
- Restructured the diagnostic categories into Performance, ApiDesign and Correctness
ThreadSleepInAsyncMethod
does not suggest a no-op refactor if the method is not marked asasync
ElementaryMethodsOfTypeInCollectionNotOverridden
is more targeted and only warns if it finds an actual lookup that will be problematicExceptionThrownFromProhibitedContext
doesn't crash when encountering emptythrow
statementsExceptionThrownFromProhibitedContext
doesn't crash when encounteringthrow
statements that reference propertiesAsyncOverloadsAvailable
will no longer suggest to use an overload if that overload is the current surrounding methodAsyncOverloadsAvailable
now works inside lambda expressions as wellUnusedResultOnImmutableObject
doesn't trigger onCopyTo
andTryCopyTo
- Fixed:
AsyncOverloadsAvailable
supports methods that returnValueTask
- Fixed:
AccessingTaskResultWithoutAwait
supports methods that returnValueTask
- Fixed:
ThreadSleepInAsyncMethod
supports methods that returnValueTask
AsyncMethodWithVoidReturnType
now also works for top-level function declarations and local functionsThreadSleepInAsyncMethod
now also works for top-level function declarations and local functions
- Fixed:
GetHashCodeRefersToMutableMember
correctly handlespartial
classes - Fixed:
EqualsAndGetHashcodeNotImplemented
correctly handlespartial
classes
- Fixed:
AsyncOverloadsAvailable
wraps theawait
expression with parentheses when the function return value is accessed inline - Fixed:
AsyncOverloadsAvailable
no longer suggests a change if it would result in invalid code - Fixed:
AsyncOverloadsAvailable
now also reports improvements when using top-level statements - Fixed:
AsyncOverloadsAvailable
takes nullable reference types into account when selecting an overload EqualsAndGetHashcodeNotImplementedTogether
now mentions the class name in the diagnostic message
- Fixed:
ElementaryMethodsOfTypeInCollectionNotOverridden
triggers for external types - Fixed:
ExceptionThrownFromProhibitedContext
will no longer trigger forNotSupportedException
andNotImplementedException
- Fixed:
TestMethodWithoutTestAttribute
no longer crashes when encountering arecord
- Fixed:
TestMethodWithoutTestAttribute
no longer triggers forDispose()
methods
- Implemented
UnnecessaryEnumerableMaterialization
: AnIEnumerable
was materialized before a deferred execution call SwitchDoesNotHandleAllEnumOptions
produces more accurate code when static imports cause enum members to conflict- SharpSource its unit tests now run on .NET 6.0
- Implemented
UnusedResultOnImmutableObject
: The result of an operation on an immutable object is unused
- Implemented
EnumWithoutDefaultValue
: An enum should specify a default value - Changed the categories of
ExplicitEnumValues
,FlagsEnumValuesAreNotPowersOfTwo
andFlagsEnumValuesDontFit
- Improved messaging for
DateTimeNow
- Added documentation
- Implemented
HttpContextStoredInField
: show a warning whenHttpContext
was stored in a field. UseIHttpContextAccessor
instead - Fixed DiagnosticID of
HttpClientInstantiatedDirectly
- Implemented
HttpClientInstantiatedDirectly
: show a warning whenHttpClient
is instantiated. UseIHttpClientFactory
instead
- Implemented
ExplicitEnumValues
: show a warning when an enum does not explicitly specify its value
- Automatically publish updates to Github Packages
- Automatically publish updates to the VSIX marketplace
- Don't trigger
ElementaryMethodsOfTypeInCollectionNotOverridden
for enums - Don't trigger
ElementaryMethodsOfTypeInCollectionNotOverridden
for arrays DateTimeNow
now shows the correct code fix title action