Browse Source

[CodeIssues] Add helper FindReferences(AstNode, IVariable) to BaseRefactoringContext.

Simon Lindgren 14 years ago
parent
commit
6c2336b582
  1. 1
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 10
      ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
  3. 18
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/AccessToClosureIssues/AccessToClosureIssue.cs
  4. 36
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ForControlVariableNotModifiedIssue.cs
  5. 53
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs
  6. 30
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/LocalVariableNotUsedIssue.cs
  7. 20
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/ParameterNotUsedIssue.cs
  8. 54
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/VariableNotUsedIssue.cs
  9. 4
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/LocalVariableOnlyAssignedIssue.cs
  10. 26
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/ParameterOnlyAssignedIssue.cs
  11. 57
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/VariableOnlyAssignedIssue.cs
  12. 49
      ICSharpCode.NRefactory.CSharp/Refactoring/LocalReferenceFinder.cs

1
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -324,7 +324,6 @@ @@ -324,7 +324,6 @@
<Compile Include="Refactoring\CodeIssues\VariableNotUsedIssues\LocalVariableNotUsedIssue.cs" />
<Compile Include="Refactoring\CodeIssues\VariableNotUsedIssues\ParameterNotUsedIssue.cs" />
<Compile Include="Refactoring\CodeIssues\TypeParameterNotUsedIssue.cs" />
<Compile Include="Refactoring\CodeIssues\VariableNotUsedIssues\VariableNotUsedIssue.cs" />
<Compile Include="Refactoring\CodeIssues\VariableOnlyAssignedIssues\ParameterOnlyAssignedIssue.cs" />
<Compile Include="Refactoring\CodeIssues\VariableOnlyAssignedIssues\VariableOnlyAssignedIssue.cs" />
<Compile Include="Refactoring\DocumentScript.cs" />

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

@ -36,6 +36,7 @@ using ICSharpCode.NRefactory.Editor; @@ -36,6 +36,7 @@ using ICSharpCode.NRefactory.Editor;
using System.ComponentModel.Design;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.Utils;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -87,6 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -87,6 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
this.resolver = resolver;
this.cancellationToken = cancellationToken;
this.referenceFinder = new LocalReferenceFinder(resolver);
}
@ -161,6 +163,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -161,6 +163,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
return new CompositeFormatStringParser().Parse(source);
}
LocalReferenceFinder referenceFinder;
public IList<ReferenceResult> FindReferences(AstNode rootNode, IVariable variable)
{
return referenceFinder.FindReferences(rootNode, variable);
}
#endregion
/// <summary>

18
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/AccessToClosureIssues/AccessToClosureIssue.cs

