Browse Source

Reference to static member via derived type: ignore curiously recurring template pattern

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
81c09524d6
  1. 27
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ReferenceToStaticMemberViaDerivedTypeIssue.cs
  2. 22
      ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ReferenceToStaticMemberViaDerivedTypeTests.cs

27
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ReferenceToStaticMemberViaDerivedTypeIssue.cs

@ -89,6 +89,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -89,6 +89,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return;
if (typeResolveResult.Type.Equals(member.DeclaringType))
return;
// check whether member.DeclaringType contains the original type
// (curiously recurring template pattern)
var v = new ContainsTypeVisitor(typeResolveResult.Type.GetDefinition());
member.DeclaringType.AcceptVisitor(v);
if (v.IsContained)
return;
AddIssue(issueAnchor, context.TranslateString("Static method invoked via derived type"),
GetActions(context, targetExpression, member));
}
@ -96,14 +102,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -96,14 +102,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IEnumerable<CodeAction> GetActions(BaseRefactoringContext context, Expression targetExpression,
IMember member)
{
var csResolver = context.Resolver.GetResolverStateBefore(targetExpression);
var builder = new TypeSystemAstBuilder(csResolver);
var builder = context.CreateTypeSytemAstBuilder(targetExpression);
var newType = builder.ConvertType(member.DeclaringType);
string description = string.Format("{0} '{1}'", context.TranslateString("Use base class"), newType.GetText());
yield return new CodeAction(description, script => {
script.Replace(targetExpression, newType);
});
}
sealed class ContainsTypeVisitor : TypeVisitor
{
readonly ITypeDefinition searchedType;
internal bool IsContained;
public ContainsTypeVisitor(ITypeDefinition searchedType)
{
this.searchedType = searchedType;
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (type.Equals(searchedType))
IsContained = true;
return base.VisitTypeDefinition(type);
}
}
}
#endregion
}

22
ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ReferenceToStaticMemberViaDerivedTypeTests.cs

@ -299,6 +299,28 @@ class B : A @@ -299,6 +299,28 @@ class B : A
var issues = GetIssues(new ReferenceToStaticMemberViaDerivedTypeIssue(), input, out context);
Assert.AreEqual(0, issues.Count);
}
[Test]
public void IgnoresCuriouslyRecurringTemplatePattern()
{
var input = @"
class Base<T>
{
public static void F() { }
}
class Derived : Base<Derived> {}
class Test
{
void Main()
{
Derived.F();
}
}";
// do not suggest replacing 'Derived.F()' with 'Base<Derived>.F()'
TestRefactoringContext context;
var issues = GetIssues(new ReferenceToStaticMemberViaDerivedTypeIssue(), input, out context);
Assert.AreEqual(0, issues.Count);
}
}
}

Loading…
Cancel
Save