|
|
@ -1,39 +1,53 @@ |
|
|
|
/* |
|
|
|
// <file>
|
|
|
|
* Created by SharpDevelop. |
|
|
|
// <copyright see="prj:///doc/copyright.txt"/>
|
|
|
|
* User: HP |
|
|
|
// <license see="prj:///doc/license.txt"/>
|
|
|
|
* Date: 01.05.2008 |
|
|
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
|
|
|
* Time: 20:37 |
|
|
|
// <version>$Revision$</version>
|
|
|
|
*/ |
|
|
|
// </file>
|
|
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
|
|
|
|
using ICSharpCode.Core; |
|
|
|
using ICSharpCode.Core; |
|
|
|
using ICSharpCode.NRefactory; |
|
|
|
using ICSharpCode.NRefactory; |
|
|
|
using ICSharpCode.NRefactory.Ast; |
|
|
|
using ICSharpCode.NRefactory.Ast; |
|
|
|
|
|
|
|
using ICSharpCode.NRefactory.PrettyPrinter; |
|
|
|
using ICSharpCode.NRefactory.Visitors; |
|
|
|
using ICSharpCode.NRefactory.Visitors; |
|
|
|
using Dom = ICSharpCode.SharpDevelop.Dom; |
|
|
|
using Dom = ICSharpCode.SharpDevelop.Dom; |
|
|
|
|
|
|
|
|
|
|
|
namespace SharpRefactoring.Visitors |
|
|
|
namespace SharpRefactoring.Visitors |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
public enum ErrorKind { |
|
|
|
/// Description of FindJumpInstructionVisitor.
|
|
|
|
ContainsBreak, |
|
|
|
/// </summary>
|
|
|
|
ContainsContinue, |
|
|
|
|
|
|
|
ContainsGoto, |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public class FindJumpInstructionsVisitor : AbstractAstVisitor |
|
|
|
public class FindJumpInstructionsVisitor : AbstractAstVisitor |
|
|
|
{ |
|
|
|
{ |
|
|
|
MethodDeclaration method; |
|
|
|
MethodDeclaration method; |
|
|
|
|
|
|
|
|
|
|
|
List<LabelStatement> labels; |
|
|
|
List<LabelStatement> labels; |
|
|
|
List<CaseLabel> cases; |
|
|
|
List<CaseLabel> cases; |
|
|
|
bool isOk = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public bool IsOk { |
|
|
|
List<GotoStatement> gotos; |
|
|
|
get { return isOk; } |
|
|
|
List<GotoCaseStatement> gotoCases; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<BreakStatement> breaks; |
|
|
|
|
|
|
|
List<ContinueStatement> continues; |
|
|
|
|
|
|
|
|
|
|
|
public FindJumpInstructionsVisitor(MethodDeclaration method) |
|
|
|
public FindJumpInstructionsVisitor(MethodDeclaration method) |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.method = method; |
|
|
|
this.method = method; |
|
|
|
|
|
|
|
|
|
|
|
this.labels = new List<LabelStatement>(); |
|
|
|
this.labels = new List<LabelStatement>(); |
|
|
|
this.cases = new List<CaseLabel>(); |
|
|
|
this.cases = new List<CaseLabel>(); |
|
|
|
|
|
|
|
this.gotoCases = new List<GotoCaseStatement>(); |
|
|
|
|
|
|
|
this.gotos = new List<GotoStatement>(); |
|
|
|
|
|
|
|
this.breaks = new List<BreakStatement>(); |
|
|
|
|
|
|
|
this.continues = new List<ContinueStatement>(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) |
|
|
|
public override object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) |
|
|
@ -63,19 +77,15 @@ namespace SharpRefactoring.Visitors |
|
|
|
|
|
|
|
|
|
|
|
public override object VisitBreakStatement(BreakStatement breakStatement, object data) |
|
|
|
public override object VisitBreakStatement(BreakStatement breakStatement, object data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!(data is bool)) { |
|
|
|
if (!(data is bool)) |
|
|
|
this.isOk = false; |
|
|
|
this.breaks.Add(breakStatement); |
|
|
|
MessageService.ShowError("Selection contains a 'break' statement without the enclosing loop."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return base.VisitBreakStatement(breakStatement, data); |
|
|
|
return base.VisitBreakStatement(breakStatement, data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override object VisitContinueStatement(ContinueStatement continueStatement, object data) |
|
|
|
public override object VisitContinueStatement(ContinueStatement continueStatement, object data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!(data is bool)) { |
|
|
|
if (!(data is bool)) |
|
|
|
this.isOk = false; |
|
|
|
this.continues.Add(continueStatement); |
|
|
|
MessageService.ShowError("Selection contains a 'continue' statement without the enclosing loop."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return base.VisitContinueStatement(continueStatement, data); |
|
|
|
return base.VisitContinueStatement(continueStatement, data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -93,30 +103,54 @@ namespace SharpRefactoring.Visitors |
|
|
|
|
|
|
|
|
|
|
|
public override object VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, object data) |
|
|
|
public override object VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, object data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.isOk = false; |
|
|
|
gotoCases.Add(gotoCaseStatement); |
|
|
|
foreach (CaseLabel label in this.cases) { |
|
|
|
|
|
|
|
if (label.Label.ToString() == gotoCaseStatement.Expression.ToString()) |
|
|
|
|
|
|
|
this.isOk = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!this.isOk) { |
|
|
|
|
|
|
|
MessageService.ShowError("Case section '" + ((PrimitiveExpression)gotoCaseStatement.Expression).StringValue + "' not found inside the selected range!"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return base.VisitGotoCaseStatement(gotoCaseStatement, data); |
|
|
|
return base.VisitGotoCaseStatement(gotoCaseStatement, data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override object VisitGotoStatement(GotoStatement gotoStatement, object data) |
|
|
|
public override object VisitGotoStatement(GotoStatement gotoStatement, object data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.isOk = false; |
|
|
|
gotos.Add(gotoStatement); |
|
|
|
foreach (LabelStatement label in this.labels) { |
|
|
|
return base.VisitGotoStatement(gotoStatement, data); |
|
|
|
if (label.Label == gotoStatement.Label) |
|
|
|
} |
|
|
|
this.isOk = true; |
|
|
|
|
|
|
|
|
|
|
|
public ErrorKind DoCheck() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (this.breaks.Any()) |
|
|
|
|
|
|
|
return ErrorKind.ContainsBreak; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.continues.Any()) |
|
|
|
|
|
|
|
return ErrorKind.ContainsContinue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.gotos.Any()) { |
|
|
|
|
|
|
|
foreach (GotoStatement stmt in this.gotos) { |
|
|
|
|
|
|
|
if (!this.labels.Any(label => label.Label == stmt.Label)) |
|
|
|
|
|
|
|
return ErrorKind.ContainsGoto; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (!this.isOk) { |
|
|
|
|
|
|
|
MessageService.ShowError("Label '" + gotoStatement.Label + "' not found inside the selected range!"); |
|
|
|
if (this.gotoCases.Any()) { |
|
|
|
|
|
|
|
foreach (GotoCaseStatement stmt in this.gotoCases) { |
|
|
|
|
|
|
|
if (!this.cases.Any(@case => CompareCase(@case, stmt))) |
|
|
|
|
|
|
|
return ErrorKind.ContainsGoto; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return base.VisitGotoStatement(gotoStatement, data); |
|
|
|
return ErrorKind.None; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CompareCase(CaseLabel label, GotoCaseStatement stmt) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (label.IsDefault && stmt.IsDefaultCase) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (stmt.Expression is PrimitiveExpression && label.Label is PrimitiveExpression) { |
|
|
|
|
|
|
|
PrimitiveExpression e1 = stmt.Expression as PrimitiveExpression; |
|
|
|
|
|
|
|
PrimitiveExpression e2 = label.Label as PrimitiveExpression; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return object.Equals(e1.Value, e2.Value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|