@ -27,7 +27,6 @@ @@ -27,7 +27,6 @@
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
@ -82,7 +81,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -82,7 +81,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
: base (context)
{
this.title = context.TranslateString (issueProvider.Title);
this.referenceFinder = new LocalReferenceFinder(context);
this.issueProvider = issueProvider;
}
@ -122,24 +120,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -122,24 +120,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
base.VisitParameterDeclaration (parameterDeclaration);
}
LocalReferenceFinder referenceFinder;
void FindLocalReferences (AstNode rootNode, IVariable variable, FoundReferenceCallback callback)
void CheckVariable(IVariable variable, Statement env)
{
referenceFinder.FindReferences(rootNode, variable, callback);
}
void CheckVariable (IVariable variable, Statement env)
{
if (!issueProvider.IsTargetVariable (variable))
if (!issueProvider.IsTargetVariable(variable))
return;
var root = new Environment (env, env);
var envLookup = new Dictionary<AstNode, Environment> ();
envLookup [env] = root;
FindLocalReferences (env, variable, (astNode, resolveResult) =>
AddNode (envLookup, new Node (astNode, issueProvider.GetNodeKind (astNode))));
foreach (var result in ctx.FindReferences(env, variable)) {
AddNode(envLookup, new Node(result.Node, issueProvider.GetNodeKind(result.Node)));
}
root.SortChildren ();
CollectIssues (root, variable.Name);

36
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ForControlVariableNotModifiedIssue.cs

@ -45,12 +45,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -45,12 +45,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
LocalReferenceFinder referenceFinder;
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
this.referenceFinder = new LocalReferenceFinder(ctx);
}
static VariableInitializer GetControlVariable(VariableDeclarationStatement variableDecl,
@ -105,25 +102,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -105,25 +102,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (localResolveResult == null)
return;
var results = ctx.FindReferences (forStatement, localResolveResult.Variable);
var modified = false;
referenceFinder.FindReferences (forStatement, localResolveResult.Variable,
(node, resolveResult) =>
{
if (modified)
return;
var unary = node.Parent as UnaryOperatorExpression;
if (unary != null && unary.Expression == node) {
modified = unary.Operator == UnaryOperatorType.Decrement ||
unary.Operator == UnaryOperatorType.PostDecrement ||
unary.Operator == UnaryOperatorType.Increment ||
unary.Operator == UnaryOperatorType.PostIncrement;
return;
}
foreach (var result in results) {
if (modified)
break;
var node = result.Node;
var unary = node.Parent as UnaryOperatorExpression;
if (unary != null && unary.Expression == node) {
modified = unary.Operator == UnaryOperatorType.Decrement ||
unary.Operator == UnaryOperatorType.PostDecrement ||
unary.Operator == UnaryOperatorType.Increment ||
unary.Operator == UnaryOperatorType.PostIncrement;
continue;
}
var assignment = node.Parent as AssignmentExpression;
modified = assignment != null && assignment.Left == node;
});
var assignment = node.Parent as AssignmentExpression;
modified = assignment != null && assignment.Left == node;
}
if (!modified)
AddIssue (controlVariable.NameToken,

53
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantAssignmentIssue.cs

@ -26,7 +26,6 @@ @@ -26,7 +26,6 @@
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
@ -48,12 +47,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -48,12 +47,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
LocalReferenceFinder referenceFinder;
public GatherVisitor (BaseRefactoringContext ctx, SyntaxTree unit)
: base (ctx)
{
referenceFinder = new LocalReferenceFinder(ctx);
}
public override void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration)
@ -91,30 +87,35 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -91,30 +87,35 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var references = new HashSet<AstNode> ();
var refStatements = new HashSet<Statement> ();
var usedInLambda = false;
referenceFinder.FindReferences (rootStatement, resolveResult.Variable, (astNode, rr) => {
if (usedInLambda || astNode == variableDecl)
return;
var parent = astNode.Parent;
while (!(parent == null || parent is Statement || parent is LambdaExpression))
parent = parent.Parent;
if (parent == null)
return;
var statement = parent as Statement;
if (statement != null) {
references.Add (astNode);
refStatements.Add (statement);
}
var results = ctx.FindReferences (rootStatement, resolveResult.Variable);
foreach (var result in results) {
var node = result.Node;
if (node == variableDecl)
continue;
var parent = node.Parent;
while (!(parent == null || parent is Statement || parent is LambdaExpression))
parent = parent.Parent;
if (parent == null)
continue;
var statement = parent as Statement;
if (statement != null) {
references.Add (node);
refStatements.Add (statement);
}
while (parent != null && parent != rootStatement) {
if (parent is LambdaExpression || parent is AnonymousMethodExpression) {
usedInLambda = true;
break;
}
parent = parent.Parent;
while (parent != null && parent != rootStatement) {
if (parent is LambdaExpression || parent is AnonymousMethodExpression) {
usedInLambda = true;
break;
}
});
parent = parent.Parent;
}
if (usedInLambda) {
break;
}
}
// stop analyzing if the variable is used in any lambda expression or anonymous method
if (usedInLambda)

30
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/LocalVariableNotUsedIssue.cs

@ -25,6 +25,8 @@ @@ -25,6 +25,8 @@
// THE SOFTWARE.
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -33,24 +35,22 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -33,24 +35,22 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Category = IssueCategories.Redundancies,
Severity = Severity.Warning,
IssueMarker = IssueMarker.GrayOut)]
public class LocalVariableNotUsedIssue : VariableNotUsedIssue
public class LocalVariableNotUsedIssue : ICodeIssueProvider
{
internal override GatherVisitorBase GetGatherVisitor (BaseRefactoringContext context)
#region ICodeIssueProvider implementation
public System.Collections.Generic.IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor (context, this);
return new GatherVisitor (context).GetIssues ();
}
#endregion
class GatherVisitor : GatherVisitorBase
{
LocalReferenceFinder referenceFinder;
VariableNotUsedIssue inspector;
public GatherVisitor (BaseRefactoringContext ctx, VariableNotUsedIssue inspector)
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
this.inspector = inspector;
this.referenceFinder = new LocalReferenceFinder(ctx);
}
public override void VisitVariableInitializer (VariableInitializer variableInitializer)
@ -68,8 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -68,8 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult == null)
return;
var b = inspector.FindUsage(referenceFinder, decl.Parent, resolveResult.Variable, variableInitializer);
if (b)
if (IsUsed (decl.Parent, resolveResult.Variable, variableInitializer))
return;
AddIssue (variableInitializer.NameToken, ctx.TranslateString ("Remove unused local variable"),
@ -94,11 +93,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -94,11 +93,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult == null)
return;
if (inspector.FindUsage (referenceFinder, foreachStatement, resolveResult.Variable, foreachStatement.VariableNameToken))
if (IsUsed (foreachStatement, resolveResult.Variable, foreachStatement.VariableNameToken))
return;
AddIssue (foreachStatement.VariableNameToken, ctx.TranslateString ("Local variable is never used"));
}
bool IsUsed(AstNode rootNode, IVariable variable, AstNode variableNode)
{
return ctx.FindReferences(rootNode, variable).Any(result => result.Node != variableNode);
}
}
}

