~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/NRefactory/Project/Src/Visitors/CSharpConstructsConvertVisitor.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// <file>
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>
6
 
// </file>
7
 
 
8
 
using System;
9
 
using ICSharpCode.OldNRefactory.Ast;
10
 
 
11
 
namespace ICSharpCode.OldNRefactory.Visitors
12
 
{
13
 
        /// <summary>
14
 
        /// Converts special C# constructs to use more general AST classes.
15
 
        /// </summary>
16
 
        public class CSharpConstructsConvertVisitor : ConvertVisitorBase
17
 
        {
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
26
 
                
27
 
                public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
28
 
                {
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;
34
 
                                }
35
 
                                if (IsNullLiteralExpression(binaryOperatorExpression.Right)) {
36
 
                                        if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) {
37
 
                                                binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality;
38
 
                                        } else {
39
 
                                                binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality;
40
 
                                        }
41
 
                                }
42
 
                        }
43
 
                        return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
44
 
                }
45
 
                
46
 
                static bool IsNullLiteralExpression(Expression expr)
47
 
                {
48
 
                        PrimitiveExpression pe = expr as PrimitiveExpression;
49
 
                        if (pe == null) return false;
50
 
                        return pe.Value == null;
51
 
                }
52
 
                
53
 
                
54
 
                public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
55
 
                {
56
 
                        UnaryOperatorExpression uoe = expressionStatement.Expression as UnaryOperatorExpression;
57
 
                        if (uoe != null) {
58
 
                                switch (uoe.Op) {
59
 
                                        case UnaryOperatorType.Increment:
60
 
                                        case UnaryOperatorType.PostIncrement:
61
 
                                                expressionStatement.Expression = new AssignmentExpression(uoe.Expression, AssignmentOperatorType.Add, new PrimitiveExpression(1, "1"));
62
 
                                                break;
63
 
                                        case UnaryOperatorType.Decrement:
64
 
                                        case UnaryOperatorType.PostDecrement:
65
 
                                                expressionStatement.Expression = new AssignmentExpression(uoe.Expression, AssignmentOperatorType.Subtract, new PrimitiveExpression(1, "1"));
66
 
                                                break;
67
 
                                }
68
 
                        }
69
 
                        return base.VisitExpressionStatement(expressionStatement, data);
70
 
                }
71
 
                
72
 
                public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
73
 
                {
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;
78
 
                        }
79
 
                        if (ifElseStatement.ElseIfSections.Count == 0
80
 
                            && ifElseStatement.FalseStatement.Count == 0
81
 
                            && ifElseStatement.TrueStatement.Count == 1
82
 
                            && boe != null
83
 
                            && boe.Op == BinaryOperatorType.InEquality
84
 
                            && (IsNullLiteralExpression(boe.Left) || IsNullLiteralExpression(boe.Right))
85
 
                           )
86
 
                        {
87
 
                                string ident = GetPossibleEventName(boe.Left) ?? GetPossibleEventName(boe.Right);
88
 
                                ExpressionStatement se = ifElseStatement.TrueStatement[0] as ExpressionStatement;
89
 
                                if (se == null) {
90
 
                                        BlockStatement block = ifElseStatement.TrueStatement[0] as BlockStatement;
91
 
                                        if (block != null && block.Children.Count == 1) {
92
 
                                                se = block.Children[0] as ExpressionStatement;
93
 
                                        }
94
 
                                }
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));
99
 
                                        }
100
 
                                }
101
 
                        }
102
 
                        return base.VisitIfElseStatement(ifElseStatement, data);
103
 
                }
104
 
                
105
 
                string GetPossibleEventName(Expression expression)
106
 
                {
107
 
                        IdentifierExpression ident = expression as IdentifierExpression;
108
 
                        if (ident != null)
109
 
                                return ident.Identifier;
110
 
                        MemberReferenceExpression fre = expression as MemberReferenceExpression;
111
 
                        if (fre != null && fre.TargetObject is ThisReferenceExpression)
112
 
                                return fre.MemberName;
113
 
                        return null;
114
 
                }
115
 
                
116
 
                public override object VisitForStatement(ForStatement forStatement, object data)
