Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.11/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/OutputVisitor/CodeDomConvertVisitor.cs @ 13398

Last change on this file since 13398 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 51.9 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.CodeDom;
21using System.Collections.Generic;
22using System.IO;
23using System.Linq;
24using ICSharpCode.NRefactory.CSharp.Refactoring;
25using ICSharpCode.NRefactory.CSharp.Resolver;
26using ICSharpCode.NRefactory.CSharp.TypeSystem;
27using ICSharpCode.NRefactory.PatternMatching;
28using ICSharpCode.NRefactory.Semantics;
29using ICSharpCode.NRefactory.TypeSystem;
30
31namespace ICSharpCode.NRefactory.CSharp
32{
33  /// <summary>
34  /// Converts from C# AST to CodeDom.
35  /// </summary>
36  /// <remarks>
37  /// The conversion is intended for use in the SharpDevelop forms designer.
38  /// </remarks>
39  public class CodeDomConvertVisitor : IAstVisitor<CodeObject>
40  {
41    CSharpAstResolver resolver;
42   
43    /// <summary>
44    /// Gets/Sets whether the visitor should convert short type names into
45    /// fully qualified type names.
46    /// The default is <c>false</c>.
47    /// </summary>
48    public bool UseFullyQualifiedTypeNames { get; set; }
49   
50    /// <summary>
51    /// Gets whether the visitor is allowed to produce snippet nodes for
52    /// code that cannot be converted.
53    /// The default is <c>true</c>. If this property is set to <c>false</c>,
54    /// unconvertible code will throw a NotSupportedException.
55    /// </summary>
56    public bool AllowSnippetNodes { get; set; }
57   
58    public CodeDomConvertVisitor()
59    {
60      this.AllowSnippetNodes = true;
61    }
62   
63    /// <summary>
64    /// Converts a syntax tree to CodeDom.
65    /// </summary>
66    /// <param name="syntaxTree">The input syntax tree.</param>
67    /// <param name="compilation">The current compilation.</param>
68    /// <param name="unresolvedFile">CSharpUnresolvedFile, used for resolving.</param>
69    /// <returns>Converted CodeCompileUnit</returns>
70    /// <remarks>
71    /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
72    /// </remarks>
73    public CodeCompileUnit Convert(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile)
74    {
75      if (syntaxTree == null)
76        throw new ArgumentNullException("syntaxTree");
77      if (compilation == null)
78        throw new ArgumentNullException("compilation");
79     
80      CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
81      return (CodeCompileUnit)Convert(syntaxTree, resolver);
82    }
83   
84    /// <summary>
85    /// Converts a C# AST node to CodeDom.
86    /// </summary>
87    /// <param name="node">The input node.</param>
88    /// <param name="resolver">The AST resolver.</param>
89    /// <returns>The node converted into CodeDom</returns>
90    /// <remarks>
91    /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc.
92    /// </remarks>
93    public CodeObject Convert(AstNode node, CSharpAstResolver resolver)
94    {
95      if (node == null)
96        throw new ArgumentNullException("node");
97      if (resolver == null)
98        throw new ArgumentNullException("resolver");
99      try {
100        this.resolver = resolver;
101        return node.AcceptVisitor(this);
102      } finally {
103        this.resolver = null;
104      }
105    }
106   
107    ResolveResult Resolve(AstNode node)
108    {
109      if (resolver == null)
110        return ErrorResolveResult.UnknownError;
111      else
112        return resolver.Resolve(node);
113    }
114   
115    CodeExpression Convert(Expression expr)
116    {
117      return (CodeExpression)expr.AcceptVisitor(this);
118    }
119   
120    CodeExpression[] Convert(IEnumerable<Expression> expressions)
121    {
122      List<CodeExpression> result = new List<CodeExpression>();
123      foreach (Expression expr in expressions) {
124        CodeExpression e = Convert(expr);
125        if (e != null)
126          result.Add(e);
127      }
128      return result.ToArray();
129    }
130   
131    CodeTypeReference Convert(AstType type)
132    {
133      return (CodeTypeReference)type.AcceptVisitor(this);
134    }
135   
136    CodeTypeReference[] Convert(IEnumerable<AstType> types)
137    {
138      List<CodeTypeReference> result = new List<CodeTypeReference>();
139      foreach (AstType type in types) {
140        CodeTypeReference e = Convert(type);
141        if (e != null)
142          result.Add(e);
143      }
144      return result.ToArray();
145    }
146   
147    public CodeTypeReference Convert(IType type)
148    {
149      if (type.Kind == TypeKind.Array) {
150        ArrayType a = (ArrayType)type;
151        return new CodeTypeReference(Convert(a.ElementType), a.Dimensions);
152      } else if (type is ParameterizedType) {
153        var pt = (ParameterizedType)type;
154        return new CodeTypeReference(pt.GetDefinition().ReflectionName, pt.TypeArguments.Select(Convert).ToArray());
155      } else {
156        return new CodeTypeReference(type.ReflectionName);
157      }
158    }
159   
160    CodeStatement Convert(Statement stmt)
161    {
162      return (CodeStatement)stmt.AcceptVisitor(this);
163    }
164   
165    CodeStatement[] ConvertBlock(BlockStatement block)
166    {
167      List<CodeStatement> result = new List<CodeStatement>();
168      foreach (Statement stmt in block.Statements) {
169        if (stmt is EmptyStatement)
170          continue;
171        CodeStatement s = Convert(stmt);
172        if (s != null)
173          result.Add(s);
174      }
175      return result.ToArray();
176    }
177   
178    CodeStatement[] ConvertEmbeddedStatement(Statement embeddedStatement)
179    {
180      BlockStatement block = embeddedStatement as BlockStatement;
181      if (block != null) {
182        return ConvertBlock(block);
183      } else if (embeddedStatement is EmptyStatement) {
184        return new CodeStatement[0];
185      }
186      CodeStatement s = Convert(embeddedStatement);
187      if (s != null)
188        return new CodeStatement[] { s };
189      else
190        return new CodeStatement[0];
191    }
192   
193    string MakeSnippet(AstNode node)
194    {
195      if (!AllowSnippetNodes)
196        throw new NotSupportedException();
197      StringWriter w = new StringWriter();
198      CSharpOutputVisitor v = new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateMono ());
199      node.AcceptVisitor(v);
200      return w.ToString();
201    }
202   
203    /// <summary>
204    /// Converts an expression by storing it as C# snippet.
205    /// This is used for expressions that cannot be represented in CodeDom.
206    /// </summary>
207    CodeSnippetExpression MakeSnippetExpression(Expression expr)
208    {
209      return new CodeSnippetExpression(MakeSnippet(expr));
210    }
211   
212    CodeSnippetStatement MakeSnippetStatement(Statement stmt)
213    {
214      return new CodeSnippetStatement(MakeSnippet(stmt));
215    }
216
217    CodeObject IAstVisitor<CodeObject>.VisitNullNode(AstNode nullNode)
218    {
219      return null;
220    }
221
222    CodeObject IAstVisitor<CodeObject>.VisitErrorNode(AstNode errorNode)
223    {
224      return null;
225    }
226
227    CodeObject IAstVisitor<CodeObject>.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
228    {
229      return MakeSnippetExpression(anonymousMethodExpression);
230    }
231   
232    CodeObject IAstVisitor<CodeObject>.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression)
233    {
234      return MakeSnippetExpression(undocumentedExpression);
235    }
236   
237    CodeObject IAstVisitor<CodeObject>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
238    {
239      CodeArrayCreateExpression ace = new CodeArrayCreateExpression();
240      int dimensions = arrayCreateExpression.Arguments.Count;
241      int nestingDepth = arrayCreateExpression.AdditionalArraySpecifiers.Count;
242      if (dimensions > 0)
243        nestingDepth++;
244      if (nestingDepth > 1 || dimensions > 1) {
245        // CodeDom does not support jagged or multi-dimensional arrays
246        return MakeSnippetExpression(arrayCreateExpression);
247      }
248      if (arrayCreateExpression.Type.IsNull) {
249        ace.CreateType = Convert(Resolve(arrayCreateExpression).Type);
250      } else {
251        ace.CreateType = Convert(arrayCreateExpression.Type);
252      }
253      if (arrayCreateExpression.Arguments.Count == 1) {
254        ace.SizeExpression = Convert(arrayCreateExpression.Arguments.Single());
255      }
256      ace.Initializers.AddRange(Convert(arrayCreateExpression.Initializer.Elements));
257      return ace;
258    }
259   
260    CodeObject IAstVisitor<CodeObject>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
261    {
262      // Array initializers should be handled by the parent node
263      return MakeSnippetExpression(arrayInitializerExpression);
264    }
265   
266    CodeObject IAstVisitor<CodeObject>.VisitAsExpression(AsExpression asExpression)
267    {
268      return MakeSnippetExpression(asExpression);
269    }
270   
271    CodeObject IAstVisitor<CodeObject>.VisitAssignmentExpression(AssignmentExpression assignmentExpression)
272    {
273      // assignments are only supported as statements, not as expressions
274      return MakeSnippetExpression(assignmentExpression);
275    }
276   
277    CodeObject IAstVisitor<CodeObject>.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
278    {
279      return new CodeBaseReferenceExpression();
280    }
281   
282    CodeObject IAstVisitor<CodeObject>.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
283    {
284      CodeBinaryOperatorType op;
285      switch (binaryOperatorExpression.Operator) {
286        case BinaryOperatorType.BitwiseAnd:
287          op = CodeBinaryOperatorType.BitwiseAnd;
288          break;
289        case BinaryOperatorType.BitwiseOr:
290          op = CodeBinaryOperatorType.BitwiseOr;
291          break;
292        case BinaryOperatorType.ConditionalAnd:
293          op = CodeBinaryOperatorType.BooleanAnd;
294          break;
295        case BinaryOperatorType.ConditionalOr:
296          op = CodeBinaryOperatorType.BooleanOr;
297          break;
298        case BinaryOperatorType.GreaterThan:
299          op = CodeBinaryOperatorType.GreaterThan;
300          break;
301        case BinaryOperatorType.GreaterThanOrEqual:
302          op = CodeBinaryOperatorType.GreaterThanOrEqual;
303          break;
304        case BinaryOperatorType.LessThan:
305          op = CodeBinaryOperatorType.LessThan;
306          break;
307        case BinaryOperatorType.LessThanOrEqual:
308          op = CodeBinaryOperatorType.LessThanOrEqual;
309          break;
310        case BinaryOperatorType.Add:
311          op = CodeBinaryOperatorType.Add;
312          break;
313        case BinaryOperatorType.Subtract:
314          op = CodeBinaryOperatorType.Subtract;
315          break;
316        case BinaryOperatorType.Multiply:
317          op = CodeBinaryOperatorType.Multiply;
318          break;
319        case BinaryOperatorType.Divide:
320          op = CodeBinaryOperatorType.Divide;
321          break;
322        case BinaryOperatorType.Modulus:
323          op = CodeBinaryOperatorType.Modulus;
324          break;
325        case BinaryOperatorType.Equality:
326        case BinaryOperatorType.InEquality:
327          OperatorResolveResult rr = Resolve(binaryOperatorExpression) as OperatorResolveResult;
328          if (rr != null && rr.GetChildResults().Any(cr => cr.Type.IsReferenceType == true)) {
329            if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality)
330              op = CodeBinaryOperatorType.IdentityEquality;
331            else
332              op = CodeBinaryOperatorType.IdentityInequality;
333          } else {
334            if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) {
335              op = CodeBinaryOperatorType.ValueEquality;
336            } else {
337              // CodeDom is retarded and does not support ValueInequality, so we'll simulate it using
338              // ValueEquality and Not... but CodeDom doesn't have Not either, so we use
339              // '(a == b) == false'
340              return new CodeBinaryOperatorExpression(
341                new CodeBinaryOperatorExpression(
342                  Convert(binaryOperatorExpression.Left),
343                  CodeBinaryOperatorType.ValueEquality,
344                  Convert(binaryOperatorExpression.Right)
345                ),
346                CodeBinaryOperatorType.ValueEquality,
347                new CodePrimitiveExpression(false)
348              );
349            }
350          }
351          break;
352        default:
353          // not supported: xor, shift, null coalescing
354          return MakeSnippetExpression(binaryOperatorExpression);
355      }
356      return new CodeBinaryOperatorExpression(Convert(binaryOperatorExpression.Left), op, Convert(binaryOperatorExpression.Right));
357    }
358   
359    CodeObject IAstVisitor<CodeObject>.VisitCastExpression(CastExpression castExpression)
360    {
361      return new CodeCastExpression(Convert(castExpression.Type), Convert(castExpression.Expression));
362    }
363   
364    CodeObject IAstVisitor<CodeObject>.VisitCheckedExpression(CheckedExpression checkedExpression)
365    {
366      return MakeSnippetExpression(checkedExpression);
367    }
368   
369    CodeObject IAstVisitor<CodeObject>.VisitConditionalExpression(ConditionalExpression conditionalExpression)
370    {
371      return MakeSnippetExpression(conditionalExpression);
372    }
373   
374    CodeObject IAstVisitor<CodeObject>.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
375    {
376      return new CodeDefaultValueExpression(Convert(defaultValueExpression.Type));
377    }
378   
379    CodeObject IAstVisitor<CodeObject>.VisitDirectionExpression(DirectionExpression directionExpression)
380    {
381      System.CodeDom.FieldDirection direction;
382      if (directionExpression.FieldDirection == FieldDirection.Out) {
383        direction = System.CodeDom.FieldDirection.Out;
384      } else {
385        direction = System.CodeDom.FieldDirection.Ref;
386      }
387      return new CodeDirectionExpression(direction, Convert(directionExpression.Expression));
388    }
389   
390    CodeObject IAstVisitor<CodeObject>.VisitIdentifierExpression(IdentifierExpression identifierExpression)
391    {
392      ResolveResult rr = Resolve(identifierExpression);
393      LocalResolveResult lrr = rr as LocalResolveResult;
394      if (lrr != null && lrr.IsParameter) {
395        if (lrr.Variable.Name == "value" && identifierExpression.Ancestors.Any(a => a is Accessor)) {
396          return new CodePropertySetValueReferenceExpression();
397        } else {
398          return new CodeArgumentReferenceExpression(lrr.Variable.Name);
399        }
400      }
401      MemberResolveResult mrr = rr as MemberResolveResult;
402      if (mrr != null) {
403        return HandleMemberReference(null, identifierExpression.Identifier, identifierExpression.TypeArguments, mrr);
404      }
405      TypeResolveResult trr = rr as TypeResolveResult;
406      if (trr != null) {
407        CodeTypeReference typeRef;
408        if (UseFullyQualifiedTypeNames) {
409          typeRef = Convert(trr.Type);
410        } else {
411          typeRef = new CodeTypeReference(identifierExpression.Identifier);
412          typeRef.TypeArguments.AddRange(Convert(identifierExpression.TypeArguments));
413        }
414        return new CodeTypeReferenceExpression(typeRef);
415      }
416      MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
417      if (mgrr != null || identifierExpression.TypeArguments.Any()) {
418        return new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), identifierExpression.Identifier, Convert(identifierExpression.TypeArguments));
419      }
420      return new CodeVariableReferenceExpression(identifierExpression.Identifier);
421    }
422   
423    CodeObject IAstVisitor<CodeObject>.VisitIndexerExpression(IndexerExpression indexerExpression)
424    {
425      if (Resolve(indexerExpression) is ArrayAccessResolveResult)
426        return new CodeArrayIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments));
427      else
428        return new CodeIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments));
429    }
430   
431    CodeObject IAstVisitor<CodeObject>.VisitInvocationExpression(InvocationExpression invocationExpression)
432    {
433      MemberResolveResult rr = Resolve(invocationExpression) as MemberResolveResult;
434      CSharpInvocationResolveResult csRR = rr as CSharpInvocationResolveResult;
435      if (csRR != null && csRR.IsDelegateInvocation) {
436        return new CodeDelegateInvokeExpression(Convert(invocationExpression.Target), Convert(invocationExpression.Arguments));
437      }
438     
439      Expression methodExpr = invocationExpression.Target;
440      while (methodExpr is ParenthesizedExpression)
441        methodExpr = ((ParenthesizedExpression)methodExpr).Expression;
442      CodeMethodReferenceExpression mr = null;
443      MemberReferenceExpression mre = methodExpr as MemberReferenceExpression;
444      if (mre != null) {
445        mr = new CodeMethodReferenceExpression(Convert(mre.Target), mre.MemberName, Convert(mre.TypeArguments));
446      }
447      IdentifierExpression id = methodExpr as IdentifierExpression;
448      if (id != null) {
449        CodeExpression target;
450        if (rr != null && rr.Member.IsStatic)
451          target = new CodeTypeReferenceExpression(Convert(rr.Member.DeclaringType));
452        else
453          target = new CodeThisReferenceExpression();
454       
455        mr = new CodeMethodReferenceExpression(target, id.Identifier, Convert(id.TypeArguments));
456      }
457      if (mr != null)
458        return new CodeMethodInvokeExpression(mr, Convert(invocationExpression.Arguments));
459      else
460        return MakeSnippetExpression(invocationExpression);
461    }
462   
463    CodeObject IAstVisitor<CodeObject>.VisitIsExpression(IsExpression isExpression)
464    {
465      return MakeSnippetExpression(isExpression);
466    }
467   
468    CodeObject IAstVisitor<CodeObject>.VisitLambdaExpression(LambdaExpression lambdaExpression)
469    {
470      return MakeSnippetExpression(lambdaExpression);
471    }
472   
473    CodeObject IAstVisitor<CodeObject>.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
474    {
475      CodeExpression target = Convert(memberReferenceExpression.Target);
476      ResolveResult rr = Resolve(memberReferenceExpression);
477      MemberResolveResult mrr = rr as MemberResolveResult;
478      TypeResolveResult trr = rr as TypeResolveResult;
479      if (mrr != null) {
480        return HandleMemberReference(target, memberReferenceExpression.MemberName, memberReferenceExpression.TypeArguments, mrr);
481      } else if (trr != null) {
482        return new CodeTypeReferenceExpression(Convert(trr.Type));
483      } else {
484        if (memberReferenceExpression.TypeArguments.Any() || rr is MethodGroupResolveResult) {
485          return new CodeMethodReferenceExpression(target, memberReferenceExpression.MemberName, Convert(memberReferenceExpression.TypeArguments));
486        } else {
487          return new CodePropertyReferenceExpression(target, memberReferenceExpression.MemberName);
488        }
489      }
490    }
491   
492    CodeExpression HandleMemberReference(CodeExpression target, string identifier, AstNodeCollection<AstType> typeArguments, MemberResolveResult mrr)
493    {
494      if (target == null) {
495        if (mrr.Member.IsStatic)
496          target = new CodeTypeReferenceExpression(Convert(mrr.Member.DeclaringType));
497        else
498          target = new CodeThisReferenceExpression();
499      }
500      if (mrr.Member is IField) {
501        return new CodeFieldReferenceExpression(target, identifier);
502      } else if (mrr.Member is IMethod) {
503        return new CodeMethodReferenceExpression(target, identifier, Convert(typeArguments));
504      } else if (mrr.Member is IEvent) {
505        return new CodeEventReferenceExpression(target, identifier);
506      } else {
507        return new CodePropertyReferenceExpression(target, identifier);
508      }
509    }
510   
511    CodeObject IAstVisitor<CodeObject>.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
512    {
513      return MakeSnippetExpression(namedArgumentExpression);
514    }
515   
516    CodeObject IAstVisitor<CodeObject>.VisitNamedExpression(NamedExpression namedExpression)
517    {
518      return MakeSnippetExpression(namedExpression);
519    }
520   
521    CodeObject IAstVisitor<CodeObject>.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression)
522    {
523      return new CodePrimitiveExpression(null);
524    }
525   
526    CodeObject IAstVisitor<CodeObject>.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
527    {
528      if (!objectCreateExpression.Initializer.IsNull)
529        return MakeSnippetExpression(objectCreateExpression);
530      return new CodeObjectCreateExpression(Convert(objectCreateExpression.Type), Convert(objectCreateExpression.Arguments));
531    }
532   
533    CodeObject IAstVisitor<CodeObject>.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
534    {
535      return MakeSnippetExpression(anonymousTypeCreateExpression);
536    }
537   
538    CodeObject IAstVisitor<CodeObject>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
539    {
540      // CodeDom generators will insert parentheses where necessary
541      return Convert(parenthesizedExpression.Expression);
542    }
543   
544    CodeObject IAstVisitor<CodeObject>.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
545    {
546      return MakeSnippetExpression(pointerReferenceExpression);
547    }
548   
549    CodeObject IAstVisitor<CodeObject>.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
550    {
551      return new CodePrimitiveExpression(primitiveExpression.Value);
552    }
553   
554    CodeObject IAstVisitor<CodeObject>.VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
555    {
556      return MakeSnippetExpression(sizeOfExpression);
557    }
558   
559    CodeObject IAstVisitor<CodeObject>.VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
560    {
561      return MakeSnippetExpression(stackAllocExpression);
562    }
563   
564    CodeObject IAstVisitor<CodeObject>.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
565    {
566      return new CodeThisReferenceExpression();
567    }
568   
569    CodeObject IAstVisitor<CodeObject>.VisitTypeOfExpression(TypeOfExpression typeOfExpression)
570    {
571      return new CodeTypeOfExpression(Convert(typeOfExpression.Type));
572    }
573   
574    CodeObject IAstVisitor<CodeObject>.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
575    {
576      return new CodeTypeReferenceExpression(Convert(typeReferenceExpression.Type));
577    }
578   
579    CodeObject IAstVisitor<CodeObject>.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
580    {
581      switch (unaryOperatorExpression.Operator) {
582        case UnaryOperatorType.Not:
583          return new CodeBinaryOperatorExpression(
584            Convert(unaryOperatorExpression.Expression),
585            CodeBinaryOperatorType.ValueEquality,
586            new CodePrimitiveExpression(false));
587        case UnaryOperatorType.Minus:
588          return new CodeBinaryOperatorExpression(
589            new CodePrimitiveExpression(0),
590            CodeBinaryOperatorType.Subtract,
591            Convert(unaryOperatorExpression.Expression));
592        case UnaryOperatorType.Plus:
593          return Convert(unaryOperatorExpression.Expression);
594        default:
595          return MakeSnippetExpression(unaryOperatorExpression);
596      }
597    }
598   
599    CodeObject IAstVisitor<CodeObject>.VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
600    {
601      return MakeSnippetExpression(uncheckedExpression);
602    }
603   
604    CodeObject IAstVisitor<CodeObject>.VisitQueryExpression(QueryExpression queryExpression)
605    {
606      return MakeSnippetExpression(queryExpression);
607    }
608   
609    CodeObject IAstVisitor<CodeObject>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
610    {
611      throw new NotSupportedException();
612    }
613   
614    CodeObject IAstVisitor<CodeObject>.VisitQueryFromClause(QueryFromClause queryFromClause)
615    {
616      throw new NotSupportedException();
617    }
618   
619    CodeObject IAstVisitor<CodeObject>.VisitQueryLetClause(QueryLetClause queryLetClause)
620    {
621      throw new NotSupportedException();
622    }
623   
624    CodeObject IAstVisitor<CodeObject>.VisitQueryWhereClause(QueryWhereClause queryWhereClause)
625    {
626      throw new NotSupportedException();
627    }
628   
629    CodeObject IAstVisitor<CodeObject>.VisitQueryJoinClause(QueryJoinClause queryJoinClause)
630    {
631      throw new NotSupportedException();
632    }
633   
634    CodeObject IAstVisitor<CodeObject>.VisitQueryOrderClause(QueryOrderClause queryOrderClause)
635    {
636      throw new NotSupportedException();
637    }
638   
639    CodeObject IAstVisitor<CodeObject>.VisitQueryOrdering(QueryOrdering queryOrdering)
640    {
641      throw new NotSupportedException();
642    }
643   
644    CodeObject IAstVisitor<CodeObject>.VisitQuerySelectClause(QuerySelectClause querySelectClause)
645    {
646      throw new NotSupportedException();
647    }
648   
649    CodeObject IAstVisitor<CodeObject>.VisitQueryGroupClause(QueryGroupClause queryGroupClause)
650    {
651      throw new NotSupportedException();
652    }
653   
654    CodeObject IAstVisitor<CodeObject>.VisitAttribute(Attribute attribute)
655    {
656      throw new NotSupportedException();
657    }
658   
659    CodeObject IAstVisitor<CodeObject>.VisitAttributeSection(AttributeSection attributeSection)
660    {
661      throw new NotSupportedException();
662    }
663   
664    CodeAttributeDeclaration Convert(Attribute attribute)
665    {
666      var attr = new CodeAttributeDeclaration(Convert(attribute.Type));
667      foreach (Expression expr in attribute.Arguments) {
668        NamedExpression ne = expr as NamedExpression;
669        if (ne != null)
670          attr.Arguments.Add(new CodeAttributeArgument(ne.Name, Convert(ne.Expression)));
671        else
672          attr.Arguments.Add(new CodeAttributeArgument(Convert(expr)));
673      }
674      return attr;
675    }
676   
677    CodeAttributeDeclaration[] Convert(IEnumerable<AttributeSection> attributeSections)
678    {
679      List<CodeAttributeDeclaration> result = new List<CodeAttributeDeclaration>();
680      foreach (AttributeSection section in attributeSections) {
681        foreach (Attribute attr in section.Attributes) {
682          CodeAttributeDeclaration attrDecl = Convert(attr);
683          if (attrDecl != null)
684            result.Add(attrDecl);
685        }
686      }
687      return result.ToArray();
688    }
689   
690    CodeObject IAstVisitor<CodeObject>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
691    {
692      CodeTypeDelegate d = new CodeTypeDelegate(delegateDeclaration.Name);
693      d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers, SymbolKind.TypeDefinition);
694      d.CustomAttributes.AddRange(Convert(delegateDeclaration.Attributes));
695      d.ReturnType = Convert(delegateDeclaration.ReturnType);
696      d.Parameters.AddRange(Convert(delegateDeclaration.Parameters));
697      d.TypeParameters.AddRange(ConvertTypeParameters(delegateDeclaration.TypeParameters, delegateDeclaration.Constraints));
698      return d;
699    }
700   
701    MemberAttributes ConvertMemberAttributes(Modifiers modifiers, SymbolKind symbolKind)
702    {
703      MemberAttributes a = 0;
704      if ((modifiers & Modifiers.Abstract) != 0)
705        a |= MemberAttributes.Abstract;
706      if ((modifiers & Modifiers.Sealed) != 0)
707        a |= MemberAttributes.Final;
708      if (symbolKind != SymbolKind.TypeDefinition && (modifiers & (Modifiers.Abstract | Modifiers.Override | Modifiers.Virtual)) == 0)
709        a |= MemberAttributes.Final;
710      if ((modifiers & Modifiers.Static) != 0)
711        a |= MemberAttributes.Static;
712      if ((modifiers & Modifiers.Override) != 0)
713        a |= MemberAttributes.Override;
714      if ((modifiers & Modifiers.Const) != 0)
715        a |= MemberAttributes.Const;
716      if ((modifiers & Modifiers.New) != 0)
717        a |= MemberAttributes.New;
718     
719      if ((modifiers & Modifiers.Public) != 0)
720        a |= MemberAttributes.Public;
721      else if ((modifiers & (Modifiers.Protected | Modifiers.Internal)) == (Modifiers.Protected | Modifiers.Internal))
722        a |= MemberAttributes.FamilyOrAssembly;
723      else if ((modifiers & Modifiers.Protected) != 0)
724        a |= MemberAttributes.Family;
725      else if ((modifiers & Modifiers.Internal) != 0)
726        a |= MemberAttributes.Assembly;
727      else if ((modifiers & Modifiers.Private) != 0)
728        a |= MemberAttributes.Private;
729     
730      return a;
731    }
732   
733    CodeObject IAstVisitor<CodeObject>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
734    {
735      CodeNamespace ns = new CodeNamespace(namespaceDeclaration.Name);
736      foreach (AstNode node in namespaceDeclaration.Members) {
737        CodeObject r = node.AcceptVisitor(this);
738       
739        CodeNamespaceImport import = r as CodeNamespaceImport;
740        if (import != null)
741          ns.Imports.Add(import);
742       
743        CodeTypeDeclaration typeDecl = r as CodeTypeDeclaration;
744        if (typeDecl != null)
745          ns.Types.Add(typeDecl);
746      }
747      return ns;
748    }
749   
750    Stack<CodeTypeDeclaration> typeStack = new Stack<CodeTypeDeclaration>();
751   
752    CodeObject IAstVisitor<CodeObject>.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
753    {
754      //bool isNestedType = typeStack.Count > 0;
755      CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name);
756      typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers, SymbolKind.TypeDefinition);
757      typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes));
758     
759      switch (typeDeclaration.ClassType) {
760        case ClassType.Struct:
761          typeDecl.IsStruct = true;
762          break;
763        case ClassType.Interface:
764          typeDecl.IsInterface = true;
765          break;
766        case ClassType.Enum:
767          typeDecl.IsEnum = true;
768          break;
769        default:
770          typeDecl.IsClass = true;
771          break;
772      }
773      typeDecl.IsPartial = (typeDeclaration.Modifiers & Modifiers.Partial) == Modifiers.Partial;
774     
775      typeDecl.BaseTypes.AddRange(Convert(typeDeclaration.BaseTypes));
776      typeDecl.TypeParameters.AddRange(ConvertTypeParameters(typeDeclaration.TypeParameters, typeDeclaration.Constraints));
777     
778      typeStack.Push(typeDecl);
779      foreach (var member in typeDeclaration.Members) {
780        CodeTypeMember m = member.AcceptVisitor(this) as CodeTypeMember;
781        if (m != null)
782          typeDecl.Members.Add(m);
783      }
784      typeStack.Pop();
785      return typeDecl;
786    }
787   
788    void AddTypeMember(CodeTypeMember member)
789    {
790      if (typeStack.Count != 0)
791        typeStack.Peek().Members.Add(member);
792    }
793   
794    CodeObject IAstVisitor<CodeObject>.VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration)
795    {
796      return new CodeSnippetTypeMember(MakeSnippet(usingAliasDeclaration));
797    }
798   
799    CodeObject IAstVisitor<CodeObject>.VisitUsingDeclaration(UsingDeclaration usingDeclaration)
800    {
801      return new CodeNamespaceImport(usingDeclaration.Namespace);
802    }
803   
804    CodeObject IAstVisitor<CodeObject>.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
805    {
806      return new CodeSnippetTypeMember(MakeSnippet(externAliasDeclaration));
807    }
808   
809    CodeObject IAstVisitor<CodeObject>.VisitBlockStatement(BlockStatement blockStatement)
810    {
811      return new CodeConditionStatement(new CodePrimitiveExpression(true), ConvertBlock(blockStatement));
812    }
813   
814    CodeObject IAstVisitor<CodeObject>.VisitBreakStatement(BreakStatement breakStatement)
815    {
816      return MakeSnippetStatement(breakStatement);
817    }
818   
819    CodeObject IAstVisitor<CodeObject>.VisitCheckedStatement(CheckedStatement checkedStatement)
820    {
821      return MakeSnippetStatement(checkedStatement);
822    }
823   
824    CodeObject IAstVisitor<CodeObject>.VisitContinueStatement(ContinueStatement continueStatement)
825    {
826      return MakeSnippetStatement(continueStatement);
827    }
828   
829    CodeObject IAstVisitor<CodeObject>.VisitDoWhileStatement(DoWhileStatement doWhileStatement)
830    {
831      // do { } while (expr);
832      //
833      // emulate with:
834      //  for (bool _do = true; _do; _do = expr) {}
835      string varName = "_do" + doWhileStatement.Ancestors.OfType<DoWhileStatement>().Count();
836      return new CodeIterationStatement(
837        new CodeVariableDeclarationStatement(typeof(bool), varName, new CodePrimitiveExpression(true)),
838        new CodeVariableReferenceExpression(varName),
839        new CodeAssignStatement(new CodeVariableReferenceExpression(varName), Convert(doWhileStatement.Condition)),
840        ConvertEmbeddedStatement(doWhileStatement.EmbeddedStatement)
841      );
842    }
843   
844    CodeObject IAstVisitor<CodeObject>.VisitEmptyStatement(EmptyStatement emptyStatement)
845    {
846      return EmptyStatement();
847    }
848   
849    CodeStatement EmptyStatement()
850    {
851      return new CodeExpressionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(object))));
852    }
853   
854    CodeObject IAstVisitor<CodeObject>.VisitExpressionStatement(ExpressionStatement expressionStatement)
855    {
856      AssignmentExpression assignment = expressionStatement.Expression as AssignmentExpression;
857      if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign) {
858        return new CodeAssignStatement(Convert(assignment.Left), Convert(assignment.Right));
859      } else if (assignment != null && CanBeDuplicatedForCompoundAssignment(assignment.Left)) {
860        CodeBinaryOperatorType op;
861        switch (assignment.Operator) {
862          case AssignmentOperatorType.Add:
863            op = CodeBinaryOperatorType.Add;
864            break;
865          case AssignmentOperatorType.Subtract:
866            op = CodeBinaryOperatorType.Subtract;
867            break;
868          case AssignmentOperatorType.Multiply:
869            op = CodeBinaryOperatorType.Multiply;
870            break;
871          case AssignmentOperatorType.Divide:
872            op = CodeBinaryOperatorType.Divide;
873            break;
874          case AssignmentOperatorType.Modulus:
875            op = CodeBinaryOperatorType.Modulus;
876            break;
877          case AssignmentOperatorType.BitwiseAnd:
878            op = CodeBinaryOperatorType.BitwiseAnd;
879            break;
880          case AssignmentOperatorType.BitwiseOr:
881            op = CodeBinaryOperatorType.BitwiseOr;
882            break;
883          default:
884            return MakeSnippetStatement(expressionStatement);
885        }
886        var cboe = new CodeBinaryOperatorExpression(Convert(assignment.Left), op, Convert(assignment.Right));
887        return new CodeAssignStatement(Convert(assignment.Left), cboe);
888      }
889      UnaryOperatorExpression unary = expressionStatement.Expression as UnaryOperatorExpression;
890      if (unary != null && CanBeDuplicatedForCompoundAssignment(unary.Expression)) {
891        var op = unary.Operator;
892        if (op == UnaryOperatorType.Increment || op == UnaryOperatorType.PostIncrement) {
893          var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1));
894          return new CodeAssignStatement(Convert(unary.Expression), cboe);
895        } else if (op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostDecrement) {
896          var cboe = new CodeBinaryOperatorExpression(Convert(unary.Expression), CodeBinaryOperatorType.Subtract, new CodePrimitiveExpression(1));
897          return new CodeAssignStatement(Convert(unary.Expression), cboe);
898        }
899      }
900      if (assignment != null && assignment.Operator == AssignmentOperatorType.Add) {
901        var rr = Resolve(assignment.Left);
902        if (!rr.IsError && rr.Type.Kind == TypeKind.Delegate) {
903          var expr = (MemberReferenceExpression)assignment.Left;
904          var memberRef = (CodeEventReferenceExpression)HandleMemberReference(Convert(expr.Target), expr.MemberName, expr.TypeArguments, (MemberResolveResult)rr);
905          return new CodeAttachEventStatement(memberRef, Convert(assignment.Right));
906        }
907      }
908      return new CodeExpressionStatement(Convert(expressionStatement.Expression));
909    }
910   
911    bool CanBeDuplicatedForCompoundAssignment(Expression expr)
912    {
913      return expr is IdentifierExpression;
914    }
915   
916    CodeObject IAstVisitor<CodeObject>.VisitFixedStatement(FixedStatement fixedStatement)
917    {
918      return MakeSnippetStatement(fixedStatement);
919    }
920   
921    CodeObject IAstVisitor<CodeObject>.VisitForeachStatement(ForeachStatement foreachStatement)
922    {
923      return MakeSnippetStatement(foreachStatement);
924    }
925   
926    CodeObject IAstVisitor<CodeObject>.VisitForStatement(ForStatement forStatement)
927    {
928      if (forStatement.Initializers.Count != 1 || forStatement.Iterators.Count != 1)
929        return MakeSnippetStatement(forStatement);
930      return new CodeIterationStatement(
931        Convert(forStatement.Initializers.Single()),
932        Convert(forStatement.Condition),
933        Convert(forStatement.Iterators.Single()),
934        ConvertEmbeddedStatement(forStatement.EmbeddedStatement)
935      );
936    }
937   
938    CodeObject IAstVisitor<CodeObject>.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
939    {
940      return MakeSnippetStatement(gotoCaseStatement);
941    }
942   
943    CodeObject IAstVisitor<CodeObject>.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
944    {
945      return MakeSnippetStatement(gotoDefaultStatement);
946    }
947   
948    CodeObject IAstVisitor<CodeObject>.VisitGotoStatement(GotoStatement gotoStatement)
949    {
950      return new CodeGotoStatement(gotoStatement.Label);
951    }
952   
953    CodeObject IAstVisitor<CodeObject>.VisitIfElseStatement(IfElseStatement ifElseStatement)
954    {
955      return new CodeConditionStatement(
956        Convert(ifElseStatement.Condition),
957        ConvertEmbeddedStatement(ifElseStatement.TrueStatement),
958        ConvertEmbeddedStatement(ifElseStatement.FalseStatement));
959    }
960   
961    CodeObject IAstVisitor<CodeObject>.VisitLabelStatement(LabelStatement labelStatement)
962    {
963      return new CodeLabeledStatement(labelStatement.Label);
964    }
965   
966    CodeObject IAstVisitor<CodeObject>.VisitLockStatement(LockStatement lockStatement)
967    {
968      return MakeSnippetStatement(lockStatement);
969    }
970   
971    CodeObject IAstVisitor<CodeObject>.VisitReturnStatement(ReturnStatement returnStatement)
972    {
973      return new CodeMethodReturnStatement(Convert(returnStatement.Expression));
974    }
975   
976    CodeObject IAstVisitor<CodeObject>.VisitSwitchStatement(SwitchStatement switchStatement)
977    {
978      return MakeSnippetStatement(switchStatement);
979    }
980   
981    CodeObject IAstVisitor<CodeObject>.VisitSwitchSection(SwitchSection switchSection)
982    {
983      throw new NotSupportedException();
984    }
985   
986    CodeObject IAstVisitor<CodeObject>.VisitCaseLabel(CaseLabel caseLabel)
987    {
988      throw new NotSupportedException();
989    }
990   
991    CodeObject IAstVisitor<CodeObject>.VisitThrowStatement(ThrowStatement throwStatement)
992    {
993      return new CodeThrowExceptionStatement(Convert(throwStatement.Expression));
994    }
995   
996    CodeObject IAstVisitor<CodeObject>.VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
997    {
998      List<CodeCatchClause> catchClauses = new List<CodeCatchClause>();
999      foreach (var catchClause in tryCatchStatement.CatchClauses) {
1000        catchClauses.Add(new CodeCatchClause(catchClause.VariableName, Convert(catchClause.Type), ConvertBlock(catchClause.Body)));
1001      }
1002      return new CodeTryCatchFinallyStatement(
1003        ConvertBlock(tryCatchStatement.TryBlock),
1004        catchClauses.ToArray(),
1005        ConvertBlock(tryCatchStatement.FinallyBlock));
1006    }
1007   
1008    CodeObject IAstVisitor<CodeObject>.VisitCatchClause(CatchClause catchClause)
1009    {
1010      throw new NotSupportedException();
1011    }
1012   
1013    CodeObject IAstVisitor<CodeObject>.VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
1014    {
1015      return MakeSnippetStatement(uncheckedStatement);
1016    }
1017   
1018    CodeObject IAstVisitor<CodeObject>.VisitUnsafeStatement(UnsafeStatement unsafeStatement)
1019    {
1020      return MakeSnippetStatement(unsafeStatement);
1021    }
1022   
1023    CodeObject IAstVisitor<CodeObject>.VisitUsingStatement(UsingStatement usingStatement)
1024    {
1025      return MakeSnippetStatement(usingStatement);
1026    }
1027   
1028    CodeObject IAstVisitor<CodeObject>.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
1029    {
1030      if (variableDeclarationStatement.Variables.Count != 1)
1031        return MakeSnippetStatement(variableDeclarationStatement);
1032      VariableInitializer vi = variableDeclarationStatement.Variables.Single();
1033      return new CodeVariableDeclarationStatement(
1034        Convert(variableDeclarationStatement.Type),
1035        vi.Name,
1036        ConvertVariableInitializer(vi.Initializer, variableDeclarationStatement.Type));
1037    }
1038   
1039    CodeExpression ConvertVariableInitializer(Expression expr, AstType type)
1040    {
1041      ArrayInitializerExpression aie = expr as ArrayInitializerExpression;
1042      if (aie != null) {
1043        return new CodeArrayCreateExpression(Convert(type), Convert(aie.Elements));
1044      } else {
1045        return Convert(expr);
1046      }
1047    }
1048   
1049    CodeObject IAstVisitor<CodeObject>.VisitWhileStatement(WhileStatement whileStatement)
1050    {
1051      return new CodeIterationStatement(EmptyStatement(), Convert(whileStatement.Condition), EmptyStatement(), ConvertEmbeddedStatement(whileStatement.EmbeddedStatement));
1052    }
1053   
1054    CodeObject IAstVisitor<CodeObject>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
1055    {
1056      return MakeSnippetStatement(yieldBreakStatement);
1057    }
1058   
1059    CodeObject IAstVisitor<CodeObject>.VisitYieldReturnStatement(YieldReturnStatement yieldStatement)
1060    {
1061      return MakeSnippetStatement(yieldStatement);
1062    }
1063   
1064    CodeObject IAstVisitor<CodeObject>.VisitAccessor(Accessor accessor)
1065    {
1066      throw new NotSupportedException();
1067    }
1068   
1069    CodeObject IAstVisitor<CodeObject>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
1070    {
1071      CodeConstructor ctor = new CodeConstructor();
1072      ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers, SymbolKind.Constructor);
1073      ctor.CustomAttributes.AddRange(Convert(constructorDeclaration.Attributes));
1074      if (constructorDeclaration.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) {
1075        ctor.ChainedConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments));
1076      } else {
1077        ctor.BaseConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments));
1078      }
1079      ctor.Parameters.AddRange(Convert(constructorDeclaration.Parameters));
1080     
1081      ctor.Statements.AddRange(ConvertBlock(constructorDeclaration.Body));
1082      return ctor;
1083    }
1084   
1085    CodeObject IAstVisitor<CodeObject>.VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
1086    {
1087      throw new NotSupportedException();
1088    }
1089   
1090    CodeObject IAstVisitor<CodeObject>.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
1091    {
1092      return new CodeSnippetTypeMember(MakeSnippet(destructorDeclaration));
1093    }
1094   
1095    CodeObject IAstVisitor<CodeObject>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
1096    {
1097      TypeDeclaration td = enumMemberDeclaration.Parent as TypeDeclaration;
1098      CodeMemberField f = new CodeMemberField(td != null ? td.Name : "Enum", enumMemberDeclaration.Name);
1099      f.Attributes = MemberAttributes.Public | MemberAttributes.Static;
1100      f.CustomAttributes.AddRange(Convert(enumMemberDeclaration.Attributes));
1101      f.InitExpression = Convert(enumMemberDeclaration.Initializer);
1102      return f;
1103    }
1104   
1105    CodeObject IAstVisitor<CodeObject>.VisitEventDeclaration(EventDeclaration eventDeclaration)
1106    {
1107      foreach (VariableInitializer vi in eventDeclaration.Variables) {
1108        if (!vi.Initializer.IsNull) {
1109          AddTypeMember(new CodeSnippetTypeMember(MakeSnippet(eventDeclaration)));
1110          continue;
1111        }
1112       
1113        CodeMemberEvent e = new CodeMemberEvent();
1114        e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers, SymbolKind.Event);
1115        e.CustomAttributes.AddRange(Convert(eventDeclaration.Attributes));
1116        e.Name = vi.Name;
1117        e.Type = Convert(eventDeclaration.ReturnType);
1118        AddTypeMember(e);
1119      }
1120      return null;
1121    }
1122   
1123    CodeObject IAstVisitor<CodeObject>.VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration)
1124    {
1125      return new CodeSnippetTypeMember(MakeSnippet(customEventDeclaration));
1126    }
1127   
1128    CodeObject IAstVisitor<CodeObject>.VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
1129    {
1130      foreach (VariableInitializer vi in fieldDeclaration.Variables) {
1131        CodeMemberField f = new CodeMemberField(Convert(fieldDeclaration.ReturnType), vi.Name);
1132        f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers, SymbolKind.Field);
1133        f.CustomAttributes.AddRange(Convert(fieldDeclaration.Attributes));
1134        f.InitExpression = ConvertVariableInitializer(vi.Initializer, fieldDeclaration.ReturnType);
1135        AddTypeMember(f);
1136      }
1137      return null;
1138    }
1139   
1140    CodeObject IAstVisitor<CodeObject>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
1141    {
1142      CodeMemberProperty p = new CodeMemberProperty();
1143      p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers, SymbolKind.Indexer);
1144      p.CustomAttributes.AddRange(Convert(indexerDeclaration.Attributes));
1145      p.Name = "Items";
1146      p.PrivateImplementationType = Convert(indexerDeclaration.PrivateImplementationType);
1147      p.Parameters.AddRange(Convert(indexerDeclaration.Parameters));
1148      p.Type = Convert(indexerDeclaration.ReturnType);
1149     
1150      if (!indexerDeclaration.Getter.IsNull) {
1151        p.HasGet = true;
1152        p.GetStatements.AddRange(ConvertBlock(indexerDeclaration.Getter.Body));
1153      }
1154      if (!indexerDeclaration.Setter.IsNull) {
1155        p.HasSet = true;
1156        p.SetStatements.AddRange(ConvertBlock(indexerDeclaration.Setter.Body));
1157      }
1158      return p;
1159    }
1160   
1161    CodeObject IAstVisitor<CodeObject>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
1162    {
1163      CodeMemberMethod m = new CodeMemberMethod();
1164      m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers, SymbolKind.Method);
1165     
1166      m.CustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
1167      m.ReturnTypeCustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
1168     
1169      m.ReturnType = Convert(methodDeclaration.ReturnType);
1170      m.PrivateImplementationType = Convert(methodDeclaration.PrivateImplementationType);
1171      m.Name = methodDeclaration.Name;
1172      m.TypeParameters.AddRange(ConvertTypeParameters(methodDeclaration.TypeParameters, methodDeclaration.Constraints));
1173      m.Parameters.AddRange(Convert(methodDeclaration.Parameters));
1174     
1175      m.Statements.AddRange(ConvertBlock(methodDeclaration.Body));
1176      return m;
1177    }
1178   
1179    CodeObject IAstVisitor<CodeObject>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
1180    {
1181      CodeMemberMethod m = new CodeMemberMethod();
1182      m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers, SymbolKind.Method);
1183     
1184      m.CustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget != "return")));
1185      m.ReturnTypeCustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget == "return")));
1186     
1187      m.ReturnType = Convert(operatorDeclaration.ReturnType);
1188      m.Name = operatorDeclaration.Name;
1189      m.Parameters.AddRange(Convert(operatorDeclaration.Parameters));
1190     
1191      m.Statements.AddRange(ConvertBlock(operatorDeclaration.Body));
1192      return m;
1193    }
1194   
1195    CodeObject IAstVisitor<CodeObject>.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
1196    {
1197      var p = new CodeParameterDeclarationExpression(Convert(parameterDeclaration.Type), parameterDeclaration.Name);
1198      p.CustomAttributes.AddRange(Convert(parameterDeclaration.Attributes));
1199      switch (parameterDeclaration.ParameterModifier) {
1200        case ParameterModifier.Ref:
1201          p.Direction = System.CodeDom.FieldDirection.Ref;
1202          break;
1203        case ParameterModifier.Out:
1204          p.Direction = System.CodeDom.FieldDirection.Out;
1205          break;
1206      }
1207      return p;
1208    }
1209   
1210    CodeParameterDeclarationExpression[] Convert(IEnumerable<ParameterDeclaration> parameters)
1211    {
1212      List<CodeParameterDeclarationExpression> result = new List<CodeParameterDeclarationExpression>();
1213      foreach (ParameterDeclaration pd in parameters) {
1214        CodeParameterDeclarationExpression pde = pd.AcceptVisitor(this) as CodeParameterDeclarationExpression;
1215        if (pde != null)
1216          result.Add(pde);
1217      }
1218      return result.ToArray();
1219    }
1220   
1221    CodeObject IAstVisitor<CodeObject>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
1222    {
1223      CodeMemberProperty p = new CodeMemberProperty();
1224      p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers, SymbolKind.Property);
1225      p.CustomAttributes.AddRange(Convert(propertyDeclaration.Attributes));
1226      p.Name = propertyDeclaration.Name;
1227      p.PrivateImplementationType = Convert(propertyDeclaration.PrivateImplementationType);
1228      p.Type = Convert(propertyDeclaration.ReturnType);
1229     
1230      if (!propertyDeclaration.Getter.IsNull) {
1231        p.HasGet = true;
1232        p.GetStatements.AddRange(ConvertBlock(propertyDeclaration.Getter.Body));
1233      }
1234      if (!propertyDeclaration.Setter.IsNull) {
1235        p.HasSet = true;
1236        p.SetStatements.AddRange(ConvertBlock(propertyDeclaration.Setter.Body));
1237      }
1238      return p;
1239    }
1240   
1241    CodeObject IAstVisitor<CodeObject>.VisitVariableInitializer(VariableInitializer variableInitializer)
1242    {
1243      throw new NotSupportedException(); // should be handled by the parent node
1244    }
1245   
1246    CodeObject IAstVisitor<CodeObject>.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
1247    {
1248      return new CodeSnippetTypeMember(MakeSnippet(fixedFieldDeclaration));
1249    }
1250   
1251    CodeObject IAstVisitor<CodeObject>.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
1252    {
1253      throw new NotSupportedException(); // should be handled by the parent node
1254    }
1255   
1256    CodeObject IAstVisitor<CodeObject>.VisitSyntaxTree(SyntaxTree syntaxTree)
1257    {
1258      CodeCompileUnit cu = new CodeCompileUnit();
1259      var globalImports = new List<CodeNamespaceImport> ();
1260      foreach (AstNode node in syntaxTree.Children) {
1261        CodeObject o = node.AcceptVisitor(this);
1262       
1263        CodeNamespace ns = o as CodeNamespace;
1264        if (ns != null) {
1265          cu.Namespaces.Add(ns);
1266        }
1267        CodeTypeDeclaration td = o as CodeTypeDeclaration;
1268        if (td != null) {
1269          cu.Namespaces.Add(new CodeNamespace() { Types = { td } });
1270        }
1271       
1272        var import = o as CodeNamespaceImport;
1273        if (import != null)
1274          globalImports.Add (import);
1275      }
1276      foreach (var gi in globalImports) {
1277        for (int j = 0; j < cu.Namespaces.Count; j++) {
1278          var cn = cu.Namespaces [j];
1279          bool found = cn.Imports
1280            .Cast<CodeNamespaceImport> ()
1281            .Any (ns => ns.Namespace == gi.Namespace);
1282          if (!found)
1283            cn.Imports.Add (gi);
1284        }
1285      }
1286      return cu;
1287    }
1288   
1289    CodeObject IAstVisitor<CodeObject>.VisitSimpleType(SimpleType simpleType)
1290    {
1291      if (UseFullyQualifiedTypeNames) {
1292        IType type = Resolve(simpleType).Type;
1293        if (type.Kind != TypeKind.Unknown)
1294          return Convert(type);
1295      }
1296      var tr = new CodeTypeReference(simpleType.Identifier);
1297      tr.TypeArguments.AddRange(Convert(simpleType.TypeArguments));
1298      return tr;
1299    }
1300   
1301    CodeObject IAstVisitor<CodeObject>.VisitMemberType(MemberType memberType)
1302    {
1303      if (memberType.IsDoubleColon && new SimpleType("global").IsMatch(memberType.Target)) {
1304        var tr = new CodeTypeReference(memberType.MemberName, CodeTypeReferenceOptions.GlobalReference);
1305        tr.TypeArguments.AddRange(Convert(memberType.TypeArguments));
1306        return tr;
1307      }
1308      if (UseFullyQualifiedTypeNames || memberType.IsDoubleColon) {
1309        IType type = Resolve(memberType).Type;
1310        if (type.Kind != TypeKind.Unknown)
1311          return Convert(type);
1312      }
1313      CodeTypeReference target = Convert(memberType.Target);
1314      if (target == null)
1315        return null;
1316      target.BaseType = target.BaseType + "." + memberType.MemberName;
1317      target.TypeArguments.AddRange(Convert(memberType.TypeArguments));
1318      return target;
1319    }
1320   
1321    CodeObject IAstVisitor<CodeObject>.VisitComposedType(ComposedType composedType)
1322    {
1323      CodeTypeReference typeRef = Convert(composedType.BaseType);
1324      if (typeRef == null)
1325        return null;
1326      if (composedType.HasNullableSpecifier) {
1327        typeRef = new CodeTypeReference("System.Nullable") { TypeArguments = { typeRef } };
1328      }
1329      foreach (ArraySpecifier s in composedType.ArraySpecifiers.Reverse()) {
1330        typeRef = new CodeTypeReference(typeRef, s.Dimensions);
1331      }
1332      return typeRef;
1333    }
1334   
1335    CodeObject IAstVisitor<CodeObject>.VisitArraySpecifier(ArraySpecifier arraySpecifier)
1336    {
1337      throw new NotSupportedException(); // handled by parent node
1338    }
1339   
1340    CodeObject IAstVisitor<CodeObject>.VisitPrimitiveType(PrimitiveType primitiveType)
1341    {
1342      KnownTypeCode typeCode = primitiveType.KnownTypeCode;
1343      if (typeCode != KnownTypeCode.None) {
1344        KnownTypeReference ktr = KnownTypeReference.Get(typeCode);
1345        return new CodeTypeReference(ktr.Namespace + "." + ktr.Name);
1346      }
1347      return new CodeTypeReference(primitiveType.Keyword);
1348    }
1349   
1350    CodeObject IAstVisitor<CodeObject>.VisitComment (Comment comment)
1351    {
1352      return new CodeComment (comment.Content, comment.CommentType == CommentType.Documentation);
1353    }
1354
1355    CodeObject IAstVisitor<CodeObject>.VisitNewLine(NewLineNode newLineNode)
1356    {
1357      return null;
1358    }
1359
1360    CodeObject IAstVisitor<CodeObject>.VisitWhitespace(WhitespaceNode whitespaceNode)
1361    {
1362      return null;
1363    }
1364
1365    CodeObject IAstVisitor<CodeObject>.VisitText(TextNode textNode)
1366    {
1367      throw new NotSupportedException();
1368    }
1369
1370    CodeObject IAstVisitor<CodeObject>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
1371    {
1372      return new CodeComment ("#" + preProcessorDirective.Type.ToString ().ToLowerInvariant ());
1373    }
1374   
1375    CodeObject IAstVisitor<CodeObject>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
1376    {
1377      throw new NotSupportedException(); // type parameters and constraints are handled together
1378    }
1379   
1380    CodeObject IAstVisitor<CodeObject>.VisitConstraint(Constraint constraint)
1381    {
1382      throw new NotSupportedException();
1383    }
1384   
1385    CodeTypeParameter[] ConvertTypeParameters(IEnumerable<TypeParameterDeclaration> typeParameters, IEnumerable<Constraint> constraints)
1386    {
1387      List<CodeTypeParameter> result = new List<CodeTypeParameter>();
1388      foreach (TypeParameterDeclaration tpDecl in typeParameters) {
1389        CodeTypeParameter tp = new CodeTypeParameter(tpDecl.Name);
1390        tp.CustomAttributes.AddRange(Convert(tpDecl.Attributes));
1391        foreach (Constraint constraint in constraints) {
1392          if (constraint.TypeParameter.Identifier == tp.Name) {
1393            foreach (AstType baseType in constraint.BaseTypes) {
1394              if (baseType is PrimitiveType && ((PrimitiveType)baseType).Keyword == "new") {
1395                tp.HasConstructorConstraint = true;
1396              } else {
1397                CodeTypeReference tr = Convert(baseType);
1398                if (tr != null)
1399                  tp.Constraints.Add(tr);
1400              }
1401            }
1402          }
1403        }
1404        result.Add(tp);
1405      }
1406      return result.ToArray();
1407    }
1408   
1409    CodeObject IAstVisitor<CodeObject>.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode)
1410    {
1411      return null;
1412    }
1413   
1414    CodeObject IAstVisitor<CodeObject>.VisitIdentifier(Identifier identifier)
1415    {
1416      return null;
1417    }
1418   
1419    CodeObject IAstVisitor<CodeObject>.VisitPatternPlaceholder(AstNode placeholder, Pattern pattern)
1420    {
1421      return null;
1422    }
1423   
1424    CodeObject IAstVisitor<CodeObject>.VisitDocumentationReference(DocumentationReference documentationReference)
1425    {
1426      return null;
1427    }
1428  }
1429}
Note: See TracBrowser for help on using the repository browser.