Browse Source

Simplified several inspectors. Includes some minor bugfixes.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
a3ced27e3e
  1. 2
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 19
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs
  3. 6
      ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs
  4. 14
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/ConditionalToNullCoalescingInspector.cs
  5. 19
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantInternalInspector.cs
  6. 11
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantNamespaceUsageInspector.cs
  7. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantPrivateInspector.cs
  8. 8
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantThisInspector.cs
  9. 2
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs
  10. 72
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/StringIsNullOrEmptyInspector.cs
  11. 62
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/UseVarKeywordInspector.cs
  12. 40
      ICSharpCode.NRefactory.CSharp/Refactoring/PatternHelper.cs
  13. 49
      ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringAstHelper.cs
  14. 23
      ICSharpCode.NRefactory.Tests/CSharp/ContextAction/ConvertForeachToForTests.cs

2
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -265,6 +265,8 @@ @@ -265,6 +265,8 @@
<Compile Include="Refactoring\ContextAction\UseVarKeyword.cs" />
<Compile Include="Refactoring\DocumentScript.cs" />
<Compile Include="Refactoring\IContextAction.cs" />
<Compile Include="Refactoring\PatternHelper.cs" />
<Compile Include="Refactoring\RefactoringAstHelper.cs" />
<Compile Include="Refactoring\RefactoringContext.cs" />
<Compile Include="Refactoring\Script.cs" />
<Compile Include="Refactoring\TypeSystemAstBuilder.cs" />

19
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs

@ -46,10 +46,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -46,10 +46,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (bodyStatement == null)
return false;
if (parameter.Type is PrimitiveType)
return (((PrimitiveType)parameter.Type).Keyword == "object" || ((PrimitiveType)parameter.Type).Keyword == "string") && !HasNullCheck (parameter);
var type = context.ResolveType(parameter.Type);
if (type.IsReferenceType == false)
return false;
// TODO: check for structs
return !HasNullCheck (parameter);
}
@ -83,25 +83,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -83,25 +83,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class CheckNullVisitor : DepthFirstAstVisitor<object, object>
{
ParameterDeclaration parameter;
readonly Expression pattern;
public bool ContainsNullCheck {
get;
set;
}
internal bool ContainsNullCheck;
public CheckNullVisitor (ParameterDeclaration parameter)
{
this.parameter = parameter;
this.pattern = PatternHelper.CommutativeOperator(new IdentifierExpression(parameter.Name), BinaryOperatorType.Any, new NullReferenceExpression());
}
public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data)
{
if (ifElseStatement.Condition is BinaryOperatorExpression) {
var binOp = ifElseStatement.Condition as BinaryOperatorExpression;
if ((binOp.Operator == BinaryOperatorType.Equality || binOp.Operator == BinaryOperatorType.InEquality) &&
binOp.Left.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Right.IsMatch (new NullReferenceExpression ()) ||
binOp.Right.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Left.IsMatch (new NullReferenceExpression ())) {
if ((binOp.Operator == BinaryOperatorType.Equality || binOp.Operator == BinaryOperatorType.InEquality) && pattern.IsMatch(binOp)) {
ContainsNullCheck = true;
}
}

6
ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs

@ -54,6 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -54,6 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var result = context.Resolve (foreachStatement.InExpression);
var countProperty = GetCountProperty (result.Type);
// TODO: use another variable name if 'i' is already in use
var initializer = new VariableDeclarationStatement (new PrimitiveType ("int"), "i", new PrimitiveExpression (0));
var id1 = new IdentifierExpression ("i");
var id2 = id1.Clone ();
@ -88,7 +89,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -88,7 +89,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (astNode == null)
return null;
var result = (astNode as ForeachStatement) ?? astNode.Parent as ForeachStatement;
if (result == null || context.Resolve (result.InExpression) == null)
if (result == null)
return null;
var collection = context.Resolve (result.InExpression);
if (collection.Type.Kind != TypeKind.Array && !collection.Type.GetProperties(p => p.IsIndexer).Any())
return null;
return result;
}

14
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/ConditionalToNullCoalescingInspector.cs

@ -39,23 +39,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -39,23 +39,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
static readonly Pattern pattern = new Choice {
// a != null ? a : other
new ConditionalExpression(
new Choice {
// a != null
new BinaryOperatorExpression(new AnyNode("a"), BinaryOperatorType.InEquality, new NullReferenceExpression()),
// null != a
new BinaryOperatorExpression(new NullReferenceExpression(), BinaryOperatorType.InEquality, new AnyNode("a")),
},
PatternHelper.CommutativeOperator(new AnyNode("a"), BinaryOperatorType.InEquality, new NullReferenceExpression()),
new Backreference("a"),
new AnyNode("other")
),
// a == null ? other : a
new ConditionalExpression(
new Choice {
// a == null
new BinaryOperatorExpression(new AnyNode("a"), BinaryOperatorType.Equality, new NullReferenceExpression()),
// null == a
new BinaryOperatorExpression(new NullReferenceExpression(), BinaryOperatorType.Equality, new AnyNode("a")),
},
PatternHelper.CommutativeOperator(new AnyNode("a"), BinaryOperatorType.Equality, new NullReferenceExpression()),
new AnyNode("other"),
new Backreference("a")
),

19
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantInternalInspector.cs

@ -65,19 +65,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -65,19 +65,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
if (!(typeDeclaration.Parent is TypeDeclaration)) {
foreach (var token_ in typeDeclaration.ModifierTokens) {
var token = token_;
if (token.Modifier == Modifiers.Internal) {
AddIssue(token, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Remove(token);
}
});
}
foreach (var token_ in typeDeclaration.ModifierTokens) {
var token = token_;
if (token.Modifier == Modifiers.Internal) {
AddIssue(token, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Remove(token);
}
});
}
}
base.VisitTypeDeclaration(typeDeclaration);
}
}
}

