From b40843eab577001bcb2ce146df5ff5a6c0abc62e Mon Sep 17 00:00:00 2001 From: Giovanni Bassi Date: Fri, 19 Aug 2016 12:09:58 -0300 Subject: [PATCH] Ignore member order on ReadonlyFieldAnalyzer Fix #812 Add constructor to the top of the list so we add fields with constructors initializers first --- .../Usage/ReadonlyFieldAnalyzer.cs | 14 +++++++++++ .../Usage/ReadonlyFieldTests.cs | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs index 401e7ef48..d9db192ba 100644 --- a/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs +++ b/src/CSharp/CodeCracker/Usage/ReadonlyFieldAnalyzer.cs @@ -36,6 +36,19 @@ private static void AnalyzeCompilation(CompilationStartAnalysisContext compilati compilationStartAnalysisContext.RegisterSyntaxTreeAction(context => AnalyzeTree(context, compilation)); } + private struct MethodKindComparer : IComparer + { + public int Compare(MethodKind x, MethodKind y) => + x - y == 0 + ? 0 + : (x == MethodKind.Constructor + ? 1 + : (y == MethodKind.Constructor + ? -1 + : x - y)); + } + private static readonly MethodKindComparer methodKindComparer = new MethodKindComparer(); + private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation compilation) { if (context.IsGenerated()) return; @@ -51,6 +64,7 @@ private static void AnalyzeTree(SyntaxTreeAnalysisContext context, Compilation c var typeSymbol = semanticModel.GetDeclaredSymbol(type); if (typeSymbol == null) continue; var methods = typeSymbol.GetAllMethodsIncludingFromInnerTypes(); + methods = methods.OrderByDescending(m => m.MethodKind, methodKindComparer).ToList(); foreach (var method in methods) { foreach (var syntaxReference in method.DeclaringSyntaxReferences) diff --git a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs index efbaa8c12..e4181d876 100644 --- a/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs +++ b/test/CSharp/CodeCracker.Test/Usage/ReadonlyFieldTests.cs @@ -967,5 +967,29 @@ public Person(string name) }; await VerifyCSharpDiagnosticAsync(source, expected); } + + [Fact] + public async Task IgnoreWhenConstructorIsTheLastMember() + { + const string source = @" +class Test +{ + private int value; + public int Value + { + get { return value; } + set { this.value = value; } + } + public void Foo() + { + value = 1; + } + public Test() + { + value = 8; + } +}"; + await VerifyCSharpHasNoDiagnosticsAsync(source); + } } }