From 931c7344f2f1e3b324ffcefeacc2c82126313123 Mon Sep 17 00:00:00 2001 From: Pavel Mikula Date: Wed, 16 Feb 2022 14:28:30 +0100 Subject: [PATCH 1/2] Reduce CFG memory allocations --- .../Extensions/PropertyInfoExtensions.cs | 52 ++++++++++++++ .../SonarAnalyzer.CFG/Helpers/RoslynHelper.cs | 16 ----- .../SonarAnalyzer.CFG/Roslyn/BasicBlock.cs | 70 +++++++------------ .../Roslyn/ControlFlowBranch.cs | 44 +++++------- .../Roslyn/ControlFlowGraph.cs | 27 +++---- .../Roslyn/ControlFlowRegion.cs | 54 ++++++-------- .../ShimLayer/IOperationWrapperSonar.cs | 12 ++-- 7 files changed, 135 insertions(+), 140 deletions(-) create mode 100644 analyzers/src/SonarAnalyzer.CFG/Extensions/PropertyInfoExtensions.cs diff --git a/analyzers/src/SonarAnalyzer.CFG/Extensions/PropertyInfoExtensions.cs b/analyzers/src/SonarAnalyzer.CFG/Extensions/PropertyInfoExtensions.cs new file mode 100644 index 00000000000..89bb9dc1e45 --- /dev/null +++ b/analyzers/src/SonarAnalyzer.CFG/Extensions/PropertyInfoExtensions.cs @@ -0,0 +1,52 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2022 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System; +using System.Collections; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; + +namespace SonarAnalyzer.CFG +{ + internal static class PropertyInfoExtensions + { + public static T ReadCached(this PropertyInfo property, object instance, ref T cache) where T : class => + cache ??= (T)property.GetValue(instance); + + public static T ReadCached(this PropertyInfo property, object instance, ref T? cache) where T : struct => + cache ??= (T)property.GetValue(instance); + + public static T ReadCached(this PropertyInfo property, object instance, Func createInstance, ref T cache) where T : class => + cache ??= createInstance(property.GetValue(instance)); + + public static ImmutableArray ReadCached(this PropertyInfo property, object instance, ref ImmutableArray cache) => + ReadCached(property, instance, x => (T)x, ref cache); + + public static ImmutableArray ReadCached(this PropertyInfo property, object instance, Func createInstance, ref ImmutableArray cache) + { + if (cache.IsDefault) + { + cache = ((IEnumerable)property.GetValue(instance)).Cast().Select(createInstance).ToImmutableArray(); + } + return cache; + } + } +} diff --git a/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs b/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs index acc80a49f65..85aaa8f4d85 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Helpers/RoslynHelper.cs @@ -19,10 +19,6 @@ */ using System; -using System.Collections; -using System.Collections.Immutable; -using System.Linq; -using System.Reflection; using Microsoft.CodeAnalysis; namespace SonarAnalyzer.CFG.Helpers @@ -36,17 +32,5 @@ public static bool IsRoslynCfgSupported(int minimalVersion = MinimalSupportedMaj public static Type FlowAnalysisType(string typeName) => typeof(SemanticModel).Assembly.GetType("Microsoft.CodeAnalysis.FlowAnalysis." + typeName); - - public static Lazy ReadValue(this PropertyInfo property, object instance) => - ReadValue(property, instance, x => (T)x); - - public static Lazy ReadValue(this PropertyInfo property, object instance, Func createInstance) => - new Lazy(() => createInstance(property.GetValue(instance))); - - public static Lazy> ReadImmutableArray(this PropertyInfo property, object instance) => - ReadImmutableArray(property, instance, x => (T)x); - - public static Lazy> ReadImmutableArray(this PropertyInfo property, object instance, Func createInstance) => - new Lazy>(() => ((IEnumerable)property.GetValue(instance)).Cast().Select(createInstance).ToImmutableArray()); } } diff --git a/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs b/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs index a4535f75a78..d83e4fe0124 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs @@ -31,7 +31,7 @@ namespace SonarAnalyzer.CFG.Roslyn { public class BasicBlock { - private static readonly ConditionalWeakTable InstanceCache = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable InstanceCache = new(); private static readonly PropertyInfo BranchValueProperty; private static readonly PropertyInfo ConditionalSuccessorProperty; private static readonly PropertyInfo ConditionKindProperty; @@ -43,30 +43,31 @@ public class BasicBlock private static readonly PropertyInfo OrdinalProperty; private static readonly PropertyInfo PredecessorsProperty; - private readonly Lazy branchValue; - private readonly Lazy conditionalSuccessor; - private readonly Lazy conditionKind; - private readonly Lazy enclosingRegion; - private readonly Lazy fallThroughSuccessor; - private readonly Lazy isReachable; - private readonly Lazy kind; - private readonly Lazy> operations; - private readonly Lazy ordinal; - private readonly Lazy> predecessors; + private readonly object instance; private readonly Lazy> successors; private readonly Lazy> successorBlocks; private readonly Lazy> operationsAndBranchValue; + private IOperation branchValue; + private ControlFlowBranch conditionalSuccessor; + private ControlFlowConditionKind? conditionKind; + private ControlFlowRegion enclosingRegion; + private ControlFlowBranch fallThroughSuccessor; + private bool? isReachable; + private BasicBlockKind? kind; + private ImmutableArray operations; + private int? ordinal; + private ImmutableArray predecessors; - public IOperation BranchValue => branchValue.Value; - public ControlFlowBranch ConditionalSuccessor => conditionalSuccessor.Value; - public ControlFlowConditionKind ConditionKind => conditionKind.Value; - public ControlFlowRegion EnclosingRegion => enclosingRegion.Value; - public ControlFlowBranch FallThroughSuccessor => fallThroughSuccessor.Value; - public bool IsReachable => isReachable.Value; - public BasicBlockKind Kind => kind.Value; - public ImmutableArray Operations => operations.Value; - public int Ordinal => ordinal.Value; - public ImmutableArray Predecessors => predecessors.Value; + public IOperation BranchValue => BranchValueProperty.ReadCached(instance, ref branchValue); + public ControlFlowBranch ConditionalSuccessor => ConditionalSuccessorProperty.ReadCached(instance, ControlFlowBranch.Wrap, ref conditionalSuccessor); + public ControlFlowConditionKind ConditionKind => ConditionKindProperty.ReadCached(instance, ref conditionKind); + public ControlFlowRegion EnclosingRegion => EnclosingRegionProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref enclosingRegion); + public ControlFlowBranch FallThroughSuccessor => FallThroughSuccessorProperty.ReadCached(instance, ControlFlowBranch.Wrap, ref fallThroughSuccessor); + public bool IsReachable => IsReachableProperty.ReadCached(instance, ref isReachable); + public BasicBlockKind Kind => KindProperty.ReadCached(instance, ref kind); + public ImmutableArray Operations => OperationsProperty.ReadCached(instance, ref operations); + public int Ordinal => OrdinalProperty.ReadCached(instance, ref ordinal); + public ImmutableArray Predecessors => PredecessorsProperty.ReadCached(instance, ControlFlowBranch.Wrap, ref predecessors); public ImmutableArray Successors => successors.Value; public ImmutableArray SuccessorBlocks => successorBlocks.Value; public ImmutableArray OperationsAndBranchValue => operationsAndBranchValue.Value; @@ -90,41 +91,22 @@ static BasicBlock() private BasicBlock(object instance) { - _ = instance ?? throw new ArgumentNullException(nameof(instance)); - branchValue = BranchValueProperty.ReadValue(instance); - conditionalSuccessor = ConditionalSuccessorProperty.ReadValue(instance, ControlFlowBranch.Wrap); - conditionKind = ConditionKindProperty.ReadValue(instance); - enclosingRegion = EnclosingRegionProperty.ReadValue(instance, ControlFlowRegion.Wrap); - fallThroughSuccessor = FallThroughSuccessorProperty.ReadValue(instance, ControlFlowBranch.Wrap); - isReachable = IsReachableProperty.ReadValue(instance); - kind = KindProperty.ReadValue(instance); - operations = OperationsProperty.ReadImmutableArray(instance); - ordinal = OrdinalProperty.ReadValue(instance); - predecessors = PredecessorsProperty.ReadImmutableArray(instance, ControlFlowBranch.Wrap); + this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); successors = new Lazy>(() => { // since Roslyn does not differentiate between pattern types in CFG, it builds unreachable block for missing // pattern match even when discard pattern option is presented. In this case we explicitly exclude this branch if (SwitchExpressionArmSyntaxWrapper.IsInstance(BranchValue?.Syntax) && DiscardPatternSyntaxWrapper.IsInstance(((SwitchExpressionArmSyntaxWrapper)BranchValue.Syntax).Pattern)) { - return FallThroughSuccessor != null ? ImmutableArray.Create(FallThroughSuccessor) : ImmutableArray.Empty; + return FallThroughSuccessor is null ? ImmutableArray.Empty : ImmutableArray.Create(FallThroughSuccessor); } else { - return ImmutableArray.CreateRange(new[] { FallThroughSuccessor, ConditionalSuccessor }.Where(x => x != null)); + return new[] { FallThroughSuccessor, ConditionalSuccessor }.Where(x => x != null).ToImmutableArray(); } }); successorBlocks = new Lazy>(() => Successors.Select(x => x.Destination).Where(x => x != null).ToImmutableArray()); - operationsAndBranchValue = new Lazy>(() => - { - if (BranchValue == null) - { - return Operations; - } - var builder = Operations.ToBuilder(); - builder.Add(BranchValue); - return builder.ToImmutable(); - }); + operationsAndBranchValue = new Lazy>(() => BranchValue is null ? Operations : Operations.Add(BranchValue)); } public bool ContainsThrow() => diff --git a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowBranch.cs b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowBranch.cs index 25659edbf72..c29be64c0f7 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowBranch.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowBranch.cs @@ -28,7 +28,7 @@ namespace SonarAnalyzer.CFG.Roslyn { public class ControlFlowBranch { - private static readonly ConditionalWeakTable InstanceCache = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable InstanceCache = new(); private static readonly PropertyInfo SourceProperty; private static readonly PropertyInfo DestinationProperty; private static readonly PropertyInfo SemanticsProperty; @@ -37,21 +37,22 @@ public class ControlFlowBranch private static readonly PropertyInfo LeavingRegionsProperty; private static readonly PropertyInfo FinallyRegionsProperty; - private readonly Lazy source; - private readonly Lazy destination; - private readonly Lazy semantics; - private readonly Lazy isConditionalSuccessor; - private readonly Lazy> enteringRegions; - private readonly Lazy> leavingRegions; - private readonly Lazy> finallyRegions; + private readonly object instance; + private BasicBlock source; + private BasicBlock destination; + private ControlFlowBranchSemantics? semantics; + private bool? isConditionalSuccessor; + private ImmutableArray enteringRegions; + private ImmutableArray leavingRegions; + private ImmutableArray finallyRegions; - public BasicBlock Source => source.Value; - public BasicBlock Destination => destination.Value; - public ControlFlowBranchSemantics Semantics => semantics.Value; - public bool IsConditionalSuccessor => isConditionalSuccessor.Value; - public ImmutableArray EnteringRegions => enteringRegions.Value; - public ImmutableArray LeavingRegions => leavingRegions.Value; - public ImmutableArray FinallyRegions => finallyRegions.Value; + public BasicBlock Source => SourceProperty.ReadCached(instance, BasicBlock.Wrap, ref source); + public BasicBlock Destination => DestinationProperty.ReadCached(instance, BasicBlock.Wrap, ref destination); + public ControlFlowBranchSemantics Semantics => SemanticsProperty.ReadCached(instance, ref semantics); + public bool IsConditionalSuccessor => IsConditionalSuccessorProperty.ReadCached(instance, ref isConditionalSuccessor); + public ImmutableArray EnteringRegions => EnteringRegionsProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref enteringRegions); + public ImmutableArray LeavingRegions => LeavingRegionsProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref leavingRegions); + public ImmutableArray FinallyRegions => FinallyRegionsProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref finallyRegions); static ControlFlowBranch() { @@ -67,17 +68,8 @@ static ControlFlowBranch() } } - private ControlFlowBranch(object instance) - { - _ = instance ?? throw new ArgumentNullException(nameof(instance)); - source = SourceProperty.ReadValue(instance, BasicBlock.Wrap); - destination = DestinationProperty.ReadValue(instance, BasicBlock.Wrap); - semantics = SemanticsProperty.ReadValue(instance); - isConditionalSuccessor = IsConditionalSuccessorProperty.ReadValue(instance); - enteringRegions = EnteringRegionsProperty.ReadImmutableArray(instance, ControlFlowRegion.Wrap); - leavingRegions = LeavingRegionsProperty.ReadImmutableArray(instance, ControlFlowRegion.Wrap); - finallyRegions = FinallyRegionsProperty.ReadImmutableArray(instance, ControlFlowRegion.Wrap); - } + private ControlFlowBranch(object instance) => + this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); public static ControlFlowBranch Wrap(object instance) => instance == null ? null : InstanceCache.GetValue(instance, x => new ControlFlowBranch(x)); diff --git a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowGraph.cs b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowGraph.cs index 11242320457..a0fb4bacf95 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowGraph.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowGraph.cs @@ -32,7 +32,7 @@ namespace SonarAnalyzer.CFG.Roslyn { public class ControlFlowGraph { - private static readonly ConditionalWeakTable InstanceCache = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable InstanceCache = new(); private static readonly PropertyInfo BlocksProperty; private static readonly PropertyInfo LocalFunctionsProperty; private static readonly PropertyInfo OriginalOperationProperty; @@ -43,18 +43,18 @@ public class ControlFlowGraph private static readonly MethodInfo GetLocalFunctionControlFlowGraphMethod; private readonly object instance; - private readonly Lazy> blocks; - private readonly Lazy> localFunctions; - private readonly Lazy parent; - private readonly Lazy originalOperation; - private readonly Lazy root; + private ImmutableArray blocks; + private ImmutableArray localFunctions; + private ControlFlowGraph parent; + private IOperation originalOperation; + private ControlFlowRegion root; public static bool IsAvailable { get; } - public ImmutableArray Blocks => blocks.Value; - public ImmutableArray LocalFunctions => localFunctions.Value; - public IOperation OriginalOperation => originalOperation.Value; - public ControlFlowGraph Parent => parent.Value; - public ControlFlowRegion Root => root.Value; + public ImmutableArray Blocks => BlocksProperty.ReadCached(instance, BasicBlock.Wrap, ref blocks); + public ImmutableArray LocalFunctions => LocalFunctionsProperty.ReadCached(instance, ref localFunctions); + public IOperation OriginalOperation => OriginalOperationProperty.ReadCached(instance, ref originalOperation); + public ControlFlowGraph Parent => ParentProperty.ReadCached(instance, Wrap, ref parent); + public ControlFlowRegion Root => RootProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref root); public BasicBlock EntryBlock => Blocks[Root.FirstBlockOrdinal]; public BasicBlock ExitBlock => Blocks[Root.LastBlockOrdinal]; @@ -78,11 +78,6 @@ static ControlFlowGraph() private ControlFlowGraph(object instance) { this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); - blocks = BlocksProperty.ReadImmutableArray(instance, BasicBlock.Wrap); - localFunctions = LocalFunctionsProperty.ReadImmutableArray(instance); - originalOperation = OriginalOperationProperty.ReadValue(instance); - parent = ParentProperty.ReadValue(instance, Wrap); - root = RootProperty.ReadValue(instance, ControlFlowRegion.Wrap); Debug.Assert(EntryBlock.Kind == BasicBlockKind.Entry, "Roslyn CFG Entry block is not the first one"); Debug.Assert(ExitBlock.Kind == BasicBlockKind.Exit, "Roslyn CFG Exit block is not the last one"); } diff --git a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowRegion.cs b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowRegion.cs index 395d56c94cc..07df409d476 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowRegion.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Roslyn/ControlFlowRegion.cs @@ -30,7 +30,7 @@ namespace SonarAnalyzer.CFG.Roslyn { public class ControlFlowRegion { - private static readonly ConditionalWeakTable InstanceCache = new ConditionalWeakTable(); + private static readonly ConditionalWeakTable InstanceCache = new(); private static readonly PropertyInfo KindProperty; private static readonly PropertyInfo EnclosingRegionProperty; private static readonly PropertyInfo ExceptionTypeProperty; @@ -41,25 +41,26 @@ public class ControlFlowRegion private static readonly PropertyInfo LocalFunctionsProperty; private static readonly PropertyInfo CaptureIdsProperty; - private readonly Lazy kind; - private readonly Lazy enclosingRegion; - private readonly Lazy exceptionType; - private readonly Lazy firstBlockOrdinal; - private readonly Lazy lastBlockOrdinal; - private readonly Lazy> nestedRegions; - private readonly Lazy> locals; - private readonly Lazy> localFunctions; - private readonly Lazy> captureIds; + private readonly object instance; + private ControlFlowRegionKind? kind; + private ControlFlowRegion enclosingRegion; + private ITypeSymbol exceptionType; + private int? firstBlockOrdinal; + private int? lastBlockOrdinal; + private ImmutableArray nestedRegions; + private ImmutableArray locals; + private ImmutableArray localFunctions; + private ImmutableArray captureIds; - public ControlFlowRegionKind Kind => kind.Value; - public ControlFlowRegion EnclosingRegion => enclosingRegion.Value; - public ITypeSymbol ExceptionType => exceptionType.Value; - public int FirstBlockOrdinal => firstBlockOrdinal.Value; - public int LastBlockOrdinal => lastBlockOrdinal.Value; - public ImmutableArray NestedRegions => nestedRegions.Value; - public ImmutableArray Locals => locals.Value; - public ImmutableArray LocalFunctions => localFunctions.Value; - public ImmutableArray CaptureIds => captureIds.Value; + public ControlFlowRegionKind Kind => KindProperty.ReadCached(instance, ref kind); + public ControlFlowRegion EnclosingRegion => EnclosingRegionProperty.ReadCached(instance, Wrap, ref enclosingRegion); + public ITypeSymbol ExceptionType => ExceptionTypeProperty.ReadCached(instance, ref exceptionType); + public int FirstBlockOrdinal => FirstBlockOrdinalProperty.ReadCached(instance, ref firstBlockOrdinal); + public int LastBlockOrdinal => LastBlockOrdinalProperty.ReadCached(instance, ref lastBlockOrdinal); + public ImmutableArray NestedRegions => NestedRegionsProperty.ReadCached(instance, Wrap, ref nestedRegions); + public ImmutableArray Locals => LocalsProperty.ReadCached(instance, ref locals); + public ImmutableArray LocalFunctions => LocalFunctionsProperty.ReadCached(instance, ref localFunctions); + public ImmutableArray CaptureIds => CaptureIdsProperty.ReadCached(instance, x => new CaptureId(x), ref captureIds); static ControlFlowRegion() { @@ -77,19 +78,8 @@ static ControlFlowRegion() } } - private ControlFlowRegion(object instance) - { - _ = instance ?? throw new ArgumentNullException(nameof(instance)); - kind = KindProperty.ReadValue(instance); - enclosingRegion = EnclosingRegionProperty.ReadValue(instance, Wrap); - exceptionType = ExceptionTypeProperty.ReadValue(instance); - firstBlockOrdinal = FirstBlockOrdinalProperty.ReadValue(instance); - lastBlockOrdinal = LastBlockOrdinalProperty.ReadValue(instance); - nestedRegions = NestedRegionsProperty.ReadImmutableArray(instance, Wrap); - locals = LocalsProperty.ReadImmutableArray(instance); - localFunctions = LocalFunctionsProperty.ReadImmutableArray(instance); - captureIds = CaptureIdsProperty.ReadImmutableArray(instance, x => new CaptureId(x)); - } + private ControlFlowRegion(object instance) => + this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); public static ControlFlowRegion Wrap(object instance) => instance == null ? null : InstanceCache.GetValue(instance, x => new ControlFlowRegion(x)); diff --git a/analyzers/src/SonarAnalyzer.CFG/ShimLayer/IOperationWrapperSonar.cs b/analyzers/src/SonarAnalyzer.CFG/ShimLayer/IOperationWrapperSonar.cs index 38e9a921618..55856527e4b 100644 --- a/analyzers/src/SonarAnalyzer.CFG/ShimLayer/IOperationWrapperSonar.cs +++ b/analyzers/src/SonarAnalyzer.CFG/ShimLayer/IOperationWrapperSonar.cs @@ -22,7 +22,7 @@ using System.Collections.Generic; using System.Reflection; using Microsoft.CodeAnalysis; -using SonarAnalyzer.CFG.Helpers; +using SonarAnalyzer.CFG; namespace StyleCop.Analyzers.Lightup { @@ -42,11 +42,11 @@ public class IOperationWrapperSonar private SemanticModel semanticModel; public IOperation Instance { get; } - public IOperation Parent => parent ??= (IOperation)ParentProperty.GetValue(Instance); - public IEnumerable Children => children ??= (IEnumerable)ChildrenProperty.GetValue(Instance); - public string Language => language ??= (string)LanguageProperty.GetValue(Instance); - public bool IsImplicit => isImplicit ??= (bool)IsImplicitProperty.GetValue(Instance); - public SemanticModel SemanticModel => semanticModel ??= (SemanticModel)SemanticModelProperty.GetValue(Instance); + public IOperation Parent => ParentProperty.ReadCached(Instance, ref parent); + public IEnumerable Children => ChildrenProperty.ReadCached(Instance, ref children); + public string Language => LanguageProperty.ReadCached(Instance, ref language); + public bool IsImplicit => IsImplicitProperty.ReadCached(Instance, ref isImplicit); + public SemanticModel SemanticModel => SemanticModelProperty.ReadCached(Instance, ref semanticModel); static IOperationWrapperSonar() { From 1358666a1bd1d3bfd8d88647b98315a6bcd659b7 Mon Sep 17 00:00:00 2001 From: Pavel Mikula Date: Fri, 18 Feb 2022 08:54:19 +0100 Subject: [PATCH 2/2] Review update --- analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs b/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs index d83e4fe0124..d87a7c02b88 100644 --- a/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs +++ b/analyzers/src/SonarAnalyzer.CFG/Roslyn/BasicBlock.cs @@ -63,10 +63,10 @@ public class BasicBlock public ControlFlowConditionKind ConditionKind => ConditionKindProperty.ReadCached(instance, ref conditionKind); public ControlFlowRegion EnclosingRegion => EnclosingRegionProperty.ReadCached(instance, ControlFlowRegion.Wrap, ref enclosingRegion); public ControlFlowBranch FallThroughSuccessor => FallThroughSuccessorProperty.ReadCached(instance, ControlFlowBranch.Wrap, ref fallThroughSuccessor); - public bool IsReachable => IsReachableProperty.ReadCached(instance, ref isReachable); - public BasicBlockKind Kind => KindProperty.ReadCached(instance, ref kind); + public bool IsReachable => IsReachableProperty.ReadCached(instance, ref isReachable); + public BasicBlockKind Kind => KindProperty.ReadCached(instance, ref kind); public ImmutableArray Operations => OperationsProperty.ReadCached(instance, ref operations); - public int Ordinal => OrdinalProperty.ReadCached(instance, ref ordinal); + public int Ordinal => OrdinalProperty.ReadCached(instance, ref ordinal); public ImmutableArray Predecessors => PredecessorsProperty.ReadCached(instance, ControlFlowBranch.Wrap, ref predecessors); public ImmutableArray Successors => successors.Value; public ImmutableArray SuccessorBlocks => successorBlocks.Value;