20
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/ParameterNotUsedIssue.cs

@ -27,6 +27,7 @@ @@ -27,6 +27,7 @@
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -35,25 +36,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -35,25 +36,20 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Category = IssueCategories.Redundancies,
Severity = Severity.Warning,
IssueMarker = IssueMarker.GrayOut)]
public class ParameterNotUsedIssue : VariableNotUsedIssue
public class ParameterNotUsedIssue : ICodeIssueProvider
{
internal override GatherVisitorBase GetGatherVisitor (BaseRefactoringContext context)
#region ICodeIssueProvider implementation
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor (context, this);
return new GatherVisitor (context).GetIssues ();
}
#endregion
class GatherVisitor : GatherVisitorBase
{
VariableNotUsedIssue inspector;
LocalReferenceFinder referenceFinder;
public GatherVisitor (BaseRefactoringContext ctx, VariableNotUsedIssue inspector)
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
this.inspector = inspector;
this.referenceFinder = new LocalReferenceFinder(ctx);
}
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
@ -85,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -85,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult == null)
return;
if (inspector.FindUsage (referenceFinder, parameterDeclaration.Parent, resolveResult.Variable, parameterDeclaration))
if (ctx.FindReferences (parameterDeclaration.Parent, resolveResult.Variable).Any(r => r.Node != parameterDeclaration))
return;
AddIssue (parameterDeclaration.NameToken, ctx.TranslateString ("Parameter is never used"));

54
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/VariableNotUsedIssue.cs

@ -1,54 +0,0 @@ @@ -1,54 +0,0 @@
//
// VariableNotUsedIssue.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.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.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public abstract class VariableNotUsedIssue : ICodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context)
{
var unit = context.RootNode as SyntaxTree;
if (unit == null)
return Enumerable.Empty<CodeIssue> ();
return GetGatherVisitor(context).GetIssues ();
}
public bool FindUsage (LocalReferenceFinder referenceFinder, AstNode rootNode, IVariable variable, AstNode declaration)
{
var found = false;
referenceFinder.FindReferences (rootNode, variable, (node, resolveResult) => {
found |= node != declaration;
});
return found;
}
internal abstract GatherVisitorBase GetGatherVisitor (BaseRefactoringContext context);
}
}

4
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/LocalVariableOnlyAssignedIssue.cs