11
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantNamespaceUsageInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// RedundantNamespaceUsageInspector.cs
//
// Author:
@ -25,10 +25,11 @@ @@ -25,10 +25,11 @@
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -80,10 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -80,10 +81,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var state = ctx.GetResolverStateBefore(memberReferenceExpression);
var lookupName = state.LookupSimpleNameOrTypeName(memberReferenceExpression.MemberName, new List<IType> (), SimpleNameLookupMode.Expression);
if (lookupName != null && wholeResult.Type.Equals(lookupName.Type)) {
if (lookupName is TypeResolveResult && !lookupName.IsError && wholeResult.Type.Equals(lookupName.Type)) {
AddIssue(memberReferenceExpression.StartLocation, memberReferenceExpression.MemberNameToken.StartLocation, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Replace(memberReferenceExpression, new IdentifierExpression (memberReferenceExpression.MemberName));
script.Replace(memberReferenceExpression, RefactoringAstHelper.RemoveTarget(memberReferenceExpression));
}
}
);

2
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantPrivateInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// RedundantPrivateInspector.cs
//
// Author:

8
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantThisInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// RedundantThisInspector.cs
//
// Author:
@ -72,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -72,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (result is MemberResolveResult) {
return ((MemberResolveResult)result).Member;
} else if (result is MethodGroupResolveResult) {
return ((MethodGroupResolveResult)result).Methods.First ();
return ((MethodGroupResolveResult)result).Methods.FirstOrDefault ();
}
return null;
@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return;
}
var result = state.LookupSimpleNameOrTypeName (memberReference.MemberName, new List<IType> (), SimpleNameLookupMode.Expression);
var result = state.LookupSimpleNameOrTypeName (memberReference.MemberName, EmptyList<IType>.Instance, SimpleNameLookupMode.Expression);
bool isRedundant;
if (result is MemberResolveResult) {
@ -108,7 +108,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -108,7 +108,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (isRedundant) {
AddIssue(thisReferenceExpression.StartLocation, memberReference.MemberNameToken.StartLocation, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Replace(memberReference, new IdentifierExpression (memberReference.MemberName));
script.Replace(memberReference, RefactoringAstHelper.RemoveTarget(memberReference));
}
}
);

2
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// RedundantUsingInspector.cs
//
// Author:

