Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid allocations in CanWrap... methods #3711

Conversation

martin-strecker-sonarsource
Copy link
Contributor

The "CanWrap.." methods are in the hot path in our repository (see SonarSource/sonar-dotnet/issues/8106). It is likely that the methods are on the hot path in your analyzer as well (they are called by each ...Wrapper.IsInstance implementation).

The following improvements can be validated by the generated IL:

  • Capture class creation is removed: IL_00000 creates a capture class for the whole method. In the new version, no capture class is created.
  • Func<,> delegate instantiation for _ => new ConcurrentDictionary<Type, bool>() is deferred for sure. The function delegate in IL_0047 seems to be stored in a hidden static field and reused in the old version. The new version makes sure that the delegate is not instantiated on the happy path for sure. IL_0033 in the new version is only conditional executed after the branch after the SupportedSyntaxWrappers.TryGetValue (IL_0017) and a second branch after the static field lookup (IL_0025).
  • If wrappedSyntax.TryGetValue is not successful canCast is calculated and added to the ConcurrentDictionary without a delegate. This is possible because canCast is a value type. Unlike with reference types, the created value doesn't suffer from concurrency issues if TryAdd fails.

The allocation saving for the capture class was measured in this SonarSource/sonar-dotnet/pull/8107 on our side with the similar changes in place.