@ -43,11 +43,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -43,11 +43,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
class GatherVisitor : GatherVisitorBase
{
LocalReferenceFinder referenceFinder;
public GatherVisitor (BaseRefactoringContext ctx)
: base (ctx)
{
referenceFinder = new LocalReferenceFinder(ctx);
}
public override void VisitVariableInitializer (VariableInitializer variableInitializer)
@ -61,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -61,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var resolveResult = ctx.Resolve (variableInitializer) as LocalResolveResult;
if (resolveResult == null)
return;
if (!TestOnlyAssigned (referenceFinder, decl.Parent, resolveResult.Variable))
if (!TestOnlyAssigned (ctx, decl.Parent, resolveResult.Variable))
return;
AddIssue (variableInitializer.NameToken,
ctx.TranslateString ("Local variable is assigned by its value is never used"));

26
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/ParameterOnlyAssignedIssue.cs

@ -23,7 +23,6 @@ @@ -23,7 +23,6 @@
// 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 ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
@ -35,32 +34,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -35,32 +34,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IssueMarker = IssueMarker.Underline)]
public class ParameterOnlyAssignedIssue : VariableOnlyAssignedIssue
{
internal override GatherVisitorBase GetGatherVisitor (BaseRefactoringContext ctx)
internal override GatherVisitorBase GetGatherVisitor(BaseRefactoringContext ctx)
{
return new GatherVisitor (ctx);
return new GatherVisitor(ctx);
}
private class GatherVisitor : GatherVisitorBase
{
LocalReferenceFinder referenceFinder;
public GatherVisitor (BaseRefactoringContext ctx)
public GatherVisitor(BaseRefactoringContext ctx)
: base (ctx)
{
referenceFinder = new LocalReferenceFinder(ctx);
}
public override void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration)
public override void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
{
base.VisitParameterDeclaration (parameterDeclaration);
base.VisitParameterDeclaration(parameterDeclaration);
var resolveResult = ctx.Resolve (parameterDeclaration) as LocalResolveResult;
var resolveResult = ctx.Resolve(parameterDeclaration) as LocalResolveResult;
if (resolveResult == null)
return;
if (parameterDeclaration.ParameterModifier == ParameterModifier.Out || parameterDeclaration.ParameterModifier == ParameterModifier.Ref
|| !TestOnlyAssigned (referenceFinder, parameterDeclaration.Parent, resolveResult.Variable))
var parameterModifier = parameterDeclaration.ParameterModifier;
if (parameterModifier == ParameterModifier.Out || parameterModifier == ParameterModifier.Ref ||
!TestOnlyAssigned(ctx, parameterDeclaration.Parent, resolveResult.Variable)) {
return;
AddIssue (parameterDeclaration.NameToken,
ctx.TranslateString ("Parameter is assigned by its value is never used"));
}
AddIssue(parameterDeclaration.NameToken,
ctx.TranslateString("Parameter is assigned by its value is never used"));
}
}
}

57
ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableOnlyAssignedIssues/VariableOnlyAssignedIssue.cs

