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

« back to all changes in this revision

Viewing changes to contrib/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.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: 4570 $</version>
6
 
// </file>
7
 
 
8
 
using System;
9
 
using System.Collections.Generic;
10
 
using ICSharpCode.OldNRefactory.Ast;
11
 
using ICSharpCode.OldNRefactory.AstBuilder;
12
 
using Attribute = ICSharpCode.OldNRefactory.Ast.Attribute;
13
 
 
14
 
namespace ICSharpCode.OldNRefactory.Visitors
15
 
{
16
 
        /// <summary>
17
 
        /// Converts elements not supported by VB to their VB representation.
18
 
        /// Not all elements are converted here, most simple elements (e.g. ConditionalExpression)
19
 
        /// are converted in the output visitor.
20
 
        /// </summary>
21
 
        public class ToVBNetConvertVisitor : ConvertVisitorBase
22
 
        {
23
 
                // The following conversions are implemented:
24
 
                //   Conflicting field/property names -> m_field
25
 
                //   Conflicting variable names inside methods
26
 
                //   Anonymous methods are put into new methods
27
 
                //   Simple event handler creation is replaced with AddressOfExpression
28
 
                //   Move Imports-statements out of namespaces
29
 
                //   Parenthesis around Cast expressions remove - these are syntax errors in VB.NET
30
 
                //   Decrease array creation size - VB specifies upper bound instead of array length
31
 
                //   Automatic properties are converted to explicit implementation
32
 
                
33
 
                List<INode> nodesToMoveToCompilationUnit = new List<INode>();
34
 
                
35
 
                public override object VisitCompilationUnit(CompilationUnit compilationUnit, object data)
36
 
                {
37
 
                        base.VisitCompilationUnit(compilationUnit, data);
38
 
                        for (int i = 0; i < nodesToMoveToCompilationUnit.Count; i++) {
39
 
                                compilationUnit.Children.Insert(i, nodesToMoveToCompilationUnit[i]);
40
 
                                nodesToMoveToCompilationUnit[i].Parent = compilationUnit;
41
 
                        }
42
 
                        return null;
43
 
                }
44
 
                
45
 
                public override object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
46
 
                {
47
 
                        base.VisitUsingDeclaration(usingDeclaration, data);
48
 
                        if (usingDeclaration.Parent is NamespaceDeclaration) {
49
 
                                nodesToMoveToCompilationUnit.Add(usingDeclaration);
50
 
                                RemoveCurrentNode();
51
 
                        }
52
 
                        return null;
53
 
                }
54
 
                
55
 
                TypeDeclaration currentType;
56
 
                
57
 
                public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
58
 
                {
59
 
                        // fix default inner type visibility
60
 
                        if (currentType != null && (typeDeclaration.Modifier & Modifiers.Visibility) == 0)
61
 
                                typeDeclaration.Modifier |= Modifiers.Private;
62
 
                        
63
 
                        TypeDeclaration outerType = currentType;
64
 
                        currentType = typeDeclaration;
65
 
                        
66
 
                        if ((typeDeclaration.Modifier & Modifiers.Static) == Modifiers.Static) {
67
 
                                typeDeclaration.Modifier &= ~Modifiers.Static;
68
 
                                typeDeclaration.Modifier |= Modifiers.Sealed;
69
 
                                typeDeclaration.Children.Insert(0, new ConstructorDeclaration("#ctor", Modifiers.Private, null, null));
70
 
                        }
71
 
                        
72
 
                        //   Conflicting field/property names -> m_field
73
 
                        List<string> properties = new List<string>();
74
 
                        foreach (object o in typeDeclaration.Children) {
75
 
                                PropertyDeclaration pd = o as PropertyDeclaration;
76
 
                                if (pd != null) {
77
 
                                        properties.Add(pd.Name);
78
 
                                }
79
 
                        }
80
 
                        List<VariableDeclaration> conflicts = new List<VariableDeclaration>();
81
 
                        foreach (object o in typeDeclaration.Children) {
82
 
                                FieldDeclaration fd = o as FieldDeclaration;
83
 
                                if (fd != null) {
84
 
                                        foreach (VariableDeclaration var in fd.Fields) {
85
 
                                                string name = var.Name;
86
 
                                                foreach (string propertyName in properties) {
87
 
                                                        if (name.Equals(propertyName, StringComparison.InvariantCultureIgnoreCase)) {
88
 
                                                                conflicts.Add(var);
89
 
                                                        }
90
 
                                                }
91
 
                                        }
92
 
                                }
93
 
                        }
94
 
                        new PrefixFieldsVisitor(conflicts, "m_").Run(typeDeclaration);
95
 
                        base.VisitTypeDeclaration(typeDeclaration, data);
96
 
                        currentType = outerType;
97
 
                        
98
 
                        return null;
99
 
                }
100
 
                
101
 
                public override object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data)
102
 
                {
103
 
                        // fix default inner type visibility
104
 
                        if (currentType != null && (delegateDeclaration.Modifier & Modifiers.Visibility) == 0)
105
 
                                delegateDeclaration.Modifier |= Modifiers.Private;
106
 
                        
107
 
                        return base.VisitDelegateDeclaration(delegateDeclaration, data);
108
 
                }
109
 
                
110
 
                public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
111
 
                {
112
 
                        base.VisitExpressionStatement(expressionStatement, data);
113
 
                        AssignmentExpression ass = expressionStatement.Expression as AssignmentExpression;
114
 
                        if (ass != null && ass.Right is AddressOfExpression) {
115
 
                                if (ass.Op == AssignmentOperatorType.Add) {
116
 
                                        ReplaceCurrentNode(new AddHandlerStatement(ass.Left, ass.Right));
117
 
                                } else if (ass.Op == AssignmentOperatorType.Subtract) {
118
 
                                        ReplaceCurrentNode(new RemoveHandlerStatement(ass.Left, ass.Right));
119
 
                                }
120
 
                        }
121
 
                        return null;
122
 
                }
123
 
                
124
 
                static string GetMemberNameOnThisReference(Expression expr)
125
 
                {
126
 
                        IdentifierExpression ident = expr as IdentifierExpression;
127
 
                        if (ident != null)
128
 
                                return ident.Identifier;
129
 
                        MemberReferenceExpression fre = expr as MemberReferenceExpression;
130
 
                        if (fre != null && fre.TargetObject is ThisReferenceExpression)
131
 
                                return fre.MemberName;
132
 
                        return null;
133
 
                }
134
 
                
135
 
                public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
136
 
                {
137
 
                        base.VisitAnonymousMethodExpression(anonymousMethodExpression, data);
138
 
                        if (anonymousMethodExpression.Body.Children.Count == 1) {
139
 
                                ReturnStatement rs = anonymousMethodExpression.Body.Children[0] as ReturnStatement;
140
 
                                if (rs != null) {
141
 
                                        LambdaExpression lambda = new LambdaExpression();
142
 
                                        lambda.ExpressionBody = rs.Expression;
143
 
                                        lambda.Parameters = anonymousMethodExpression.Parameters;
144
 
                                        ReplaceCurrentNode(lambda);
145
 
                                }
146
 
                        }
147
 
                        return null;
148
 
                }
149
 
                
150
 
                public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
151
 
                {
152
 
                        base.VisitAssignmentExpression(assignmentExpression, data);
153
 
                        if (assignmentExpression.Op == AssignmentOperatorType.Assign && !(assignmentExpression.Parent is ExpressionStatement)) {
154
 
                                AddInlineAssignHelper();
155
 
                                ReplaceCurrentNode(
156
 
                                        new InvocationExpression(
157
 
                                                new IdentifierExpression("InlineAssignHelper"),
158
 
                                                new List<Expression> { assignmentExpression.Left, assignmentExpression.Right }
159
 
                                        ));
160
 
                        }
161
 
                        return null;
162
 
                }
163
 
                
164
 
                void AddInlineAssignHelper()
165
 
                {
166
 
                        MethodDeclaration method;
167
 
                        foreach (INode node in currentType.Children) {
168
 
                                method = node as MethodDeclaration;
169
 
                                if (method != null && method.Name == "InlineAssignHelper") {
170
 
                                        // inline assign helper already exists
171
 
                                        return;
172
 
                                }
173
 
                        }
174
 
                        
175
 
                        method = new MethodDeclaration {
176
 
                                Name = "InlineAssignHelper",
177
 
                                Modifier = Modifiers.Private | Modifiers.Static,
178
 
                                TypeReference = new TypeReference("T"),
179
 
                                Parameters = new List<ParameterDeclarationExpression> {
180
 
                                        new ParameterDeclarationExpression(new TypeReference("T"), "target", ParameterModifiers.Ref),
181
 
                                        new ParameterDeclarationExpression(new TypeReference("T"), "value")
182
 
                                }};
183
 
                        method.Templates.Add(new TemplateDefinition("T", null));
184
 
                        method.Body = new BlockStatement();
185
 
                        method.Body.AddChild(new ExpressionStatement(new AssignmentExpression(
186
 
                                new IdentifierExpression("target"),
187
 
                                AssignmentOperatorType.Assign,
188
 
                                new IdentifierExpression("value"))));
189
 
                        method.Body.AddChild(new ReturnStatement(new IdentifierExpression("value")));
190
 
                        currentType.AddChild(method);
191
 
                }
192
 
                
193
 
                bool IsClassType(ClassType c)
194
 
                {
195
 
                        if (currentType == null) return false;
196
 
                        return currentType.Type == c;
197
 
                }
198
 
                
199
 
                public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
200
 
                {
201
 
                        if (!IsClassType(ClassType.Interface) && (methodDeclaration.Modifier & Modifiers.Visibility) == 0)
202
 
                                methodDeclaration.Modifier |= Modifiers.Private;
203
 
                        
204
 
                        base.VisitMethodDeclaration(methodDeclaration, data);
205
 
                        
206
 
                        const Modifiers externStatic = Modifiers.Static | Modifiers.Extern;
207
 
                        if ((methodDeclaration.Modifier & externStatic) == externStatic
208
 
                            && methodDeclaration.Body.IsNull)
209
 
                        {
210
 
                                foreach (AttributeSection sec in methodDeclaration.Attributes) {
211
 
                                        foreach (Attribute att in sec.Attributes) {
212
 
                                                if ("DllImport".Equals(att.Name, StringComparison.InvariantCultureIgnoreCase)) {
213
 
                                                        if (ConvertPInvoke(methodDeclaration, att)) {
214
 
                                                                sec.Attributes.Remove(att);
215
 
                                                                break;
216
 
                                                        }
217
 
                                                }
218
 
                                        }
219
 
                                        if (sec.Attributes.Count == 0) {
220
 
                                                methodDeclaration.Attributes.Remove(sec);
221
 
                                                break;
222
 
                                        }
223
 
                                }
224
 
                        }
225
 
                        
226
 
                        ToVBNetRenameConflictingVariablesVisitor.RenameConflicting(methodDeclaration);
227
 
                        
228
 
                        return null;
229
 
                }
230
 
                
231
 
                bool ConvertPInvoke(MethodDeclaration method, ICSharpCode.OldNRefactory.Ast.Attribute att)
232
 
                {
233
 
                        if (att.PositionalArguments.Count != 1)
234
 
                                return false;
235
 
                        PrimitiveExpression pe = att.PositionalArguments[0] as PrimitiveExpression;
236
 
                        if (pe == null || !(pe.Value is string))
237
 
                                return false;
238
 
                        string libraryName = (string)pe.Value;
239
 
                        string alias = null;
240
 
                        bool setLastError = false;
241
 
                        bool exactSpelling = false;
242
 
                        CharsetModifier charSet = CharsetModifier.Auto;
243
 
                        foreach (NamedArgumentExpression arg in att.NamedArguments) {
244
 
                                switch (arg.Name) {
245
 
                                        case "SetLastError":
246
 
                                                pe = arg.Expression as PrimitiveExpression;
247
 
                                                if (pe != null && pe.Value is bool)
248
 
                                                        setLastError = (bool)pe.Value;
249
 
                                                else
250
 
                                                        return false;
251
 
                                                break;
252
 
                                        case "ExactSpelling":
253
 
                                                pe = arg.Expression as PrimitiveExpression;
254
 
                                                if (pe != null && pe.Value is bool)
255
 
                                                        exactSpelling = (bool)pe.Value;
256
 
                                                else
257
 
                                                        return false;
258
 
                                                break;
259
 
                                        case "CharSet":
260
 
                                                {
261
 
                                                        MemberReferenceExpression fre = arg.Expression as MemberReferenceExpression;
262
 
                                                        if (fre == null || !(fre.TargetObject is IdentifierExpression))
263
 
                                                                return false;
264
 
                                                        if ((fre.TargetObject as IdentifierExpression).Identifier != "CharSet")
265
 
                                                                return false;
266
 
                                                        switch (fre.MemberName) {
267
 
                                                                case "Unicode":
268
 
                                                                        charSet = CharsetModifier.Unicode;
269
 
                                                                        break;
270
 
                                                                case "Auto":
271
 
                                                                        charSet = CharsetModifier.Auto;
272
 
                                                                        break;
273
 
                                                                case "Ansi":
274
 
                                                                        charSet = CharsetModifier.Ansi;
275
 
                                                                        break;
276
 
                                                                default:
277
 
                                                                        return false;
278
 
                                                        }
279
 
                                                }
280
 
                                                break;
281
 
                                        case "EntryPoint":
282
 
                                                pe = arg.Expression as PrimitiveExpression;
283
 
                                                if (pe != null)
284
 
                                                        alias = pe.Value as string;
285
 
                                                break;
286
 
                                        default:
287
 
                                                return false;
288
 
                                }
289
 
                        }
290
 
                        if (setLastError && exactSpelling) {
291
 
                                // Only P/Invokes with SetLastError and ExactSpelling can be converted to a DeclareDeclaration
292
 
                                const Modifiers removeModifiers = Modifiers.Static | Modifiers.Extern;
293
 
                                DeclareDeclaration decl = new DeclareDeclaration(method.Name, method.Modifier &~ removeModifiers,
294
 
                                                                                 method.TypeReference,
295
 
                                                                                 method.Parameters,
296
 
                                                                                 method.Attributes,
297
 
                                                                                 libraryName, alias, charSet);
298
 
                                ReplaceCurrentNode(decl);
299
 
                                base.VisitDeclareDeclaration(decl, null);
300
 
                                return true;
301
 
                        } else {
302
 
                                return false;
303
 
                        }
304
 
                }
305
 
                
306
 
                public override object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
307
 
                {
308
 
                        if (!IsClassType(ClassType.Interface) && (propertyDeclaration.Modifier & Modifiers.Visibility) == 0)
309
 
                                propertyDeclaration.Modifier |= Modifiers.Private;
310
 
                        base.VisitPropertyDeclaration(propertyDeclaration, data);
311
 
                        
312
 
                        ToVBNetRenameConflictingVariablesVisitor.RenameConflicting(propertyDeclaration);
313
 
                        
314
 
                        if (!IsClassType(ClassType.Interface) && (propertyDeclaration.Modifier & Modifiers.Abstract) == 0) {
315
 
                                if (propertyDeclaration.HasGetRegion && propertyDeclaration.HasSetRegion) {
316
 
                                        if (propertyDeclaration.GetRegion.Block.IsNull && propertyDeclaration.SetRegion.Block.IsNull) {
317
 
                                                // automatically implemented property
318
 
                                                string fieldName = "m_" + propertyDeclaration.Name;
319
 
                                                Modifiers fieldModifier = propertyDeclaration.Modifier & ~(Modifiers.Visibility) | Modifiers.Private;
320
 
                                                FieldDeclaration newField = new FieldDeclaration(null, propertyDeclaration.TypeReference, fieldModifier);
321
 
                                                newField.Fields.Add(new VariableDeclaration(fieldName));
322
 
                                                InsertAfterSibling(propertyDeclaration, newField);
323
 
                                                
324
 
                                                propertyDeclaration.GetRegion.Block = new BlockStatement();
325
 
                                                propertyDeclaration.GetRegion.Block.Return(ExpressionBuilder.Identifier(fieldName));
326
 
                                                propertyDeclaration.SetRegion.Block = new BlockStatement();
327
 
                                                propertyDeclaration.SetRegion.Block.Assign(ExpressionBuilder.Identifier(fieldName), ExpressionBuilder.Identifier("Value"));
328
 
                                                
329
 
                                        }
330
 
                                }
331
 
                        }
332
 
                        
333
 
                        return null;
334
 
                }
335
 
                
336
 
                public override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
337
 
                {
338
 
                        if (!IsClassType(ClassType.Interface) && (eventDeclaration.Modifier & Modifiers.Visibility) == 0)
339
 
                                eventDeclaration.Modifier |= Modifiers.Private;
340
 
                        return base.VisitEventDeclaration(eventDeclaration, data);
341
 
                }
342
 
                
343
 
                public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
344
 
                {
345
 
                        // make constructor private if visiblity is not set (unless constructor is static)
346
 
                        if ((constructorDeclaration.Modifier & (Modifiers.Visibility | Modifiers.Static)) == 0)
347
 
                                constructorDeclaration.Modifier |= Modifiers.Private;
348
 
                        base.VisitConstructorDeclaration(constructorDeclaration, data);
349
 
                        
350
 
                        ToVBNetRenameConflictingVariablesVisitor.RenameConflicting(constructorDeclaration);
351
 
                        
352
 
                        return null;
353
 
                }
354
 
                
355
 
                public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
356
 
                {
357
 
                        base.VisitParenthesizedExpression(parenthesizedExpression, data);
358
 
                        if (parenthesizedExpression.Expression is CastExpression) {
359
 
                                ReplaceCurrentNode(parenthesizedExpression.Expression); // remove parenthesis around casts
360
 
                        } else if (parenthesizedExpression.Parent is CastExpression) {
361
 
                                ReplaceCurrentNode(parenthesizedExpression.Expression); // remove parenthesis inside casts
362
 
                        }
363
 
                        return null;
364
 
                }
365
 
                
366
 
                public override object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
367
 
                {
368
 
                        for (int i = 0; i < arrayCreateExpression.Arguments.Count; i++) {
369
 
                                arrayCreateExpression.Arguments[i] = Expression.AddInteger(arrayCreateExpression.Arguments[i], -1);
370
 
                        }
371
 
                        return base.VisitArrayCreateExpression(arrayCreateExpression, data);
372
 
                }
373
 
                
374
 
                public override object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
375
 
                {
376
 
                        base.VisitDefaultValueExpression(defaultValueExpression, data);
377
 
                        Expression defaultValue = ExpressionBuilder.CreateDefaultValueForType(defaultValueExpression.TypeReference);
378
 
                        if (!(defaultValue is DefaultValueExpression))
379
 
                                ReplaceCurrentNode(defaultValue);
380
 
                        return null;
381
 
                }
382
 
        }
383
 
}