diff --git a/Gu.Analyzers.Test/GU0023StaticMemberOrderTests/HappyPath.cs b/Gu.Analyzers.Test/GU0023StaticMemberOrderTests/HappyPath.cs index e0d8a2db..92c190a5 100644 --- a/Gu.Analyzers.Test/GU0023StaticMemberOrderTests/HappyPath.cs +++ b/Gu.Analyzers.Test/GU0023StaticMemberOrderTests/HappyPath.cs @@ -24,6 +24,24 @@ public class Foo AnalyzerAssert.Valid(Analyzer, code); } + [Test] + public void FieldInitializedWithFuncUsingField() + { + var code = @" +namespace RoslynSandbox +{ + using System; + + public class Foo + { + public static readonly Func Value1 = () => Value2; + + public static readonly int Value2 = 2; + } +}"; + AnalyzerAssert.Valid(Analyzer, code); + } + [Test] public void FieldInitializedWithStaticProperty() { diff --git a/Gu.Analyzers/GU0023StaticMemberOrderAnalyzer.cs b/Gu.Analyzers/GU0023StaticMemberOrderAnalyzer.cs index f025ee50..6fcebcbf 100644 --- a/Gu.Analyzers/GU0023StaticMemberOrderAnalyzer.cs +++ b/Gu.Analyzers/GU0023StaticMemberOrderAnalyzer.cs @@ -1,6 +1,8 @@ namespace Gu.Analyzers { + using System.Collections.Generic; using System.Collections.Immutable; + using System.Threading; using Gu.Roslyn.AnalyzerExtensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -55,7 +57,7 @@ variable.Initializer.Value is ExpressionSyntax fieldValue && private static bool IsInitializedWithUninitialized(ExpressionSyntax value, SyntaxNodeAnalysisContext context, out FieldOrProperty other) { - using (var walker = IdentifierNameExecutionWalker.Borrow(value, Scope.Type, context.SemanticModel, context.CancellationToken)) + using (var walker = Walker.Borrow(value, context.SemanticModel, context.CancellationToken)) { foreach (var identifierName in walker.IdentifierNames) { @@ -98,5 +100,54 @@ private static bool IsInitialized(MemberDeclarationSyntax declaration) return false; } } + + private sealed class Walker : ExecutionWalker + { + private readonly List identifierNames = new List(); + + private Walker() + { + } + + /// + /// Gets the s found in the scope. + /// + public IReadOnlyList IdentifierNames => this.identifierNames; + + /// + /// Get a walker that has visited + /// + /// The node + /// The + /// The + /// A walker that has visited + public static Walker Borrow(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) + { + return BorrowAndVisit(node, Scope.Type, semanticModel, cancellationToken, () => new Walker()); + } + + public override void VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) + { + // don't walk lambda + } + + public override void VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node) + { + // don't walk lambda + } + + /// + public override void VisitIdentifierName(IdentifierNameSyntax node) + { + this.identifierNames.Add(node); + base.VisitIdentifierName(node); + } + + /// + protected override void Clear() + { + this.identifierNames.Clear(); + } + } } }