117
 
                {
118
 
                        base.VisitForStatement(forStatement, data);
119
 
                        ConvertForStatement(forStatement);
120
 
                        return null;
121
 
                }
122
 
                
123
 
                void ConvertForStatement(ForStatement forStatement)
124
 
                {
125
 
                        //   ForStatement -> ForNextStatement when for-loop is simple
126
 
                        
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)
136
 
                        
137
 
                        // check if the form is valid and collect TypeReference, name, start, end and step
138
 
                        if (forStatement.Initializers.Count != 1)
139
 
                                return;
140
 
                        if (forStatement.Iterator.Count != 1)
141
 
                                return;
142
 
                        ExpressionStatement statement = forStatement.Iterator[0] as ExpressionStatement;
143
 
                        if (statement == null)
144
 
                                return;
145
 
                        AssignmentExpression iterator = statement.Expression as AssignmentExpression;
146
 
                        if (iterator == null || (iterator.Op != AssignmentOperatorType.Add && iterator.Op != AssignmentOperatorType.Subtract))
147
 
                                return;
148
 
                        IdentifierExpression iteratorIdentifier = iterator.Left as IdentifierExpression;
149
 
                        if (iteratorIdentifier == null)
150
 
                                return;
151
 
                        PrimitiveExpression stepExpression = iterator.Right as PrimitiveExpression;
152
 
                        if (stepExpression == null || !(stepExpression.Value is int))
153
 
                                return;
154
 
                        int step = (int)stepExpression.Value;
155
 
                        if (iterator.Op == AssignmentOperatorType.Subtract)
156
 
                                step = -step;
157
 
                        
158
 
                        BinaryOperatorExpression condition = forStatement.Condition as BinaryOperatorExpression;
159
 
                        if (condition == null || !(condition.Left is IdentifierExpression))
160
 
                                return;
161
 
                        if ((condition.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier)
162
 
                                return;
163
 
                        Expression end;
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);
169
 
                                } else {
170
 
                                        return;
171
 
                                }
172
 
                        } else {
173
 
                                if (condition.Op == BinaryOperatorType.LessThanOrEqual) {
174
 
                                        end = condition.Right;
175
 
                                } else if (condition.Op == BinaryOperatorType.LessThan) {
176
 
                                        end = Expression.AddInteger(condition.Right, -1);
177
 
                                } else {
178
 
                                        return;
179
 
                                }
180
 
                        }
181
 
                        
182
 
                        Expression start;
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)
189
 
                                        return;
190
 
                                typeReference = varDecl.GetTypeForVariable(0);
191
 
                                start = varDecl.Variables[0].Initializer;
192
 
                        } else {
193
 
                                statement = forStatement.Initializers[0] as ExpressionStatement;
194
 
                                if (statement == null)
195
 
                                        return;
196
 
                                AssignmentExpression assign = statement.Expression as AssignmentExpression;
197
 
                                if (assign == null || assign.Op != AssignmentOperatorType.Assign)
198
 
                                        return;
199
 
                                if (!(assign.Left is IdentifierExpression))
200
 
                                        return;
201
 
                                if ((assign.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier)
202
 
                                        return;
203
 
                                start = assign.Right;
204
 
                        }
205
 
                        
206
 
                        ReplaceCurrentNode(
207
 
                                new ForNextStatement {
208
 
                                        TypeReference = typeReference,
209
 
                                        VariableName = iteratorIdentifier.Identifier,
210
 
                                        Start = start,
211
 
                                        End = end,
212
 
                                        Step = (step == 1) ? null : new PrimitiveExpression(step, step.ToString(System.Globalization.NumberFormatInfo.InvariantInfo)),
213
 
                                        EmbeddedStatement = forStatement.EmbeddedStatement
214
 
                                });
215
 
                }
216
 
                
217
 
                public override object VisitCastExpression(CastExpression castExpression, object data)
218
 
                {
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
223
 
                                string type;
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;
228
 
                                        }
229
 
                                }
230
 
                        }
231
 
                        return base.VisitCastExpression(castExpression, data);
232
 
                }
233
 
        }
234
 
}