From a46f5e987465ddd98346c84b268220e3a0ba8bc9 Mon Sep 17 00:00:00 2001 From: Simon Lindgren Date: Sat, 25 Aug 2012 01:54:52 +0200 Subject: [PATCH] [CodeIssues] Don't warn about static fields in generic types if the field declaration uses all type parameters. --- .../StaticFieldInGenericTypeIssue.cs | 38 +++++++++++++--- .../StaticFieldInGenericTypeTests.cs | 44 ++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StaticFieldInGenericTypeIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StaticFieldInGenericTypeIssue.cs index f93f9368b6..2d1cfedb74 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StaticFieldInGenericTypeIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StaticFieldInGenericTypeIssue.cs @@ -25,6 +25,8 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; +using System.Linq; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -45,21 +47,47 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { } - bool isInGenericType = false; + IList availableTypeParameters = new List(); public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) { - var oldGenericStatus = isInGenericType; + var typeResolveResult = ctx.Resolve(typeDeclaration); + var newTypeParameters = typeResolveResult.Type.GetDefinition().TypeParameters; - isInGenericType = typeDeclaration.TypeParameters.Count > 0; + var oldTypeParameters = availableTypeParameters; + availableTypeParameters = Concat(availableTypeParameters, newTypeParameters); base.VisitTypeDeclaration(typeDeclaration); - isInGenericType = oldGenericStatus; + + availableTypeParameters = oldTypeParameters; + } + + static IList Concat(params IList[] lists) + { + return lists.SelectMany(l => l).ToList(); + } + + bool UsesAllTypeParameters(FieldDeclaration fieldDeclaration) + { + if (availableTypeParameters.Count == 0) + return true; + + var fieldType = ctx.Resolve(fieldDeclaration.ReturnType).Type as ParameterizedType; + if (fieldType == null) + return false; + + // Check that all current type parameters are used in the field type + var fieldTypeParameters = fieldType.TypeArguments; + foreach (var typeParameter in availableTypeParameters) { + if (!fieldTypeParameters.Contains(typeParameter)) + return false; + } + return true; } public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration) { - if (isInGenericType && fieldDeclaration.Modifiers.HasFlag(Modifiers.Static)) { + if (fieldDeclaration.Modifiers.HasFlag(Modifiers.Static) && !UsesAllTypeParameters(fieldDeclaration)) { AddIssue(fieldDeclaration, ctx.TranslateString("Static field in generic type")); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticFieldInGenericTypeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticFieldInGenericTypeTests.cs index 64d5804b51..fa3084860b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticFieldInGenericTypeTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StaticFieldInGenericTypeTests.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues [TestFixture] public class StaticFieldInGenericTypeTests : InspectionActionTestBase { - + [Test] public void GenericClass() { @@ -48,6 +48,48 @@ class Foo Assert.AreEqual(1, issues.Count); } + [Test] + public void GenericClassWithGenericField() + { + var input = @" +class Foo +{ + static System.Collections.Generic.IList Cache; +}"; + TestRefactoringContext context; + var issues = GetIssues(new StaticFieldInGenericTypeIssue(), input, out context); + Assert.AreEqual(0, issues.Count); + } + + [Test] + public void GenericClassWithMultipleGenericFields() + { + var input = @" +class Foo +{ + static System.Collections.Generic.IList Cache; +}"; + TestRefactoringContext context; + var issues = GetIssues(new StaticFieldInGenericTypeIssue(), input, out context); + Assert.AreEqual(1, issues.Count); + } + + [Test] + public void NestedGenericClassWithGenericField() + { + var input = @" +class Foo +{ + class Bar + { + static System.Collections.Generic.IList Cache; + } +}"; + TestRefactoringContext context; + var issues = GetIssues(new StaticFieldInGenericTypeIssue(), input, out context); + Assert.AreEqual(1, issues.Count); + } + [Test] public void NonGenericClass() {