Browse Source

Merge branch 'master' of github.com:icsharpcode/NRefactory

newNRvisualizers
Mike Krüger 14 years ago
parent
commit
df285ae264
  1. 8
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 10
      ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
  3. 105
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/ConditionalToNullCoalescingInspector.cs
  4. 7
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/GatherVisitorBase.cs
  5. 77
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/NotImplementedExceptionInspector.cs
  6. 84
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantInternalInspector.cs
  7. 94
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantNamespaceUsageInspector.cs
  8. 142
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantPrivateInspector.cs
  9. 130
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantThisInspector.cs
  10. 77
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs
  11. 165
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/StringIsNullOrEmptyInspector.cs
  12. 121
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/UseVarKeywordInspector.cs

8
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -327,6 +327,14 @@ @@ -327,6 +327,14 @@
<Compile Include="Refactoring\InspectionIssue.cs" />
<Compile Include="Refactoring\BaseRefactoringContext.cs" />
<Compile Include="Refactoring\Inspector\GatherVisitorBase.cs" />
<Compile Include="Refactoring\Inspector\NotImplementedExceptionInspector.cs" />
<Compile Include="Refactoring\Inspector\RedundantInternalInspector.cs" />
<Compile Include="Refactoring\Inspector\RedundantNamespaceUsageInspector.cs" />
<Compile Include="Refactoring\Inspector\RedundantPrivateInspector.cs" />
<Compile Include="Refactoring\Inspector\RedundantThisInspector.cs" />
<Compile Include="Refactoring\Inspector\RedundantUsingInspector.cs" />
<Compile Include="Refactoring\Inspector\StringIsNullOrEmptyInspector.cs" />
<Compile Include="Refactoring\Inspector\UseVarKeywordInspector.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

10
ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs

@ -70,6 +70,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -70,6 +70,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return resolver.Resolve (node, cancellationToken);
}
public CSharpResolver GetResolverStateBefore(AstNode node)
{
return resolver.GetResolverStateBefore (node, cancellationToken);
}
public CSharpResolver GetResolverStateAfter(AstNode node)
{
return resolver.GetResolverStateAfter (node, cancellationToken);
}
public IType ResolveType (AstType type)
{
return resolver.Resolve (type, cancellationToken).Type;

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

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
//
// ConditionalToNullCoalescingInspector.cs
//
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
@ -25,18 +25,42 @@ @@ -25,18 +25,42 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Checks for obj != null ? obj : <expr>
/// Converts to: obj ?? <expr>
/// Checks for "a != null ? a : other"<expr>
/// Converts to: "a ?? other"<expr>
/// </summary>
public class ConditionalToNullCoalescingInspector : IInspector
{
static ConditionalExpression[] Matches;
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")),
},
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")),
},
new AnyNode("other"),
new Backreference("a")
),
};
string title = "Convert to '??' expression";
public string Title {
@ -46,16 +70,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -46,16 +70,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
set {
title = value;
}
}
public ConditionalToNullCoalescingInspector ()
{
Matches = new [] {
new ConditionalExpression (new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.Equality, new AnyNode ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new AnyNode (), BinaryOperatorType.Equality, new NullReferenceExpression ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.InEquality, new AnyNode ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new AnyNode (), BinaryOperatorType.InEquality, new NullReferenceExpression ()), new AnyNode (), new AnyNode ()),
};
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
@ -74,58 +88,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -74,58 +88,21 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
this.inspector = inspector;
}
public override void VisitConditionalExpression (ConditionalExpression conditionalExpression)
public override void VisitConditionalExpression(ConditionalExpression conditionalExpression)
{
foreach (var match in Matches) {
if (match.IsMatch (conditionalExpression) && IsCandidate (conditionalExpression)) {
AddIssue (conditionalExpression,
inspector.Title,
delegate {
using (var script = ctx.StartScript ()) {
var expressions = SortExpressions (conditionalExpression);
var expr = new BinaryOperatorExpression (expressions.Item1.Clone (), BinaryOperatorType.NullCoalescing, expressions.Item2.Clone ());
script.Replace (conditionalExpression, expr);
}
});
}
Match m = pattern.Match(conditionalExpression);
if (m.Success) {
var a = m.Get<Expression>("a").Single();
var other = m.Get<Expression>("other").Single();
AddIssue(conditionalExpression, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
var expr = new BinaryOperatorExpression (a.Clone (), BinaryOperatorType.NullCoalescing, other.Clone ());
script.Replace (conditionalExpression, expr);
}
});
}
base.VisitConditionalExpression (conditionalExpression);
}
}
static bool IsCandidate (ConditionalExpression node)
{
var condition = node.Condition as BinaryOperatorExpression;
var compareNode = condition.Left is NullReferenceExpression ? condition.Right : condition.Left;
if (compareNode.IsMatch (node.TrueExpression)) {
// a == null ? a : other
if (condition.Operator == BinaryOperatorType.Equality)
return false;
// a != null ? a : other
return compareNode.IsMatch (node.TrueExpression);
} else {
// a == null ? other : a
if (condition.Operator == BinaryOperatorType.Equality)
return compareNode.IsMatch (node.FalseExpression);
// a != null ? other : a
return false;
}
}
static Tuple<Expression, Expression> SortExpressions (ConditionalExpression cond)
{
var condition = cond.Condition as BinaryOperatorExpression;
var compareNode = condition.Left is NullReferenceExpression ? condition.Right : condition.Left;
if (compareNode.IsMatch (cond.TrueExpression)) {
// a != null ? a : other
return new Tuple<Expression, Expression> (cond.TrueExpression, cond.FalseExpression);
}
// a == null ? other : a
return new Tuple<Expression, Expression> (cond.FalseExpression, cond.TrueExpression);
}
}
}

