Browse Source

[CodeActions] Clean up StatementsToInitializerConverter and InitializerPath.

Also, rename InitializerPath to AccessPath.
newNRvisualizers
Simon Lindgren 13 years ago
parent
commit
3cf3032f50
  1. 2
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 85
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs
  3. 100
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs

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

@ -476,7 +476,6 @@ @@ -476,7 +476,6 @@
<Compile Include="Refactoring\NamingHelper.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\ConvertToInitializerAction.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\StatementsToInitializerConverter.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\InitializerPath.cs" />
<Compile Include="Refactoring\CodeActions\MoveToOuterScopeAction.cs" />
<Compile Include="Refactoring\CodeIssues\VariableDeclaredInWideScopeIssue.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\ParameterCanBeDemotedIssue.cs" />
@ -503,6 +502,7 @@ @@ -503,6 +502,7 @@
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\AccessPath.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

85
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/InitializerPath.cs → ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs

@ -32,25 +32,16 @@ using System.Linq; @@ -32,25 +32,16 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
class InitializerPath
class AccessPath
{
InitializerPath(object anchor)
public AccessPath(IVariable target)
{
this.anchor = anchor;
VariableRoot = target;
MemberPath = new List<IMember>();
}
public InitializerPath(IVariable target) : this((object)target)
public static AccessPath FromResolveResult(ResolveResult resolveResult)
{
}
public InitializerPath(IMember target) : this((object)target)
{
}
public static InitializerPath FromResolveResult(ResolveResult resolveResult)
{
InitializerPath initializerPath = null;
var memberPath = new List<IMember>();
var currentResolveResult = resolveResult;
do {
@ -59,42 +50,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -59,42 +50,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
memberPath.Add(memberResolveResult.Member);
currentResolveResult = memberResolveResult.TargetResult;
} else if (currentResolveResult is LocalResolveResult) {
// This is the root variable
var localResolveResult = (LocalResolveResult)currentResolveResult;
memberPath.Reverse();
initializerPath = new InitializerPath(localResolveResult.Variable) {
return new AccessPath(localResolveResult.Variable) {
MemberPath = memberPath
};
break;
} else if (currentResolveResult is ThisResolveResult) {
break;
} else {
// Unsupported path
return null;
}
} while (currentResolveResult != null);
if (initializerPath == null) {
// This path is rooted at a member
memberPath.Reverse();
initializerPath = new InitializerPath(memberPath [0]) {
MemberPath = memberPath.Skip(1).ToList()
};
}
return initializerPath;
memberPath.Reverse();
return new AccessPath(null) {
MemberPath = memberPath
};
}
public InitializerPath GetParentPath()
public AccessPath GetParentPath()
{
if (MemberPath.Count < 1)
throw new InvalidOperationException("Cannot get the parent path of a path that does not contain any members.");
return new InitializerPath(anchor) {
return new AccessPath(VariableRoot) {
MemberPath = MemberPath.Take(MemberPath.Count - 1).ToList()
};
}
public bool IsSubPath(InitializerPath other)
public bool IsSubPath(AccessPath other)
{
if (!other.anchor.Equals(anchor))
if (!object.Equals(other.VariableRoot, VariableRoot))
return false;
if (MemberPath.Count <= other.MemberPath.Count)
return false;
@ -105,22 +92,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -105,22 +92,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return true;
}
object anchor;
public IVariable VariableRoot { get; set; }
public IVariable VariableRoot {
get { return anchor as IVariable; }
}
public IMember MemberRoot {
get { return anchor as IMember; }
public int PartCount {
get {
return MemberPath.Count + (VariableRoot == null ? 0 : 1);
}
}
public string RootName {
get {
if (anchor is IMember)
return (anchor as IMember).Name;
else
return (anchor as IVariable).Name;
if (VariableRoot != null)
return VariableRoot.Name;
return MemberPath.First().Name;
}
}
@ -128,12 +112,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -128,12 +112,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(InitializerPath))
if (obj.GetType() != typeof(AccessPath))
return false;
var other = (InitializerPath)obj;
var other = (AccessPath)obj;
if (!object.Equals(anchor, other.anchor))
if (!object.Equals(VariableRoot, other.VariableRoot))
return false;
if (MemberPath.Count != other.MemberPath.Count)
@ -148,29 +132,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -148,29 +132,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override int GetHashCode()
{
int hash = anchor.GetHashCode();
int hash = VariableRoot != null ? VariableRoot.GetHashCode() : 37;
foreach (var member in MemberPath)
hash ^= member.GetHashCode();
hash ^= 31 * member.GetHashCode();
return hash;
}
public static bool operator==(InitializerPath left, InitializerPath right)
public static bool operator==(AccessPath left, AccessPath right)
{
return object.Equals(left, right);
}
public static bool operator!=(InitializerPath left, InitializerPath right)
public static bool operator!=(AccessPath left, AccessPath right)
{
return !object.Equals(left, right);
}
public override string ToString()
{
if (MemberPath.Count > 0)
return string.Format("[InitializerPath: {0}.{1}]", RootName,
string.Join(".", MemberPath.Select<IMember, string>(member => member.Name)));
else
return string.Format("[InitializerPath: {0}]", RootName);
string memberPathString = string.Join(".", MemberPath.Select<IMember, string>(member => member.Name));
if (VariableRoot == null)
return string.Format("[AccessPath: {0}]", memberPathString);
return string.Format("[AccessPath: {0}.{1}]", VariableRoot.Name, memberPathString);
}
}

100
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs

@ -37,9 +37,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -37,9 +37,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public class StatementsToInitializerConverter
{
IDictionary<InitializerPath, Expression> initializers = new Dictionary<InitializerPath, Expression>();
IDictionary<AccessPath, Expression> accessPaths = new Dictionary<AccessPath, Expression>();
IList<Comment> comments = new List<Comment>();
InitializerPath mainInitializerPath;
AccessPath mainAccessPath;
RefactoringContext context;
public StatementsToInitializerConverter(RefactoringContext context)
@ -50,13 +50,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -50,13 +50,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
void Initialize(AstNode targetNode)
{
var target = context.Resolve(targetNode);
if (target is LocalResolveResult) {
mainInitializerPath = new InitializerPath(((LocalResolveResult)target).Variable);
} else if (target is MemberResolveResult) {
mainInitializerPath = new InitializerPath(((MemberResolveResult)target).Member);
} else {
throw new ArgumentException("variableInitializer must target a variable or a member.");
}
var targetInitializerPath = AccessPath.FromResolveResult(target);
if (targetInitializerPath == null)
throw new ArgumentException(string.Format("Could not create the main initializer path from resolve result ({0})", target));
mainAccessPath = targetInitializerPath;
}
public VariableInitializer ConvertToInitializer(VariableInitializer variableInitializer, ref IList<AstNode> statements)
@ -67,11 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -67,11 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
throw new ArgumentNullException("statements");
Initialize(variableInitializer);
initializers [mainInitializerPath] = variableInitializer.Initializer.Clone();
accessPaths [mainAccessPath] = variableInitializer.Initializer.Clone();
Convert(statements);
statements = ReplacementNodeHelper.GetReplacedNodes(initializers [mainInitializerPath]);
return new VariableInitializer(mainInitializerPath.RootName, initializers [mainInitializerPath]);
statements = ReplacementNodeHelper.GetReplacedNodes(accessPaths [mainAccessPath]);
return new VariableInitializer(mainAccessPath.RootName, accessPaths [mainAccessPath]);
}
public AssignmentExpression ConvertToInitializer(AssignmentExpression assignmentExpression, ref IList<AstNode> statements)
@ -84,11 +82,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -84,11 +82,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
throw new ArgumentException("assignmentExpression.Right must be an ObjectCreateExpression", "assignmentExpression");
Initialize(assignmentExpression.Left);
initializers [mainInitializerPath] = assignmentExpression.Right.Clone();
accessPaths [mainAccessPath] = assignmentExpression.Right.Clone();
Convert(statements);
statements = ReplacementNodeHelper.GetReplacedNodes(initializers [mainInitializerPath]);
return new AssignmentExpression(new IdentifierExpression(mainInitializerPath.RootName), initializers [mainInitializerPath]);
statements = ReplacementNodeHelper.GetReplacedNodes(accessPaths [mainAccessPath]);
return new AssignmentExpression(new IdentifierExpression(mainAccessPath.RootName), accessPaths [mainAccessPath]);
}
void Convert(IList<AstNode> originalStatements)
@ -123,7 +121,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -123,7 +121,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
VariableInitializer variableInitializer;
var variableDeclarationStatement = node as VariableDeclarationStatement;
if (variableDeclarationStatement == null) {
variableInitializer = VariableInitializer.Null;
return false;
}
variableInitializer = variableDeclarationStatement.Variables.FirstOrNullObject();
@ -142,7 +139,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -142,7 +139,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var invocationExpression = expressionStatement.Expression as InvocationExpression;
if (invocationExpression == null)
return false;
var target = invocationExpression.Target;
var invocationResolveResult = context.Resolve(invocationExpression) as InvocationResolveResult;
if (invocationResolveResult == null)
return false;
@ -152,15 +148,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -152,15 +148,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (targetResult is MemberResolveResult)
return false;
ArrayInitializerExpression tuple = new ArrayInitializerExpression();
var tuple = new ArrayInitializerExpression();
foreach (var argument in invocationExpression.Arguments) {
var argumentLocalResolveResult = context.Resolve(argument) as LocalResolveResult;
if (argumentLocalResolveResult != null) {
var initializerPath = InitializerPath.FromResolveResult(argumentLocalResolveResult);
if (initializerPath == null || !initializers.ContainsKey(initializerPath))
var initializerPath = AccessPath.FromResolveResult(argumentLocalResolveResult);
if (initializerPath == null || !accessPaths.ContainsKey(initializerPath))
return false;
// Add a clone, since we do not yet know if this is where the initializer will be used
var initializerClone = initializers[initializerPath].Clone();
var initializerClone = accessPaths[initializerPath].Clone();
tuple.Elements.Add(initializerClone);
} else {
tuple.Elements.Add(argument.Clone());
@ -168,11 +164,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -168,11 +164,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
}
ReplacementNodeHelper.AddReplacementAnnotation(tuple, expressionStatement);
var targetPath = InitializerPath.FromResolveResult(targetResult);
if (targetPath == null || !initializers.ContainsKey(targetPath))
var targetPath = AccessPath.FromResolveResult(targetResult);
if (targetPath == null || !accessPaths.ContainsKey(targetPath))
return false;
InsertImplicitInitializersForPath(targetPath);
var targetInitializer = initializers [targetPath];
var targetInitializer = accessPaths [targetPath];
AddToInitializer(targetInitializer, tuple);
return true;
}
@ -196,29 +192,29 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -196,29 +192,29 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
void AddNewVariable(IVariable variable, Expression initializer, AstNode node)
{
var variablePath = new InitializerPath(variable);
var variablePath = new AccessPath(variable);
var rightResolveResult = context.Resolve(initializer) as LocalResolveResult;
if (rightResolveResult != null) {
var rightPath = InitializerPath.FromResolveResult(rightResolveResult);
if (rightPath != null && initializers.ContainsKey(rightPath)) {
var rightInitializer = initializers [rightPath];
var rightPath = AccessPath.FromResolveResult(rightResolveResult);
if (rightPath != null && accessPaths.ContainsKey(rightPath)) {
var rightInitializer = accessPaths [rightPath];
ReplacementNodeHelper.AddReplacementAnnotation(rightInitializer, node);
initializers.Remove(rightPath);
initializers [variablePath] = rightInitializer;
if (rightPath == mainInitializerPath) {
mainInitializerPath = variablePath;
accessPaths.Remove(rightPath);
accessPaths [variablePath] = rightInitializer;
if (rightPath == mainAccessPath) {
mainAccessPath = variablePath;
}
}
} else {
initializers [variablePath] = ReplacementNodeHelper.CloneWithReplacementAnnotation(initializer, node);
accessPaths [variablePath] = ReplacementNodeHelper.CloneWithReplacementAnnotation(initializer, node);
}
}
void AddOldAnnotationsToInitializer(InitializerPath targetPath, Expression initializer)
void AddOldAnnotationsToInitializer(AccessPath targetPath, IAnnotatable initializer)
{
if (targetPath != null) {
if (initializers.ContainsKey(targetPath)) {
foreach (var astNode in ReplacementNodeHelper.GetAllReplacementAnnotations(initializers[targetPath])) {
if (accessPaths.ContainsKey(targetPath)) {
foreach (var astNode in ReplacementNodeHelper.GetAllReplacementAnnotations(accessPaths[targetPath])) {
initializer.AddAnnotation(astNode);
}
}
@ -231,16 +227,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -231,16 +227,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var leftResolveResult = context.Resolve(left);
Expression initializer;
if (rightResolveResult != null) {
var rightPath = InitializerPath.FromResolveResult(rightResolveResult);
if (initializers.ContainsKey(rightPath)) {
initializer = initializers [rightPath];
var rightPath = AccessPath.FromResolveResult(rightResolveResult);
if (accessPaths.ContainsKey(rightPath)) {
initializer = accessPaths [rightPath];
} else {
initializer = right.Clone();
}
} else {
initializer = right.Clone();
}
var leftPath = InitializerPath.FromResolveResult(leftResolveResult);
var leftPath = AccessPath.FromResolveResult(leftResolveResult);
if (leftPath == null) {
return false;
}
@ -249,15 +245,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -249,15 +245,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// to the same variable/member.
AddOldAnnotationsToInitializer(leftPath, initializer);
if (leftPath.MemberPath.Count == 0) {
if (leftPath.PartCount == 1) {
ReplacementNodeHelper.AddReplacementAnnotation(initializer, node);
initializers [leftPath] = initializer;
accessPaths [leftPath] = initializer;
return true;
}
if (!(leftResolveResult is MemberResolveResult))
return false;
Debug.Assert(leftPath.MemberPath.Count > 0, "No top level assignment should get here.");
Debug.Assert(leftPath.PartCount > 1, "No top level assignment should get here.");
var parentKey = leftPath.GetParentPath();
var member = leftPath.MemberPath.Last();
@ -266,13 +262,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -266,13 +262,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!success)
return false;
var parentInitializer = initializers [parentKey];
var parentInitializer = accessPaths [parentKey];
AddToInitializer(parentInitializer, comments.ToArray());
comments.Clear();
AddToInitializer(parentInitializer, new NamedExpression(member.Name, initializer));
ReplacementNodeHelper.AddReplacementAnnotation(initializer, node);
initializers [leftPath] = initializer;
accessPaths [leftPath] = initializer;
return true;
}
@ -347,8 +343,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -347,8 +343,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var resolveResult = context.Resolve(memberReference) as MemberResolveResult;
if (resolveResult == null)
continue;
var initializerPath = InitializerPath.FromResolveResult(resolveResult);
if (initializerPath != null && initializers.ContainsKey(initializerPath))
var initializerPath = AccessPath.FromResolveResult(resolveResult);
if (initializerPath != null && accessPaths.ContainsKey(initializerPath))
return true;
}
return false;
@ -356,12 +352,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -356,12 +352,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool VariableHasBeenConverted(IVariable variable)
{
return initializers.Any(item => item.Key.VariableRoot.Equals(variable));
return accessPaths.Any(item => item.Key.VariableRoot.Equals(variable));
}
bool InsertImplicitInitializersForPath(InitializerPath path)
bool InsertImplicitInitializersForPath(AccessPath path)
{
if (initializers.ContainsKey(path))
if (accessPaths.ContainsKey(path))
return true;
if (path.MemberPath.Count == 0)
@ -371,11 +367,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -371,11 +367,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!success)
return false;
var parentInitializer = initializers [parentPath];
var parentInitializer = accessPaths [parentPath];
var initializer = new ArrayInitializerExpression();
var namedExpression = new NamedExpression(path.MemberPath [path.MemberPath.Count - 1].Name, initializer);
AddToInitializer(parentInitializer, namedExpression);
initializers [path] = initializer;
accessPaths [path] = initializer;
return true;
}

Loading…
Cancel
Save