2
// <copyright see="prj:///doc/copyright.txt"/>
3
// <license see="prj:///doc/license.txt"/>
4
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
5
// <version>$Revision: 4482 $</version>
9
using ICSharpCode.OldNRefactory.Ast;
11
namespace ICSharpCode.OldNRefactory.Visitors
14
/// Converts special C# constructs to use more general AST classes.
16
public class CSharpConstructsConvertVisitor : ConvertVisitorBase
18
// The following conversions are implemented:
19
// a == null -> a Is Nothing
20
// a != null -> a Is Not Nothing
21
// i++ / ++i as statement: convert to i += 1
22
// i-- / --i as statement: convert to i -= 1
23
// ForStatement -> ForNextStatement when for-loop is simple
24
// if (Event != null) Event(this, bla); -> RaiseEvent Event(this, bla)
25
// Casts to value types are marked as conversions
27
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
29
if (binaryOperatorExpression.Op == BinaryOperatorType.Equality || binaryOperatorExpression.Op == BinaryOperatorType.InEquality) {
30
if (IsNullLiteralExpression(binaryOperatorExpression.Left)) {
31
Expression tmp = binaryOperatorExpression.Left;
32
binaryOperatorExpression.Left = binaryOperatorExpression.Right;
33
binaryOperatorExpression.Right = tmp;
35
if (IsNullLiteralExpression(binaryOperatorExpression.Right)) {
36
if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) {
37
binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality;
39
binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality;
43
return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
46
static bool IsNullLiteralExpression(Expression expr)
48
PrimitiveExpression pe = expr as PrimitiveExpression;
49
if (pe == null) return false;
50
return pe.Value == null;
54
public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
56
UnaryOperatorExpression uoe = expressionStatement.Expression as UnaryOperatorExpression;
59
case UnaryOperatorType.Increment:
60
case UnaryOperatorType.PostIncrement:
61
expressionStatement.Expression = new AssignmentExpression(uoe.Expression, AssignmentOperatorType.Add, new PrimitiveExpression(1, "1"));
63
case UnaryOperatorType.Decrement:
64
case UnaryOperatorType.PostDecrement:
65
expressionStatement.Expression = new AssignmentExpression(uoe.Expression, AssignmentOperatorType.Subtract, new PrimitiveExpression(1, "1"));
69
return base.VisitExpressionStatement(expressionStatement, data);
72
public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
74
BinaryOperatorExpression boe = ifElseStatement.Condition as BinaryOperatorExpression;
75
// the BinaryOperatorExpression might be inside a ParenthesizedExpression
76
if (boe == null && ifElseStatement.Condition is ParenthesizedExpression) {
77
boe = (ifElseStatement.Condition as ParenthesizedExpression).Expression as BinaryOperatorExpression;
79
if (ifElseStatement.ElseIfSections.Count == 0
80
&& ifElseStatement.FalseStatement.Count == 0
81
&& ifElseStatement.TrueStatement.Count == 1
83
&& boe.Op == BinaryOperatorType.InEquality
84
&& (IsNullLiteralExpression(boe.Left) || IsNullLiteralExpression(boe.Right))
87
string ident = GetPossibleEventName(boe.Left) ?? GetPossibleEventName(boe.Right);
88
ExpressionStatement se = ifElseStatement.TrueStatement[0] as ExpressionStatement;
90
BlockStatement block = ifElseStatement.TrueStatement[0] as BlockStatement;
91
if (block != null && block.Children.Count == 1) {
92
se = block.Children[0] as ExpressionStatement;
95
if (ident != null && se != null) {
96
InvocationExpression ie = se.Expression as InvocationExpression;
97
if (ie != null && GetPossibleEventName(ie.TargetObject) == ident) {
98
ReplaceCurrentNode(new RaiseEventStatement(ident, ie.Arguments));
102
return base.VisitIfElseStatement(ifElseStatement, data);
105
string GetPossibleEventName(Expression expression)
107
IdentifierExpression ident = expression as IdentifierExpression;
109
return ident.Identifier;
110
MemberReferenceExpression fre = expression as MemberReferenceExpression;
111
if (fre != null && fre.TargetObject is ThisReferenceExpression)
112
return fre.MemberName;
116
public override object VisitForStatement(ForStatement forStatement, object data)
118
base.VisitForStatement(forStatement, data);
119
ConvertForStatement(forStatement);
123
void ConvertForStatement(ForStatement forStatement)
125
// ForStatement -> ForNextStatement when for-loop is simple
127
// only the following forms of the for-statement are allowed:
128
// for (TypeReference name = start; name < oneAfterEnd; name += step)
129
// for (name = start; name < oneAfterEnd; name += step)
130
// for (TypeReference name = start; name <= end; name += step)
131
// for (name = start; name <= end; name += step)
132
// for (TypeReference name = start; name > oneAfterEnd; name -= step)
133
// for (name = start; name > oneAfterEnd; name -= step)
134
// for (TypeReference name = start; name >= end; name -= step)
135
// for (name = start; name >= end; name -= step)
137
// check if the form is valid and collect TypeReference, name, start, end and step
138
if (forStatement.Initializers.Count != 1)
140
if (forStatement.Iterator.Count != 1)
142
ExpressionStatement statement = forStatement.Iterator[0] as ExpressionStatement;
143
if (statement == null)
145
AssignmentExpression iterator = statement.Expression as AssignmentExpression;
146
if (iterator == null || (iterator.Op != AssignmentOperatorType.Add && iterator.Op != AssignmentOperatorType.Subtract))
148
IdentifierExpression iteratorIdentifier = iterator.Left as IdentifierExpression;
149
if (iteratorIdentifier == null)
151
PrimitiveExpression stepExpression = iterator.Right as PrimitiveExpression;
152
if (stepExpression == null || !(stepExpression.Value is int))
154
int step = (int)stepExpression.Value;
155
if (iterator.Op == AssignmentOperatorType.Subtract)
158
BinaryOperatorExpression condition = forStatement.Condition as BinaryOperatorExpression;
159
if (condition == null || !(condition.Left is IdentifierExpression))
161
if ((condition.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier)
164
if (iterator.Op == AssignmentOperatorType.Subtract) {
165
if (condition.Op == BinaryOperatorType.GreaterThanOrEqual) {
166
end = condition.Right;
167
} else if (condition.Op == BinaryOperatorType.GreaterThan) {
168
end = Expression.AddInteger(condition.Right, 1);
173
if (condition.Op == BinaryOperatorType.LessThanOrEqual) {
174
end = condition.Right;
175
} else if (condition.Op == BinaryOperatorType.LessThan) {
176
end = Expression.AddInteger(condition.Right, -1);
183
TypeReference typeReference = null;
184
LocalVariableDeclaration varDecl = forStatement.Initializers[0] as LocalVariableDeclaration;
185
if (varDecl != null) {
186
if (varDecl.Variables.Count != 1
187
|| varDecl.Variables[0].Name != iteratorIdentifier.Identifier
188
|| varDecl.Variables[0].Initializer == null)
190
typeReference = varDecl.GetTypeForVariable(0);
191
start = varDecl.Variables[0].Initializer;
193
statement = forStatement.Initializers[0] as ExpressionStatement;
194
if (statement == null)
196
AssignmentExpression assign = statement.Expression as AssignmentExpression;
197
if (assign == null || assign.Op != AssignmentOperatorType.Assign)
199
if (!(assign.Left is IdentifierExpression))
201
if ((assign.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier)
203
start = assign.Right;
207
new ForNextStatement {
208
TypeReference = typeReference,
209
VariableName = iteratorIdentifier.Identifier,
212
Step = (step == 1) ? null : new PrimitiveExpression(step, step.ToString(System.Globalization.NumberFormatInfo.InvariantInfo)),
213
EmbeddedStatement = forStatement.EmbeddedStatement
217
public override object VisitCastExpression(CastExpression castExpression, object data)
219
if (castExpression.CastType == CastType.Cast) {
220
// Casts to value types are marked as conversions
221
// this code only supports primitive types, user-defined value types are handled by
222
// the DOM-aware CSharpToVBNetConvertVisitor
224
if (TypeReference.PrimitiveTypesCSharpReverse.TryGetValue(castExpression.CastTo.Type, out type)) {
225
if (type != "object" && type != "string") {
226
// type is value type
227
castExpression.CastType = CastType.Conversion;
231
return base.VisitCastExpression(castExpression, data);