7
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/GatherVisitorBase.cs

@ -47,10 +47,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,10 +47,15 @@ namespace ICSharpCode.NRefactory.CSharp
base.VisitChildren (node);
}
protected void AddIssue (AstNode node, string title, System.Action fix)
protected void AddIssue (AstNode node, string title, System.Action fix = null)
{
FoundIssues.Add (new InspectionIssue (title, node.StartLocation, node.EndLocation, fix));
}
protected void AddIssue(TextLocation start, TextLocation end, string title, System.Action fix = null)
{
FoundIssues.Add (new InspectionIssue (title, start, end, fix));
}
}

77
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/NotImplementedExceptionInspector.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
//
// NotImplementedExceptionInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// This inspector just shows that there is a not implemented exception. It doesn't offer a fix.
/// Should only be shown in overview bar, no underlining.
/// </summary>
public class NotImplementedExceptionInspector : IInspector
{
string title = "NotImplemented exception thrown";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly NotImplementedExceptionInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, NotImplementedExceptionInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitThrowStatement(ThrowStatement throwStatement)
{
var result = ctx.Resolve (throwStatement.Expression);
if (result.Type.Equals (ctx.Compilation.FindType (typeof(System.NotImplementedException))))
AddIssue (throwStatement, inspector.Title);
base.VisitThrowStatement(throwStatement);
}
}
}
}

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

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
//
// RedundantInternalInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Finds redundant internal modifiers.
/// </summary>
public class RedundantInternalInspector : IInspector
{
string title = "Remove redundant 'internal' modifier";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly RedundantInternalInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, RedundantInternalInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
if (!(typeDeclaration.Parent is TypeDeclaration)) {
foreach (var token in typeDeclaration.ModifierTokens) {
if (token.Modifier == Modifiers.Internal) {
AddIssue(token, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Remove(token);
}
});
}
}
}
base.VisitTypeDeclaration(typeDeclaration);
}
}
}
}

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

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
//
// RedundantNamespaceUsageInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Finds redundant namespace usages.
/// </summary>
public class RedundantNamespaceUsageInspector : IInspector
{
string title = "Remove redundant namespace usage";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly RedundantNamespaceUsageInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, RedundantNamespaceUsageInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
{
base.VisitMemberReferenceExpression(memberReferenceExpression);
var result = ctx.Resolve(memberReferenceExpression.Target);
if (!(result is NamespaceResolveResult)) {
return;
}
var wholeResult = ctx.Resolve(memberReferenceExpression);
if (!(wholeResult is TypeResolveResult)) {
return;
}
var state = ctx.GetResolverStateBefore(memberReferenceExpression);
var lookupName = state.LookupSimpleNameOrTypeName(memberReferenceExpression.MemberName, new List<IType> (), SimpleNameLookupMode.Expression);
if (lookupName != null && 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));
}
}
);
}
}
}
}
}

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