72
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/StringIsNullOrEmptyInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// StringIsNullOrEmptyInspector.cs
//
// Author:
@ -37,72 +37,32 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -37,72 +37,32 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public class StringIsNullOrEmptyInspector : IInspector
{
static readonly Pattern pattern = new Choice {
// str == null && str == ""
// str == null || str == ""
new BinaryOperatorExpression (
new Choice {
// str == null
new BinaryOperatorExpression (new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
// null == str
new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.Equality, new AnyNode ("str")),
},
BinaryOperatorType.ConditionalAnd,
new Choice {
// str == ""
new BinaryOperatorExpression (new Backreference ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")),
// "" == str
new BinaryOperatorExpression (new PrimitiveExpression (""), BinaryOperatorType.Equality, new Backreference ("str")),
}
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
BinaryOperatorType.ConditionalOr,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new PrimitiveExpression (""))
),
// str == "" && str == null
// str == "" || str == null
new BinaryOperatorExpression (
new Choice {
// str == ""
new BinaryOperatorExpression (new AnyNode ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")),
// "" == str
new BinaryOperatorExpression (new PrimitiveExpression (""), BinaryOperatorType.Equality, new AnyNode ("str")),
},
BinaryOperatorType.ConditionalAnd,
new Choice {
// str == null
new BinaryOperatorExpression (new Backreference ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
// null == str
new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.Equality, new Backreference ("str")),
}
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")),
BinaryOperatorType.ConditionalOr,
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ())
),
};
static readonly Pattern negPattern = new Choice {
// str != null && str != ""
new BinaryOperatorExpression (
new Choice {
// str != null
new BinaryOperatorExpression (new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
// null != str
new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.InEquality, new AnyNode ("str")),
},
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
BinaryOperatorType.ConditionalAnd,
new Choice {
// str != ""
new BinaryOperatorExpression (new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
// "" != str
new BinaryOperatorExpression (new PrimitiveExpression (""), BinaryOperatorType.InEquality, new Backreference ("str")),
}
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression (""))
),
// str != "" && str != null
new BinaryOperatorExpression (
new Choice {
// str != ""
new BinaryOperatorExpression (new AnyNode ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
// "" != str
new BinaryOperatorExpression (new PrimitiveExpression (""), BinaryOperatorType.InEquality, new AnyNode ("str")),
},
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
BinaryOperatorType.ConditionalAnd,
new Choice {
// str != null
new BinaryOperatorExpression (new Backreference ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
// null != str
new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.InEquality, new Backreference ("str")),
}
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ())
),
};
@ -146,11 +106,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -146,11 +106,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var str = m.Get<Expression>("str").Single();
AddIssue(binaryOperatorExpression, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
Expression expr = new InvocationExpression (
new MemberReferenceExpression (
new TypeReferenceExpression (new PrimitiveType ("string")),
"IsNullOrEmpty"
), str.Clone());
Expression expr = new PrimitiveType ("string").Invoke("IsNullOrEmpty", str.Clone());
if (isNegated)
expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr);
script.Replace(binaryOperatorExpression, expr);

62
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/UseVarKeywordInspector.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// UseVarKeywordInspector.cs
//
// Author:
@ -74,46 +74,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -74,46 +74,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (variableDeclarationStatement.Type is SimpleType && ((SimpleType)variableDeclarationStatement.Type).Identifier == "var") {
return;
}
if (variableDeclarationStatement.Variables.Count != 1) {
return;
}
//only checks for cases where the type would be obvious - assignment of new, cast, etc.
//also check the type actually matches else the user might want to assign different subclasses later
foreach (var v in variableDeclarationStatement.Variables) {
if (v.Initializer.IsNull) {
return;
}
var v = variableDeclarationStatement.Variables.Single();
var arrCreate = v.Initializer as ArrayCreateExpression;
if (arrCreate != null) {
var n = variableDeclarationStatement.Type as ComposedType;
//FIXME: check the specifier compatibility
if (n != null && n.ArraySpecifiers.Any() && n.BaseType.IsMatch(arrCreate.Type)) {
continue;
}
return;
}
var objCreate = v.Initializer as ObjectCreateExpression;
if (objCreate != null) {
if (objCreate.Type.IsMatch(variableDeclarationStatement.Type)) {
continue;
}
return;
}
var asCast = v.Initializer as AsExpression;
if (asCast != null) {
if (asCast.Type.IsMatch(variableDeclarationStatement.Type)) {
continue;
}
return;
}
var cast = v.Initializer as CastExpression;
if (cast != null) {
if (cast.Type.IsMatch(variableDeclarationStatement.Type)) {
continue;
}
return;
var arrCreate = v.Initializer as ArrayCreateExpression;
if (arrCreate != null) {
var n = variableDeclarationStatement.Type as ComposedType;
//FIXME: check the specifier compatibility
if (n != null && n.ArraySpecifiers.Any() && n.BaseType.IsMatch(arrCreate.Type)) {
AddIssue(variableDeclarationStatement);
}
return;
}
var objCreate = v.Initializer as ObjectCreateExpression;
if (objCreate != null && objCreate.Type.IsMatch(variableDeclarationStatement.Type)) {
AddIssue(variableDeclarationStatement);
}
var asCast = v.Initializer as AsExpression;
if (asCast != null && asCast.Type.IsMatch(variableDeclarationStatement.Type)) {
AddIssue(variableDeclarationStatement);
}
var cast = v.Initializer as CastExpression;
if (cast != null && cast.Type.IsMatch(variableDeclarationStatement.Type)) {
AddIssue(variableDeclarationStatement);
}
}
void AddIssue(VariableDeclarationStatement variableDeclarationStatement)
{
AddIssue(variableDeclarationStatement.Type, inspector.Title);
}
}

40
ICSharpCode.NRefactory.CSharp/Refactoring/PatternHelper.cs

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Helper class for constructing pattern ASTs.
/// </summary>
public class PatternHelper
{
/// <summary>
/// Produces a choice pattern for <c>expr1 op expr2</c> or <c>expr2 op expr1</c>.
/// </summary>
public static Expression CommutativeOperator(Expression expr1, BinaryOperatorType op, Expression expr2)
{
return new Choice {
new BinaryOperatorExpression(expr1, op, expr2),
new BinaryOperatorExpression(expr2.Clone(), op, expr1.Clone())
};
}
}
}