@ -36,46 +36,47 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -36,46 +36,47 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return GetGatherVisitor (context).GetIssues ();
}
protected static bool TestOnlyAssigned (LocalReferenceFinder referenceFinder, AstNode rootNode, IVariable variable)
protected static bool TestOnlyAssigned(BaseRefactoringContext ctx, AstNode rootNode, IVariable variable)
{
var assignment = false;
var nonAssignment = false;
referenceFinder.FindReferences (rootNode, variable, (node, resolveResult) => {
if (node is ParameterDeclaration)
return;
foreach (var result in ctx.FindReferences(rootNode, variable)) {
var node = result.Node;
if (node is ParameterDeclaration)
continue;
if (node is VariableInitializer) {
if (!(node as VariableInitializer).Initializer.IsNull)
assignment = true;
return;
}
if (node is VariableInitializer) {
if (!(node as VariableInitializer).Initializer.IsNull)
assignment = true;
continue;
}
if (node is IdentifierExpression) {
var parent = node.Parent;
if (parent is AssignmentExpression) {
if (((AssignmentExpression)parent).Left == node) {
assignment = true;
return;
}
} else if (parent is UnaryOperatorExpression) {
var op = ((UnaryOperatorExpression)parent).Operator;
switch (op) {
if (node is IdentifierExpression) {
var parent = node.Parent;
if (parent is AssignmentExpression) {
if (((AssignmentExpression)parent).Left == node) {
assignment = true;
continue;
}
} else if (parent is UnaryOperatorExpression) {
var op = ((UnaryOperatorExpression)parent).Operator;
switch (op) {
case UnaryOperatorType.Increment:
case UnaryOperatorType.PostIncrement:
case UnaryOperatorType.Decrement:
case UnaryOperatorType.PostDecrement:
assignment = true;
return;
}
} else if (parent is DirectionExpression) {
if (((DirectionExpression)parent).FieldDirection == FieldDirection.Out) {
assignment = true;
return;
}
continue;
}
} else if (parent is DirectionExpression) {
if (((DirectionExpression)parent).FieldDirection == FieldDirection.Out) {
assignment = true;
continue;
}
}
nonAssignment = true;
});
}
nonAssignment = true;
}
return assignment && !nonAssignment;
}

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

@ -29,7 +29,6 @@ using System.Linq; @@ -29,7 +29,6 @@ using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System;
using ICSharpCode.NRefactory.Utils;
using System.Diagnostics;
@ -48,7 +47,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -48,7 +47,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
LocalReferenceLocator locator;
MultiDictionary<IVariable, Tuple<AstNode, LocalResolveResult>> references = new MultiDictionary<IVariable, Tuple<AstNode, LocalResolveResult>>();
MultiDictionary<IVariable, ReferenceResult> references = new MultiDictionary<IVariable, ReferenceResult>();
HashSet<AstNode> visitedRoots = new HashSet<AstNode>();
public LocalReferenceFinder(CSharpAstResolver resolver)
{
@ -59,8 +60,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -59,8 +60,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
}
HashSet<AstNode> visitedRoots = new HashSet<AstNode>();
void VisitIfNeccessary(AstNode rootNode)
{
// If any of the parent nodes are recorded as visited,
@ -72,8 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -72,8 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
tmpRoot = tmpRoot.Parent;
}
rootNode.AcceptVisitor(locator);
visitedRoots.Add(rootNode);
locator.ProccessRoot (rootNode);
}
/// <summary>
@ -93,15 +91,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -93,15 +91,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
/// searches, which references outside of <paramref name="rootNode"/> are
/// or are not reported is undefined.
/// </remarks>
public void FindReferences (AstNode rootNode, IVariable variable, FoundReferenceCallback action)
public IList<ReferenceResult> FindReferences(AstNode rootNode, IVariable variable)
{
VisitIfNeccessary(rootNode);
var lookup = (ILookup<IVariable, Tuple<AstNode, LocalResolveResult>>)references;
if (!lookup.Contains(variable))
return;
var iList = references[variable];
foreach (var reference in iList) {
action(reference.Item1, reference.Item2);
lock (locator) {
VisitIfNeccessary(rootNode);
var lookup = (ILookup<IVariable, ReferenceResult>)references;
if (!lookup.Contains(variable))
return new List<ReferenceResult>();
// Clone the list for thread safety
return references[variable].ToList();
}
}
@ -119,11 +117,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -119,11 +117,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
IList<IVariable> processedVariables = new List<IVariable>();
public void ProccessRoot (AstNode rootNode)
{
rootNode.AcceptVisitor(this);
referenceFinder.visitedRoots.Add(rootNode);
}
protected override void VisitChildren(AstNode node)
{
if (referenceFinder.visitedRoots.Contains(node))
return;
var localResolveResult = resolver.Resolve(node) as LocalResolveResult;
if (localResolveResult != null && !processedVariables.Contains(localResolveResult.Variable)) {
referenceFinder.references.Add(localResolveResult.Variable, Tuple.Create(node, localResolveResult));
referenceFinder.references.Add(localResolveResult.Variable, new ReferenceResult(node, localResolveResult));
processedVariables.Add(localResolveResult.Variable);
base.VisitChildren(node);
@ -135,4 +141,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -135,4 +141,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
}
}
public class ReferenceResult
{
public ReferenceResult (AstNode node, LocalResolveResult resolveResult)
{
Node = node;
ResolveResult = resolveResult;
}
public AstNode Node { get; private set; }
public LocalResolveResult ResolveResult { get; private set; }
}
}

Loading…
Cancel
Save