@ -0,0 +1,142 @@ @@ -0,0 +1,142 @@
//
// RedundantPrivateInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Finds redundant internal modifiers.
/// </summary>
public class RedundantPrivateInspector : IInspector
{
string title = "Remove redundant 'private' modifier";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly RedundantPrivateInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, RedundantPrivateInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
void CheckNode(EntityDeclaration node)
{
foreach (var token in node.ModifierTokens) {
if (token.Modifier == Modifiers.Private) {
AddIssue(token, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Remove(token);
}
});
}
}
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
base.VisitMethodDeclaration(methodDeclaration);
CheckNode(methodDeclaration);
}
public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
{
base.VisitFieldDeclaration(fieldDeclaration);
CheckNode(fieldDeclaration);
}
public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
{
base.VisitPropertyDeclaration(propertyDeclaration);
CheckNode(propertyDeclaration);
}
public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
{
base.VisitIndexerDeclaration(indexerDeclaration);
CheckNode(indexerDeclaration);
}
public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
{
base.VisitEventDeclaration(eventDeclaration);
CheckNode(eventDeclaration);
}
public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
{
base.VisitCustomEventDeclaration(eventDeclaration);
CheckNode(eventDeclaration);
}
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{
base.VisitConstructorDeclaration(constructorDeclaration);
CheckNode(constructorDeclaration);
}
public override void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
{
base.VisitOperatorDeclaration(operatorDeclaration);
CheckNode(operatorDeclaration);
}
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
{
base.VisitFixedFieldDeclaration(fixedFieldDeclaration);
CheckNode(fixedFieldDeclaration);
}
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
if (!(typeDeclaration.Parent is TypeDeclaration)) {
CheckNode(typeDeclaration);
}
base.VisitTypeDeclaration(typeDeclaration);
}
}
}
}

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

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
//
// RedundantThisInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Finds redundant namespace usages.
/// </summary>
public class RedundantThisInspector : IInspector
{
string title = "Remove redundant 'this.'";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly RedundantThisInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, RedundantThisInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
static IMember GetMember(ResolveResult result)
{
if (result is MemberResolveResult) {
return ((MemberResolveResult)result).Member;
}
return null;
}
static IEnumerable<IMember> GetMembers (ResolveResult result)
{
if (result is MemberResolveResult) {
return new IMember[] { ((MemberResolveResult)result).Member };
} else if (result is MethodGroupResolveResult) {
return ((MethodGroupResolveResult)result).Methods;
}
return null;
}
public override void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
{
base.VisitThisReferenceExpression(thisReferenceExpression);
var memberReference = thisReferenceExpression.Parent as MemberReferenceExpression;
if (memberReference == null) {
return;
}
var state = ctx.GetResolverStateAfter(thisReferenceExpression);
var wholeResult = ctx.Resolve(thisReferenceExpression);
var result = state.LookupSimpleNameOrTypeName(memberReference.MemberName, new List<IType> (), SimpleNameLookupMode.Expression);
if (result == null || wholeResult == null) {
return;
}
IMember member = GetMember(wholeResult);
if (member == null) {
return;
}
bool isRedundant;
if (result is MemberResolveResult) {
isRedundant = ((MemberResolveResult)result).Member.Region.Equals(member.Region);
} else if (result is MethodGroupResolveResult) {
isRedundant = ((MethodGroupResolveResult)result).Methods.Any(m => m.Region.Equals(member.Region));
} else {
return;
}
if (isRedundant) {
AddIssue(thisReferenceExpression.StartLocation, memberReference.MemberNameToken.StartLocation, inspector.Title, delegate {
using (var script = ctx.StartScript ()) {
script.Replace(memberReference, new IdentifierExpression (memberReference.MemberName));
}
}
);
}
}
}
}
}

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

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
//
// RedundantUsingInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Finds redundant using declarations.
/// </summary>
public class RedundantUsingInspector : IInspector
{
string title = "Remove redundant using";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly RedundantUsingInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, RedundantUsingInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
{
base.VisitUsingDeclaration(usingDeclaration);
// TODO
// return cSharpResolver.usedScopes
// .OfType<ITypeOrNamespaceReference> ()
// .Any (u => u.ResolveNamespace (ctx).NamespaceName == ns) || additionalNamespaces.Contains (ns);
}
}
}
}

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

@ -0,0 +1,165 @@ @@ -0,0 +1,165 @@
//
// StringIsNullOrEmptyInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Checks for str == null && str == ""
/// Converts to: string.IsNullOrEmpty (str)
/// </summary>
public class StringIsNullOrEmptyInspector : IInspector
{
static readonly Pattern pattern = new Choice {
// 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")),
}
),
// 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")),
}
),
};
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")),
},
BinaryOperatorType.ConditionalAnd,
new Choice {
// str != ""
new BinaryOperatorExpression (new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
// "" != str
new BinaryOperatorExpression (new PrimitiveExpression (""), BinaryOperatorType.InEquality, new Backreference ("str")),
}
),
// 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")),
},
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")),
}
),
};
string title = "Use string.IsNullOrEmpty";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly StringIsNullOrEmptyInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, StringIsNullOrEmptyInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
{
base.VisitBinaryOperatorExpression(binaryOperatorExpression);
Match m = pattern.Match(binaryOperatorExpression);
bool isNegated = false;
if (!m.Success) {
m = negPattern.Match(binaryOperatorExpression);
isNegated = true;
}
if (m.Success) {
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());
if (isNegated)
expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr);
script.Replace(binaryOperatorExpression, expr);
}
});
return;
}
}
}
}
}

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

@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
//
// UseVarKeywordInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// 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;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Checks for places where the 'var' keyword can be used. Note that the action is actually done with a context
/// action.
/// </summary>
public class UseVarKeywordInspector : IInspector
{
string title = "Use 'var' keyword";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly UseVarKeywordInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, UseVarKeywordInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
{
base.VisitVariableDeclarationStatement(variableDeclarationStatement);
if (variableDeclarationStatement.Type is PrimitiveType) {
return;
}
if (variableDeclarationStatement.Type is SimpleType && ((SimpleType)variableDeclarationStatement.Type).Identifier == "var") {
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 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;
}
return;
}
AddIssue(variableDeclarationStatement.Type, inspector.Title);
}
}
}
}
Loading…
Cancel
Save