49
ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringAstHelper.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Helper methods for constructing ASTs for refactoring.
/// These helpers work with frozen ASTs, i.e. they clone input nodes.
/// </summary>
public class RefactoringAstHelper
{
/// <summary>
/// Removes the target from a member reference while preserving the identifier and type arguments.
/// </summary>
public static IdentifierExpression RemoveTarget(MemberReferenceExpression mre)
{
IdentifierExpression ident = new IdentifierExpression(mre.MemberName);
ident.TypeArguments.AddRange(mre.TypeArguments.Select(t => t.Clone()));
return ident;
}
/// <summary>
/// Removes the target from a member reference while preserving the identifier and type arguments.
/// </summary>
public static SimpleType RemoveTarget(MemberType memberType)
{
return new SimpleType(memberType.MemberName, memberType.TypeArguments.Select(t => t.Clone()));
}
}
}

23
ICSharpCode.NRefactory.Tests/CSharp/ContextAction/ConvertForeachToForTests.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// ConvertForeachToForTests.cs
//
// Author:
@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions @@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions
}
[Test()]
public void TestEnumeration ()
public void TestListOfT ()
{
string result = RunContextAction (
new ConvertForeachToFor (),
@ -95,5 +95,24 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions @@ -95,5 +95,24 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions
" }" + Environment.NewLine +
"}", result);
}
[Test()]
public void TestEnumerableOfT ()
{
TestWrongContext (
new ConvertForeachToFor (),
"using System;" + Environment.NewLine +
"using System.Collections.Generic;" + Environment.NewLine +
"class TestClass" + Environment.NewLine +
"{" + Environment.NewLine +
" void Test (IEnumerable<string> args)" + Environment.NewLine +
" {" + Environment.NewLine +
" $foreach (var v in args) {" + Environment.NewLine +
" Console.WriteLine (v);" + Environment.NewLine +
" }" + Environment.NewLine +
" }" + Environment.NewLine +
"}"
);
}
}
}
Loading…
Cancel
Save