The IL for the old version of CanWrapNode looks like so (3 times newobj):

  .method assembly hidebysig static bool
    CanWrapNode(
      class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode node,
      class [System.Runtime]System.Type underlyingType
    ) cil managed
  {
    .maxstack 4
    .locals init (
      [0] class StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0' 'CS$<>8__locals0',
      [1] class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool> wrappedSyntax,
      [2] bool canCast
    )

    IL_0000: newobj       instance void StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::.ctor()
    IL_0005: stloc.0      // 'CS$<>8__locals0'
    IL_0006: ldloc.0      // 'CS$<>8__locals0'
    IL_0007: ldarg.1      // underlyingType
    IL_0008: stfld        class [System.Runtime]System.Type StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::underlyingType
    IL_000d: ldloc.0      // 'CS$<>8__locals0'
    IL_000e: ldarg.0      // node
    IL_000f: stfld        class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::node

    // [84 13 - 84 30]
    IL_0014: ldloc.0      // 'CS$<>8__locals0'
    IL_0015: ldfld        class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::node
    IL_001a: brtrue.s     IL_001e

    // [87 17 - 87 29]
    IL_001c: ldc.i4.1
    IL_001d: ret

    // [90 13 - 90 40]
    IL_001e: ldloc.0      // 'CS$<>8__locals0'
    IL_001f: ldfld        class [System.Runtime]System.Type StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::underlyingType
    IL_0024: brtrue.s     IL_0028

    // [93 17 - 93 30]
    IL_0026: ldc.i4.0
    IL_0027: ret

    // [96 13 - 96 168]
    IL_0028: ldsfld       class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers::SupportedSyntaxWrappers
    IL_002d: ldloc.0      // 'CS$<>8__locals0'
    IL_002e: ldfld        class [System.Runtime]System.Type StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::underlyingType
    IL_0033: ldsfld       class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
    IL_0038: dup
    IL_0039: brtrue.s     IL_0052
    IL_003b: pop
    IL_003c: ldsfld       class StyleCop.Analyzers.Lightup.LightupHelpers/'<>c' StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9'
    IL_0041: ldftn        instance class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<CanWrapNode>b__30_0'(class [System.Runtime]System.Type)
    IL_0047: newobj       instance void class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>>::.ctor(object, native int)
    IL_004c: dup
    IL_004d: stsfld       class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
    IL_0052: callvirt     instance !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/ class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>>::GetOrAdd(!0/*class [System.Runtime]System.Type*/, class [System.Runtime]System.Func`2<!0/*class [System.Runtime]System.Type*/, !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/>)
    IL_0057: stloc.1      // wrappedSyntax

    // [100 13 - 100 70]
    IL_0058: ldloc.1      // wrappedSyntax
    IL_0059: ldloc.0      // 'CS$<>8__locals0'
    IL_005a: ldfld        class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::node
    IL_005f: call         valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.CSharpExtensions::Kind(class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode)
    IL_0064: ldloca.s     canCast
    IL_0066: callvirt     instance bool class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>::TryGetValue(!0/*valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind*/, !1/*bool*/&)
    IL_006b: brtrue.s     IL_008b

    // [102 17 - 104 106]
    IL_006d: ldloc.1      // wrappedSyntax
    IL_006e: ldloc.0      // 'CS$<>8__locals0'
    IL_006f: ldfld        class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::node
    IL_0074: call         valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.CSharpExtensions::Kind(class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode)
    IL_0079: ldloc.0      // 'CS$<>8__locals0'
    IL_007a: ldftn        instance bool StyleCop.Analyzers.Lightup.LightupHelpers/'<>c__DisplayClass30_0'::'<CanWrapNode>b__1'(valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind)
    IL_0080: newobj       instance void class [System.Runtime]System.Func`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>::.ctor(object, native int)
    IL_0085: callvirt     instance !1/*bool*/ class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>::GetOrAdd(!0/*valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind*/, class [System.Runtime]System.Func`2<!0/*valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind*/, !1/*bool*/>)
    IL_008a: stloc.2      // canCast

    // [107 13 - 107 28]
    IL_008b: ldloc.2      // canCast
    IL_008c: ret

  } // end of method LightupHelpers::CanWrapNode

The IL for the new version looks like so (1 time newobj):

  .method assembly hidebysig static bool
    CanWrapNode(
      class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode node,
      class [System.Runtime]System.Type underlyingType
    ) cil managed
  {
    .maxstack 4
    .locals init (
      [0] class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool> wrappedSyntax,
      [1] bool canCast
    )

    // [82 13 - 82 30]
    IL_0000: ldarg.0      // node
    IL_0001: brtrue.s     IL_0005

    // [85 17 - 85 29]
    IL_0003: ldc.i4.1
    IL_0004: ret

    // [88 13 - 88 40]
    IL_0005: ldarg.1      // underlyingType
    IL_0006: brtrue.s     IL_000a

    // [91 17 - 91 30]
    IL_0008: ldc.i4.0
    IL_0009: ret

    // [94 13 - 94 175]
    IL_000a: ldsfld       class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers::SupportedSyntaxWrappers
    IL_000f: ldarg.1      // underlyingType
    IL_0010: ldsfld       class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
    IL_0015: dup
    IL_0016: brtrue.s     IL_002f
    IL_0018: pop
    IL_0019: ldsfld       class StyleCop.Analyzers.Lightup.LightupHelpers/'<>c' StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9'
    IL_001e: ldftn        instance class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<CanWrapNode>b__30_0'(class [System.Runtime]System.Type)
    IL_0024: newobj       instance void class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>>::.ctor(object, native int)
    IL_0029: dup
    IL_002a: stsfld       class [System.Runtime]System.Func`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
    IL_002f: callvirt     instance !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/ class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>>::GetOrAdd(!0/*class [System.Runtime]System.Type*/, class [System.Runtime]System.Func`2<!0/*class [System.Runtime]System.Type*/, !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/>)
    IL_0034: stloc.0      // wrappedSyntax

    // [97 13 - 97 74]
    IL_0035: ldloc.0      // wrappedSyntax
    IL_0036: ldarg.0      // node
    IL_0037: call         valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.CSharpExtensions::Kind(class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode)
    IL_003c: ldloca.s     canCast
    IL_003e: callvirt     instance bool class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>::TryGetValue(!0/*valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind*/, !1/*bool*/&)
    IL_0043: brtrue.s     IL_006a

    // [99 17 - 99 103]
    IL_0045: ldarg.1      // underlyingType
    IL_0046: call         class [System.Reflection]System.Reflection.TypeInfo [System.Reflection]System.Reflection.IntrospectionExtensions::GetTypeInfo(class [System.Runtime]System.Type)
    IL_004b: ldarg.0      // node
    IL_004c: callvirt     instance class [System.Runtime]System.Type [System.Runtime]System.Object::GetType()
    IL_0051: call         class [System.Reflection]System.Reflection.TypeInfo [System.Reflection]System.Reflection.IntrospectionExtensions::GetTypeInfo(class [System.Runtime]System.Type)
    IL_0056: callvirt     instance bool [System.Reflection]System.Reflection.TypeInfo::IsAssignableFrom(class [System.Reflection]System.Reflection.TypeInfo)
    IL_005b: stloc.1      // canCast

    // [100 17 - 100 60]
    IL_005c: ldloc.0      // wrappedSyntax
    IL_005d: ldarg.0      // node
    IL_005e: call         valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.CSharpExtensions::Kind(class [Microsoft.CodeAnalysis]Microsoft.CodeAnalysis.SyntaxNode)
    IL_0063: ldloc.1      // canCast
    IL_0064: callvirt     instance bool class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>::TryAdd(!0/*valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind*/, !1/*bool*/)
    IL_0069: pop

    // [103 13 - 103 28]
    IL_006a: ldloc.1      // canCast
    IL_006b: ret

  } // end of method LightupHelpers::CanWrapNode

@codecov
Copy link

codecov bot commented Oct 16, 2023

Codecov Report

Merging #3711 (b76cba6) into master (0548969) will increase coverage by 0.01%.
Report is 4 commits behind head on master.
The diff coverage is 100.00%.

❗ Current head b76cba6 differs from pull request most recent head 12b6f93. Consider uploading reports for the commit 12b6f93 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3711      +/-   ##
==========================================
+ Coverage   93.12%   93.13%   +0.01%     
==========================================
  Files        1088     1088              
  Lines      114954   115026      +72     
  Branches     4088     4113      +25     
==========================================
+ Hits       107047   107126      +79     
+ Misses       6865     6860       -5     
+ Partials     1042     1040       -2     

@bjornhellander
Copy link
Contributor

Is it still benefitial to use GetOrAdd after having checked with TryGetValue, or would it be even better to simply call TryAdd instead, to not need to capture any variables at all and get rid of the local function?

@bjornhellander
Copy link
Contributor

bjornhellander commented Oct 17, 2023

Answering myself: Since the local function in your code is rarely called, I assume there will be no practical difference in performance. But maybe it would be better with the simpler code, for readability?

...

if (!wrappedObject.TryGetValue(obj.GetType(), out var canCast))
{
    canCast = underlyingType.GetTypeInfo().IsAssignableFrom(obj.GetType().GetTypeInfo());
    wrappedObject.TryAdd(obj.GetType(), canCast);
}

return canCast;

Just a thought.

@@ -65,18 +65,22 @@ internal static bool CanWrapObject(object obj, Type underlyingType)
return false;
}

ConcurrentDictionary<Type, bool> wrappedObject = SupportedObjectWrappers.GetOrAdd(underlyingType, _ => new ConcurrentDictionary<Type, bool>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there an actual problem with this first lookup (in each method)? I haven't dug into your IL comparison, but since no capture is needed, it seems the only possible overhead would be creating the func instance. I think I recall that lambdas are automatically detected to be static if possible, but in case that is not correct, wouldn't simply marking the lambda as static be the best change?

ConcurrentDictionary<Type, bool> wrappedObject = SupportedObjectWrappers.GetOrAdd(underlyingType, static _ => new ConcurrentDictionary<Type, bool>());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IL confirmed that the delegate instance is indeed cached between calls in a static field:

// Load the delegate instance from a static field  
    IL_0033: ldsfld       class System.Func`2<System.Type, ConcurrentDictionary`2<SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
    IL_0038: dup
// Branch if not null?
    IL_0039: brtrue.s     IL_0052
    IL_003b: pop
// ..
// Create the delegate
    IL_0047: newobj       instance void class System.Func`2<System.Type, ConcurrentDictionary`2<SyntaxKind, bool>>::.ctor(object, native int)
    IL_004c: dup
// Store it
    IL_004d: stsfld       class System.Func`2<System.Type, ConcurrentDictionary`2<SyntaxKind, bool>> StyleCop.Analyzers.Lightup.LightupHelpers/'<>c'::'<>9__30_0'
// Invoke the delegate
    IL_0052: callvirt     instance !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/ class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<class [System.Runtime]System.Type, class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>>::GetOrAdd(!0/*class [System.Runtime]System.Type*/, class [System.Runtime]System.Func`2<!0/*class [System.Runtime]System.Type*/, !1/*class [System.Collections.Concurrent]System.Collections.Concurrent.ConcurrentDictionary`2<valuetype [Microsoft.CodeAnalysis.CSharp]Microsoft.CodeAnalysis.CSharp.SyntaxKind, bool>*/>)

@martin-strecker-sonarsource
Copy link
Contributor Author

But maybe it would be better with the simpler code, for readability?

This is indeed better. It works in this case because the cached value is a bool (value type). For the SupportedObjectWrappers case it wouldn't work as well as we would need to do another TryGetValue if TryAdd is failing (the ConcurrentDictionary we just created is not the same as the one stored by another thread in the meantime in the ConcurrentDictionary).

Copy link
Member

@sharwell sharwell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting simplification

@@ -65,15 +65,17 @@ internal static bool CanWrapObject(object obj, Type underlyingType)
return false;
}

ConcurrentDictionary<Type, bool> wrappedObject = SupportedObjectWrappers.GetOrAdd(underlyingType, _ => new ConcurrentDictionary<Type, bool>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This line does not need to change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just kept the static to emphasize the non-capturing semantic of the lambda.

@@ -65,15 +65,17 @@ internal static bool CanWrapObject(object obj, Type underlyingType)
return false;
}

ConcurrentDictionary<Type, bool> wrappedObject = SupportedObjectWrappers.GetOrAdd(underlyingType, _ => new ConcurrentDictionary<Type, bool>());

// Avoid creating the delegate if the value already exists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This comment is sufficient for the method (it already states the complete intent, and it's just a simple bug that we didn't adhere to it)

{
canCast = wrappedObject.GetOrAdd(
obj.GetType(),
kind => underlyingType.GetTypeInfo().IsAssignableFrom(obj.GetType().GetTypeInfo()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This line is the source of the capturing allocation (specifically, capturing a method parameter in a lambda forces the the capture to be allocated on all paths and not just the one that creates this delegate).

Comment on lines +77 to +78
canCast = underlyingType.GetTypeInfo().IsAssignableFrom(obj.GetType().GetTypeInfo());
wrappedObject.TryAdd(obj.GetType(), canCast);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ Requesting that this pull request be reduced to just this two line change in each case.

@martin-strecker-sonarsource
Copy link
Contributor Author

@sharwell Merging failed due to some (unrelated?) build error.

@bjornhellander
Copy link
Contributor

I consider myself unlucky when it comes to these builds, but you are on another level :-) I think that you got all the "usual" random build errors plus one that I don't think I have ever seen. There are however some new commits on master, so you can merge those and push again. Maybe fifth time is the charm? Otherwise I hope that @sharwell can merge this anyway.

@sharwell
Copy link
Member

I'll just restart the build. Merging from master will turn off the auto merge.

@sharwell sharwell merged commit 1dd5ced into DotNetAnalyzers:master Oct 18, 2023
4 checks passed
@sharwell sharwell added this to the 1.2-beta.next milestone Oct 18, 2023
renovate bot added a commit to smartive/cas-fee-adv-mumble-api that referenced this pull request Dec 21, 2023
…20)

[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[StyleCop.Analyzers](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers)
| `1.2.0-beta.507` -> `1.2.0-beta.556` |
[![age](https://developer.mend.io/api/mc/badges/age/nuget/StyleCop.Analyzers/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/nuget/StyleCop.Analyzers/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/nuget/StyleCop.Analyzers/1.2.0-beta.507/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/StyleCop.Analyzers/1.2.0-beta.507/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>DotNetAnalyzers/StyleCopAnalyzers
(StyleCop.Analyzers)</summary>

###
[`v1.2.0-beta.556`](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/releases/tag/1.2.0-beta.556)

[Compare
Source](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.553...1.2.0-beta.556)

#### What's Changed

- Update SA1011 to forbid trailing space before the end of a switch case
by [@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3674
- Rewrite IOperationWrapper as a wrapper structure around IOperation by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3611
- Update SA1202 to support interfaces (C# 8) and records (C# 9, 10) by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3694
- Update documentation for SA1308 to also mention prefix "t\_" by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3697
- Update SA1642 and its code fix to handle record structs correctly by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3696
- Update dependencies by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3700
- Mark several test classes as partial by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3702
- Add missing test files and fix inheritance by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3703
- Generate and validate derived test classes by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3704
- Update SA1011 to not require space before a range operator by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3709
- Update SA1131 to treat methods as constants by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3710
- Avoid allocations in CanWrap... methods by
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- Update SA1648 to accept inheritdoc on members implemented from static
abstract/virtual interface members by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3715
- Update SA1600 to also handle records by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3725
- Update SA1119 to allow parenthesis around a ref ternary conditional
expression when it is the left-hand side of an assigment by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3737
- Update SA1119 to allow parenthesized switch expressions followed by an
invocation by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3733
- Add c# 12 test project by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3734
- Run tests in parallel jobs by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3740
- Update SA1010 to accept whitespace before collection initializers by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3745
- Update SA1513 to not require a blank line if the closing brace is at
the end of a collection expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3746
- Update SA1118 to allow multi-line collection expressions by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3749
- Update SA1009 to require a space after the closing parenthesis if it
is followed by ++ or -- from a prefix unary expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3750
- Update SA1008 to allow space before the opening parenthesis of a using
alias definition of a tuple type by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3748
- Update documentation for SA1102 to contain compilable code examples by
[@&#8203;arphox](https://togithub.com/arphox) in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- Update SA1008 to not crash if there is no previous token by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3741
- Change default value of test property CodeActionValidationMode to
SemanticStructure instead of None and update so that tests still pass by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3753
- Allow inheritdoc for class constructors with base types by
[@&#8203;MartyIX](https://togithub.com/MartyIX) in
[DotNetAnalyzers/StyleCopAnalyzers#3719
- Fix that SA1134 Fix All maybe non-deterministic by
[@&#8203;pdelvo](https://togithub.com/pdelvo) in
[DotNetAnalyzers/StyleCopAnalyzers#2853
- Coverage improvements by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3675
- Fix SA1131 to not treat "complex" expressions as a literal by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3760

#### New Contributors

-
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
made their first contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- [@&#8203;arphox](https://togithub.com/arphox) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- [@&#8203;MartyIX](https://togithub.com/MartyIX) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3719

**Full Changelog**:
DotNetAnalyzers/StyleCopAnalyzers@1.2.0-beta.507...1.2.0-beta.556

###
[`v1.2.0-beta.553`](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/releases/tag/1.2.0-beta.553)

[Compare
Source](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.507...1.2.0-beta.553)

##### What's Changed

- Update SA1011 to forbid trailing space before the end of a switch case
by [@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3674
- Rewrite IOperationWrapper as a wrapper structure around IOperation by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3611
- Update SA1202 to support interfaces (C# 8) and records (C# 9, 10) by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3694
- Update documentation for SA1308 to also mention prefix "t\_" by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3697
- Update SA1642 and its code fix to handle record structs correctly by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3696
- Update dependencies by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3700
- Mark several test classes as partial by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3702
- Add missing test files and fix inheritance by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3703
- Generate and validate derived test classes by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3704
- Update SA1011 to not require space before a range operator by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3709
- Update SA1131 to treat methods as constants by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3710
- Avoid allocations in CanWrap... methods by
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- Update SA1648 to accept inheritdoc on members implemented from static
abstract/virtual interface members by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3715
- Update SA1600 to also handle records by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3725
- Update SA1119 to allow parenthesis around a ref ternary conditional
expression when it is the left-hand side of an assigment by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3737
- Update SA1119 to allow parenthesized switch expressions followed by an
invocation by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3733
- Add c# 12 test project by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3734
- Run tests in parallel jobs by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3740
- Update SA1010 to accept whitespace before collection initializers by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3745
- Update SA1513 to not require a blank line if the closing brace is at
the end of a collection expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3746
- Update SA1118 to allow multi-line collection expressions by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3749
- Update SA1009 to require a space after the closing parenthesis if it
is followed by ++ or -- from a prefix unary expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3750
- Update SA1008 to allow space before the opening parenthesis of a using
alias definition of a tuple type by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3748
- Update documentation for SA1102 to contain compilable code examples by
[@&#8203;arphox](https://togithub.com/arphox) in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- Update SA1008 to not crash if there is no previous token by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3741
- Change default value of test property CodeActionValidationMode to
SemanticStructure instead of None and update so that tests still pass by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3753
- Allow inheritdoc for class constructors with base types by
[@&#8203;MartyIX](https://togithub.com/MartyIX) in
[DotNetAnalyzers/StyleCopAnalyzers#3719
- Fix that SA1134 Fix All maybe non-deterministic by
[@&#8203;pdelvo](https://togithub.com/pdelvo) in
[DotNetAnalyzers/StyleCopAnalyzers#2853
- Coverage improvements by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3675

##### New Contributors

-
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
made their first contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- [@&#8203;arphox](https://togithub.com/arphox) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- [@&#8203;MartyIX](https://togithub.com/MartyIX) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3719

**Full Changelog**:
DotNetAnalyzers/StyleCopAnalyzers@1.2.0-beta.507...1.2.0-beta.553

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 9pm,before 6am" in timezone
Europe/Zurich, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/smartive/cas-fee-adv-mumble-api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMDMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjEwMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
ThorstenSauter pushed a commit to ThorstenSauter/NoPlan that referenced this pull request Dec 21, 2023
…591)

[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[StyleCop.Analyzers](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers)
| `1.2.0-beta.507` -> `1.2.0-beta.556` |
[![age](https://developer.mend.io/api/mc/badges/age/nuget/StyleCop.Analyzers/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/nuget/StyleCop.Analyzers/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/nuget/StyleCop.Analyzers/1.2.0-beta.507/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/StyleCop.Analyzers/1.2.0-beta.507/1.2.0-beta.556?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>DotNetAnalyzers/StyleCopAnalyzers
(StyleCop.Analyzers)</summary>

###
[`v1.2.0-beta.556`](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/releases/tag/1.2.0-beta.556)

[Compare
Source](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.553...1.2.0-beta.556)

#### What's Changed

- Update SA1011 to forbid trailing space before the end of a switch case
by [@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3674
- Rewrite IOperationWrapper as a wrapper structure around IOperation by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3611
- Update SA1202 to support interfaces (C# 8) and records (C# 9, 10) by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3694
- Update documentation for SA1308 to also mention prefix "t\_" by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3697
- Update SA1642 and its code fix to handle record structs correctly by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3696
- Update dependencies by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3700
- Mark several test classes as partial by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3702
- Add missing test files and fix inheritance by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3703
- Generate and validate derived test classes by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3704
- Update SA1011 to not require space before a range operator by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3709
- Update SA1131 to treat methods as constants by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3710
- Avoid allocations in CanWrap... methods by
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- Update SA1648 to accept inheritdoc on members implemented from static
abstract/virtual interface members by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3715
- Update SA1600 to also handle records by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3725
- Update SA1119 to allow parenthesis around a ref ternary conditional
expression when it is the left-hand side of an assigment by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3737
- Update SA1119 to allow parenthesized switch expressions followed by an
invocation by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3733
- Add c# 12 test project by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3734
- Run tests in parallel jobs by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3740
- Update SA1010 to accept whitespace before collection initializers by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3745
- Update SA1513 to not require a blank line if the closing brace is at
the end of a collection expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3746
- Update SA1118 to allow multi-line collection expressions by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3749
- Update SA1009 to require a space after the closing parenthesis if it
is followed by ++ or -- from a prefix unary expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3750
- Update SA1008 to allow space before the opening parenthesis of a using
alias definition of a tuple type by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3748
- Update documentation for SA1102 to contain compilable code examples by
[@&#8203;arphox](https://togithub.com/arphox) in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- Update SA1008 to not crash if there is no previous token by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3741
- Change default value of test property CodeActionValidationMode to
SemanticStructure instead of None and update so that tests still pass by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3753
- Allow inheritdoc for class constructors with base types by
[@&#8203;MartyIX](https://togithub.com/MartyIX) in
[DotNetAnalyzers/StyleCopAnalyzers#3719
- Fix that SA1134 Fix All maybe non-deterministic by
[@&#8203;pdelvo](https://togithub.com/pdelvo) in
[DotNetAnalyzers/StyleCopAnalyzers#2853
- Coverage improvements by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3675
- Fix SA1131 to not treat "complex" expressions as a literal by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3760

#### New Contributors

-
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
made their first contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- [@&#8203;arphox](https://togithub.com/arphox) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- [@&#8203;MartyIX](https://togithub.com/MartyIX) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3719

**Full Changelog**:
DotNetAnalyzers/StyleCopAnalyzers@1.2.0-beta.507...1.2.0-beta.556

###
[`v1.2.0-beta.553`](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/releases/tag/1.2.0-beta.553)

[Compare
Source](https://togithub.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.507...1.2.0-beta.553)

##### What's Changed

- Update SA1011 to forbid trailing space before the end of a switch case
by [@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3674
- Rewrite IOperationWrapper as a wrapper structure around IOperation by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3611
- Update SA1202 to support interfaces (C# 8) and records (C# 9, 10) by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3694
- Update documentation for SA1308 to also mention prefix "t\_" by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3697
- Update SA1642 and its code fix to handle record structs correctly by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3696
- Update dependencies by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3700
- Mark several test classes as partial by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3702
- Add missing test files and fix inheritance by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3703
- Generate and validate derived test classes by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3704
- Update SA1011 to not require space before a range operator by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3709
- Update SA1131 to treat methods as constants by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3710
- Avoid allocations in CanWrap... methods by
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- Update SA1648 to accept inheritdoc on members implemented from static
abstract/virtual interface members by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3715
- Update SA1600 to also handle records by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3725
- Update SA1119 to allow parenthesis around a ref ternary conditional
expression when it is the left-hand side of an assigment by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3737
- Update SA1119 to allow parenthesized switch expressions followed by an
invocation by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3733
- Add c# 12 test project by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3734
- Run tests in parallel jobs by
[@&#8203;sharwell](https://togithub.com/sharwell) in
[DotNetAnalyzers/StyleCopAnalyzers#3740
- Update SA1010 to accept whitespace before collection initializers by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3745
- Update SA1513 to not require a blank line if the closing brace is at
the end of a collection expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3746
- Update SA1118 to allow multi-line collection expressions by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3749
- Update SA1009 to require a space after the closing parenthesis if it
is followed by ++ or -- from a prefix unary expression by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3750
- Update SA1008 to allow space before the opening parenthesis of a using
alias definition of a tuple type by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3748
- Update documentation for SA1102 to contain compilable code examples by
[@&#8203;arphox](https://togithub.com/arphox) in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- Update SA1008 to not crash if there is no previous token by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3741
- Change default value of test property CodeActionValidationMode to
SemanticStructure instead of None and update so that tests still pass by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3753
- Allow inheritdoc for class constructors with base types by
[@&#8203;MartyIX](https://togithub.com/MartyIX) in
[DotNetAnalyzers/StyleCopAnalyzers#3719
- Fix that SA1134 Fix All maybe non-deterministic by
[@&#8203;pdelvo](https://togithub.com/pdelvo) in
[DotNetAnalyzers/StyleCopAnalyzers#2853
- Coverage improvements by
[@&#8203;bjornhellander](https://togithub.com/bjornhellander) in
[DotNetAnalyzers/StyleCopAnalyzers#3675

##### New Contributors

-
[@&#8203;martin-strecker-sonarsource](https://togithub.com/martin-strecker-sonarsource)
made their first contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3711
- [@&#8203;arphox](https://togithub.com/arphox) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3755
- [@&#8203;MartyIX](https://togithub.com/MartyIX) made their first
contribution in
[DotNetAnalyzers/StyleCopAnalyzers#3719

**Full Changelog**:
DotNetAnalyzers/StyleCopAnalyzers@1.2.0-beta.507...1.2.0-beta.553

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am" (UTC), Automerge - At any
time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/ThorstenSauter/NoPlan).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMDMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjEwMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants