Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System / compmod / system / codedom / compiler / CodeGenerator.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="CodeGenerator.cs" company="Microsoft">
3 // 
4 // <OWNER>Microsoft</OWNER>
5 //     Copyright (c) Microsoft Corporation.  All rights reserved.
6 // </copyright>                                                                
7 //------------------------------------------------------------------------------
8
9 namespace System.CodeDom.Compiler {
10     using System.Runtime.Remoting;
11     using System.Runtime.InteropServices;
12
13     using System.Diagnostics;
14     using System;
15     using Microsoft.Win32;
16     using System.IO;
17     using System.Collections;
18     using System.Reflection;
19     using System.Globalization;
20     using System.CodeDom;
21     using System.Security.Permissions;
22     using System.Text;
23     
24     /// <devdoc>
25     ///    <para>Provides a base class for code generators.</para>
26     /// </devdoc>
27     [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
28     [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")]
29     public abstract class CodeGenerator : ICodeGenerator {
30         private const int ParameterMultilineThreshold = 15;        
31         private IndentedTextWriter output;
32         private CodeGeneratorOptions options;
33
34         private CodeTypeDeclaration currentClass;
35         private CodeTypeMember currentMember;
36
37         private bool inNestedBinary = false;
38
39         /// <devdoc>
40         ///    <para>
41         ///       Gets the current class.
42         ///    </para>
43         /// </devdoc>
44         protected CodeTypeDeclaration CurrentClass {
45             get {
46                 return currentClass;
47             }
48         }
49
50         /// <devdoc>
51         ///    <para>
52         ///       Gets or sets the current class name.
53         ///    </para>
54         /// </devdoc>
55         protected string CurrentTypeName {
56             get {
57                 if (currentClass != null) {
58                     return currentClass.Name;
59                 }
60                 return "<% unknown %>";
61             }
62         }
63
64         /// <devdoc>
65         ///    <para>
66         ///       Gets or sets the current member of the class.
67         ///    </para>
68         /// </devdoc>
69         protected CodeTypeMember CurrentMember {
70             get {
71                 return currentMember;
72             }
73         }
74
75         /// <devdoc>
76         ///    <para>
77         ///       Gets or sets the current member name.
78         ///    </para>
79         /// </devdoc>
80         protected string CurrentMemberName {
81             get {
82                 if (currentMember != null) {
83                     return currentMember.Name;
84                 }
85                 return "<% unknown %>";
86             }
87         }
88
89         /// <devdoc>
90         ///    <para>
91         ///       Gets or sets a value indicating whether the current object being
92         ///       generated is an interface.
93         ///    </para>
94         /// </devdoc>
95         protected bool IsCurrentInterface {
96             get {
97                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
98                     return currentClass.IsInterface;
99                 }
100                 return false;
101             }
102         }
103
104         /// <devdoc>
105         ///    <para>
106         ///       Gets or sets a value indicating whether the current object being generated
107         ///       is a class.
108         ///    </para>
109         /// </devdoc>
110         protected bool IsCurrentClass {
111             get {
112                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
113                     return currentClass.IsClass;
114                 }
115                 return false;
116             }
117         }
118
119         /// <devdoc>
120         ///    <para>
121         ///       Gets or sets a value indicating whether the current object being generated
122         ///       is a struct.
123         ///    </para>
124         /// </devdoc>
125         protected bool IsCurrentStruct {
126             get {
127                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
128                     return currentClass.IsStruct;
129                 }
130                 return false;
131             }
132         }
133
134         /// <devdoc>
135         ///    <para>
136         ///       Gets or sets a value indicating whether the current object being generated
137         ///       is an enumeration.
138         ///    </para>
139         /// </devdoc>
140         protected bool IsCurrentEnum {
141             get {
142                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
143                     return currentClass.IsEnum;
144                 }
145                 return false;
146             }
147         }
148
149         /// <devdoc>
150         ///    <para>
151         ///       Gets or sets a value indicating whether the current object being generated
152         ///       is a delegate.
153         ///    </para>
154         /// </devdoc>
155         protected bool IsCurrentDelegate {
156             get {
157                 if (currentClass != null && currentClass is CodeTypeDelegate) {
158                     return true;
159                 }
160                 return false;
161             }
162         }
163
164         /// <devdoc>
165         ///    <para>
166         ///       Gets or sets the amount of spaces to indent.
167         ///    </para>
168         /// </devdoc>
169         protected int Indent {
170             get {
171                 return output.Indent;
172             }
173             set {
174                 output.Indent = value;
175             }
176         }
177
178         /// <devdoc>
179         ///    <para>
180         ///       Gets the token that represents <see langword='null'/>.
181         ///    </para>
182         /// </devdoc>
183         protected abstract string NullToken { get; }
184
185         /// <devdoc>
186         ///    <para>
187         ///       Gets or sets the System.IO.TextWriter
188         ///       to use for output.
189         ///    </para>
190         /// </devdoc>
191         protected TextWriter Output {
192             get {
193                 return output;
194             }
195         }
196
197         /// <devdoc>
198         ///    <para>[To be supplied.]</para>
199         /// </devdoc>
200         protected CodeGeneratorOptions Options {
201             get {
202                 return options;
203             }
204         }
205
206         private void GenerateType(CodeTypeDeclaration e) {
207             currentClass = e;
208
209             if (e.StartDirectives.Count > 0) {
210                 GenerateDirectives(e.StartDirectives);
211             }
212
213             GenerateCommentStatements(e.Comments);
214             
215             if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma);
216
217             GenerateTypeStart(e);
218             
219             if (Options.VerbatimOrder) {
220                 foreach (CodeTypeMember member in e.Members) {
221                     GenerateTypeMember(member, e);
222                 }                
223             }
224             else {
225
226                 GenerateFields(e);
227
228                 GenerateSnippetMembers(e);
229
230                 GenerateTypeConstructors(e);
231
232                 GenerateConstructors(e);
233
234                 GenerateProperties(e);
235
236                 GenerateEvents(e);
237
238                 GenerateMethods(e);
239
240                 GenerateNestedTypes(e);
241             }
242             // Nested types clobber the current class, so reset it.
243             currentClass = e;
244
245             GenerateTypeEnd(e);
246             if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma);
247             
248             if (e.EndDirectives.Count > 0) {
249                 GenerateDirectives(e.EndDirectives);
250             }
251             
252         }
253         
254         protected virtual void GenerateDirectives(CodeDirectiveCollection directives) {            
255         } 
256         
257         private void GenerateTypeMember(CodeTypeMember member, CodeTypeDeclaration declaredType) {
258
259             if (options.BlankLinesBetweenMembers) {
260                 Output.WriteLine();
261             }
262             
263             if (member is CodeTypeDeclaration) {
264                 ((ICodeGenerator)this).GenerateCodeFromType((CodeTypeDeclaration)member, output.InnerWriter, options);
265                 
266                 // Nested types clobber the current class, so reset it.
267                 currentClass = declaredType;
268                 
269                 // For nested types, comments and line pragmas are handled separately, so return here
270                 return;
271             }
272             
273             if (member.StartDirectives.Count > 0) {
274                 GenerateDirectives(member.StartDirectives);
275             }
276                        
277             GenerateCommentStatements(member.Comments);
278             
279             if (member.LinePragma != null) {
280                 GenerateLinePragmaStart(member.LinePragma);
281             }
282             
283             if (member is CodeMemberField) {
284                 GenerateField((CodeMemberField)member);
285             }
286             else if (member is CodeMemberProperty) {
287                 GenerateProperty((CodeMemberProperty)member, declaredType);
288             }
289             else if (member is CodeMemberMethod) {
290                 if (member is CodeConstructor) {
291                     GenerateConstructor((CodeConstructor)member, declaredType);
292                 }
293                 else if (member is CodeTypeConstructor) {
294                     GenerateTypeConstructor((CodeTypeConstructor) member);
295                 }
296                 else if (member is CodeEntryPointMethod) {
297                     GenerateEntryPointMethod((CodeEntryPointMethod)member, declaredType);
298                 } 
299                 else {
300                     GenerateMethod((CodeMemberMethod)member, declaredType);
301                 }
302             }            
303             else if (member is CodeMemberEvent) {
304                 GenerateEvent((CodeMemberEvent)member, declaredType);
305             }
306             else if (member is CodeSnippetTypeMember) {
307
308                 // Don't indent snippets, in order to preserve the column
309                 // information from the original code.  This improves the debugging
310                 // experience.
311                 int savedIndent = Indent;
312                 Indent=0;
313
314                 GenerateSnippetMember((CodeSnippetTypeMember)member);
315
316                 // Restore the indent
317                 Indent=savedIndent;
318                 
319                 // Generate an extra new line at the end of the snippet.
320                 // If the snippet is comment and this type only contains comments.
321                 // The generated code will not compile. 
322                 Output.WriteLine();
323             }
324
325             if (member.LinePragma != null) {
326                 GenerateLinePragmaEnd(member.LinePragma);
327             }
328
329             if (member.EndDirectives.Count > 0) {
330                 GenerateDirectives(member.EndDirectives);
331             }
332         }
333
334         private void GenerateTypeConstructors(CodeTypeDeclaration e) {
335             IEnumerator en = e.Members.GetEnumerator();
336             while (en.MoveNext()) {
337                 if (en.Current is CodeTypeConstructor) {
338                     currentMember = (CodeTypeMember)en.Current;
339
340                     if (options.BlankLinesBetweenMembers) {
341                         Output.WriteLine();
342                     }
343                     if (currentMember.StartDirectives.Count > 0) {
344                         GenerateDirectives(currentMember.StartDirectives);
345                     }
346                     GenerateCommentStatements(currentMember.Comments);
347                     CodeTypeConstructor imp = (CodeTypeConstructor)en.Current;
348                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
349                     GenerateTypeConstructor(imp);
350                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
351                     if (currentMember.EndDirectives.Count > 0) {
352                         GenerateDirectives(currentMember.EndDirectives);
353                     }
354                 }
355             }
356         }
357
358         /// <devdoc>
359         ///    <para> Generates code for the namepsaces in the specifield CodeDom compile unit.
360         ///     </para>
361         /// </devdoc>
362         protected void GenerateNamespaces(CodeCompileUnit e) {
363             foreach (CodeNamespace n in e.Namespaces) {
364                 ((ICodeGenerator)this).GenerateCodeFromNamespace(n, output.InnerWriter, options);
365             }
366         }
367
368         /// <devdoc>
369         ///    <para> Generates code for the specified CodeDom namespace representation and the classes it
370         ///       contains.</para>
371         /// </devdoc>
372         protected void GenerateTypes(CodeNamespace e) {
373             foreach (CodeTypeDeclaration c in e.Types) {
374                 if (options.BlankLinesBetweenMembers) {
375                             Output.WriteLine();
376                 }
377                 ((ICodeGenerator)this).GenerateCodeFromType(c, output.InnerWriter, options);
378             }
379         }
380
381         /// <internalonly/>
382         bool ICodeGenerator.Supports(GeneratorSupport support) {
383             return this.Supports(support);
384         }
385
386         /// <internalonly/>
387         void ICodeGenerator.GenerateCodeFromType(CodeTypeDeclaration e, TextWriter w, CodeGeneratorOptions o) {
388             bool setLocal = false;
389             if (output != null && w != output.InnerWriter) {
390                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
391             }
392             if (output == null) {
393                 setLocal = true;
394                 options = (o == null) ? new CodeGeneratorOptions() : o;
395                 output = new IndentedTextWriter(w, options.IndentString);
396             }
397
398             try {
399                 GenerateType(e);
400             }
401             finally {
402                 if (setLocal) {
403                     output = null;
404                     options = null;
405                 }
406             }
407         }
408
409         /// <internalonly/>
410         void ICodeGenerator.GenerateCodeFromExpression(CodeExpression e, TextWriter w, CodeGeneratorOptions o) {
411             bool setLocal = false;
412             if (output != null && w != output.InnerWriter) {
413                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
414             }
415             if (output == null) {
416                 setLocal = true;
417                 options = (o == null) ? new CodeGeneratorOptions() : o;
418                 output = new IndentedTextWriter(w, options.IndentString);
419             }
420
421             try {
422                 GenerateExpression(e);
423             }
424             finally {
425                 if (setLocal) {
426                     output = null;
427                     options = null;
428                 }
429             }
430         }
431
432         /// <internalonly/>
433         void ICodeGenerator.GenerateCodeFromCompileUnit(CodeCompileUnit e, TextWriter w, CodeGeneratorOptions o) {
434             bool setLocal = false;
435             if (output != null && w != output.InnerWriter) {
436                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
437             }
438             if (output == null) {
439                 setLocal = true;
440                 options = (o == null) ? new CodeGeneratorOptions() : o;
441                 output = new IndentedTextWriter(w, options.IndentString);
442             }
443
444             try {
445                 if (e is CodeSnippetCompileUnit) {
446                     GenerateSnippetCompileUnit((CodeSnippetCompileUnit) e);
447                 }
448                 else {
449                     GenerateCompileUnit(e);
450                 }
451             }
452             finally {
453                 if (setLocal) {
454                     output = null;
455                     options = null;
456                 }
457             }
458         }
459
460         /// <internalonly/>
461         void ICodeGenerator.GenerateCodeFromNamespace(CodeNamespace e, TextWriter w, CodeGeneratorOptions o) {
462             bool setLocal = false;
463             if (output != null && w != output.InnerWriter) {
464                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
465             }
466             if (output == null) {
467                 setLocal = true;
468                 options = (o == null) ? new CodeGeneratorOptions() : o;
469                 output = new IndentedTextWriter(w, options.IndentString);
470             }
471
472             try {
473                 GenerateNamespace(e);
474             }
475             finally {
476                 if (setLocal) {
477                     output = null;
478                     options = null;
479                 }
480             }
481         }
482
483         /// <internalonly/>
484         void ICodeGenerator.GenerateCodeFromStatement(CodeStatement e, TextWriter w, CodeGeneratorOptions o) {
485             bool setLocal = false;
486             if (output != null && w != output.InnerWriter) {
487                 throw new InvalidOperationException(SR.GetString(SR.CodeGenOutputWriter));
488             }
489             if (output == null) {
490                 setLocal = true;
491                 options = (o == null) ? new CodeGeneratorOptions() : o;
492                 output = new IndentedTextWriter(w, options.IndentString);
493             }
494
495             try {
496                 GenerateStatement(e);
497             }
498             finally {
499                 if (setLocal) {
500                     output = null;
501                     options = null;
502                 }
503             }
504         }
505         
506         public virtual void GenerateCodeFromMember(CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options) {
507             if (this.output != null) {
508                 throw new InvalidOperationException(SR.GetString(SR.CodeGenReentrance));
509             }
510             this.options = (options == null) ? new CodeGeneratorOptions() : options;
511             this.output = new IndentedTextWriter(writer, this.options.IndentString);
512
513             try {
514                 CodeTypeDeclaration dummyClass = new CodeTypeDeclaration();
515                 this.currentClass = dummyClass;
516                 GenerateTypeMember(member, dummyClass);
517             }
518             finally {
519                 this.currentClass = null;
520                 this.output = null;
521                 this.options = null;
522             }
523         }
524         
525
526         /// <internalonly/>
527         bool ICodeGenerator.IsValidIdentifier(string value) {
528             return this.IsValidIdentifier(value);
529         }
530         /// <internalonly/>
531         void ICodeGenerator.ValidateIdentifier(string value) {
532             this.ValidateIdentifier(value);
533         }
534
535         /// <internalonly/>
536         string ICodeGenerator.CreateEscapedIdentifier(string value) {
537             return this.CreateEscapedIdentifier(value);
538         }
539
540         /// <internalonly/>
541         string ICodeGenerator.CreateValidIdentifier(string value) {
542             return this.CreateValidIdentifier(value);
543         }
544
545         /// <internalonly/>
546         string ICodeGenerator.GetTypeOutput(CodeTypeReference type) {
547             return this.GetTypeOutput(type);
548         }
549
550         private void GenerateConstructors(CodeTypeDeclaration e) {
551             IEnumerator en = e.Members.GetEnumerator();
552             while (en.MoveNext()) {
553                 if (en.Current is CodeConstructor) {
554                     currentMember = (CodeTypeMember)en.Current;
555
556                     if (options.BlankLinesBetweenMembers) {
557                         Output.WriteLine();
558                     }
559                     if (currentMember.StartDirectives.Count > 0) {
560                         GenerateDirectives(currentMember.StartDirectives);
561                     }
562                     GenerateCommentStatements(currentMember.Comments);
563                     CodeConstructor imp = (CodeConstructor)en.Current;
564                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
565                     GenerateConstructor(imp, e);
566                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
567                     if (currentMember.EndDirectives.Count > 0) {
568                         GenerateDirectives(currentMember.EndDirectives);
569                     }
570                 }
571             }
572         }
573
574         private void GenerateEvents(CodeTypeDeclaration e) {
575             IEnumerator en = e.Members.GetEnumerator();
576             while (en.MoveNext()) {
577                 if (en.Current is CodeMemberEvent) {
578                     currentMember = (CodeTypeMember)en.Current;
579
580                     if (options.BlankLinesBetweenMembers) {
581                         Output.WriteLine();
582                     }
583                     if (currentMember.StartDirectives.Count > 0) {
584                         GenerateDirectives(currentMember.StartDirectives);
585                     }
586                     GenerateCommentStatements(currentMember.Comments);
587                     CodeMemberEvent imp = (CodeMemberEvent)en.Current;
588                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
589                     GenerateEvent(imp, e);
590                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
591                     if (currentMember.EndDirectives.Count > 0) {
592                         GenerateDirectives(currentMember.EndDirectives);
593                     }
594                 }
595             }
596         }
597
598         /// <devdoc>
599         ///    <para>Generates code for the specified CodeDom code expression representation.</para>
600         /// </devdoc>
601         protected void GenerateExpression(CodeExpression e) {
602             if (e is CodeArrayCreateExpression) {
603                 GenerateArrayCreateExpression((CodeArrayCreateExpression)e);
604             }
605             else if (e is CodeBaseReferenceExpression) {
606                 GenerateBaseReferenceExpression((CodeBaseReferenceExpression)e);
607             }
608             else if (e is CodeBinaryOperatorExpression) {
609                 GenerateBinaryOperatorExpression((CodeBinaryOperatorExpression)e);
610             }
611             else if (e is CodeCastExpression) {
612                 GenerateCastExpression((CodeCastExpression)e);
613             }
614             else if (e is CodeDelegateCreateExpression) {
615                 GenerateDelegateCreateExpression((CodeDelegateCreateExpression)e);
616             }
617             else if (e is CodeFieldReferenceExpression) {
618                 GenerateFieldReferenceExpression((CodeFieldReferenceExpression)e);
619             }
620             else if (e is CodeArgumentReferenceExpression) {
621                 GenerateArgumentReferenceExpression((CodeArgumentReferenceExpression)e);
622             }
623             else if (e is CodeVariableReferenceExpression) {
624                 GenerateVariableReferenceExpression((CodeVariableReferenceExpression)e);
625             }
626             else if (e is CodeIndexerExpression) {
627                 GenerateIndexerExpression((CodeIndexerExpression)e);
628             }
629             else if (e is CodeArrayIndexerExpression) {
630                 GenerateArrayIndexerExpression((CodeArrayIndexerExpression)e);
631             }
632             else if (e is CodeSnippetExpression) {
633                 GenerateSnippetExpression((CodeSnippetExpression)e);
634             }
635             else if (e is CodeMethodInvokeExpression) {
636                 GenerateMethodInvokeExpression((CodeMethodInvokeExpression)e);
637             }
638             else if (e is CodeMethodReferenceExpression) {
639                 GenerateMethodReferenceExpression((CodeMethodReferenceExpression)e);
640             }
641             else if (e is CodeEventReferenceExpression) {
642                 GenerateEventReferenceExpression((CodeEventReferenceExpression)e);
643             }
644             else if (e is CodeDelegateInvokeExpression) {
645                 GenerateDelegateInvokeExpression((CodeDelegateInvokeExpression)e);
646             }
647             else if (e is CodeObjectCreateExpression) {
648                 GenerateObjectCreateExpression((CodeObjectCreateExpression)e);
649             }
650             else if (e is CodeParameterDeclarationExpression) {
651                 GenerateParameterDeclarationExpression((CodeParameterDeclarationExpression)e);
652             }
653             else if (e is CodeDirectionExpression) {
654                 GenerateDirectionExpression((CodeDirectionExpression)e);
655             }
656             else if (e is CodePrimitiveExpression) {
657                 GeneratePrimitiveExpression((CodePrimitiveExpression)e);
658             }
659             else if (e is CodePropertyReferenceExpression) {
660                 GeneratePropertyReferenceExpression((CodePropertyReferenceExpression)e);
661             }
662             else if (e is CodePropertySetValueReferenceExpression) {
663                 GeneratePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e);
664             }
665             else if (e is CodeThisReferenceExpression) {
666                 GenerateThisReferenceExpression((CodeThisReferenceExpression)e);
667             }
668             else if (e is CodeTypeReferenceExpression) {
669                 GenerateTypeReferenceExpression((CodeTypeReferenceExpression)e);
670             }
671             else if (e is CodeTypeOfExpression) {
672                 GenerateTypeOfExpression((CodeTypeOfExpression)e);
673             }
674             else if (e is CodeDefaultValueExpression) {
675                 GenerateDefaultValueExpression((CodeDefaultValueExpression)e);
676             }
677             else {
678                 if (e == null) {
679                     throw new ArgumentNullException("e");
680                 }
681                 else {
682                     throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
683                 }
684             }
685         }
686
687         private void GenerateFields(CodeTypeDeclaration e) {
688             IEnumerator en = e.Members.GetEnumerator();
689             while (en.MoveNext()) {
690                 if (en.Current is CodeMemberField) {
691                     currentMember = (CodeTypeMember)en.Current;
692
693                     if (options.BlankLinesBetweenMembers) {
694                         Output.WriteLine();
695                     }
696                     if (currentMember.StartDirectives.Count > 0) {
697                         GenerateDirectives(currentMember.StartDirectives);
698                     }
699                     GenerateCommentStatements(currentMember.Comments);
700                     CodeMemberField imp = (CodeMemberField)en.Current;
701                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
702                     GenerateField(imp);
703                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
704                     if (currentMember.EndDirectives.Count > 0) {
705                         GenerateDirectives(currentMember.EndDirectives);
706                     }
707                 }
708             }
709         }
710
711         private void GenerateSnippetMembers(CodeTypeDeclaration e) {
712             IEnumerator en = e.Members.GetEnumerator();
713             bool hasSnippet = false;
714             while (en.MoveNext()) {
715                 if (en.Current is CodeSnippetTypeMember) {
716                     hasSnippet = true;
717                     currentMember = (CodeTypeMember)en.Current;
718
719                     if (options.BlankLinesBetweenMembers) {
720                         Output.WriteLine();
721                     }
722                     if (currentMember.StartDirectives.Count > 0) {
723                         GenerateDirectives(currentMember.StartDirectives);
724                     }
725                     GenerateCommentStatements(currentMember.Comments);
726                     CodeSnippetTypeMember imp = (CodeSnippetTypeMember)en.Current;
727                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
728
729                     // Don't indent snippets, in order to preserve the column
730                     // information from the original code.  This improves the debugging
731                     // experience.
732                     int savedIndent = Indent;
733                     Indent=0;
734
735                     GenerateSnippetMember(imp);
736
737                     // Restore the indent
738                     Indent=savedIndent;
739
740                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
741                     if (currentMember.EndDirectives.Count > 0) {
742                         GenerateDirectives(currentMember.EndDirectives);
743                     }
744
745                 }
746             }
747             // Generate an extra new line at the end of the snippet.
748             // If the snippet is comment and this type only contains comments.
749             // The generated code will not compile. 
750             if(hasSnippet) {
751                 Output.WriteLine();
752             }
753         }
754
755         /// <devdoc>
756         ///    <para> Generates code for the specified snippet code block
757         ///       </para>
758         /// </devdoc>
759         protected virtual void GenerateSnippetCompileUnit(CodeSnippetCompileUnit e) {
760             
761             GenerateDirectives(e.StartDirectives);
762
763             if (e.LinePragma != null) GenerateLinePragmaStart(e.LinePragma);
764             Output.WriteLine(e.Value);
765             if (e.LinePragma != null) GenerateLinePragmaEnd(e.LinePragma);
766
767             if (e.EndDirectives.Count > 0) {
768                 GenerateDirectives(e.EndDirectives);
769             }            
770         }
771
772         private void GenerateMethods(CodeTypeDeclaration e) {
773             IEnumerator en = e.Members.GetEnumerator();
774             while (en.MoveNext()) {
775                 if (en.Current is CodeMemberMethod
776                     && !(en.Current is CodeTypeConstructor)
777                     && !(en.Current is CodeConstructor)) {
778                     currentMember = (CodeTypeMember)en.Current;
779
780                     if (options.BlankLinesBetweenMembers) {
781                         Output.WriteLine();
782                     }
783                     if (currentMember.StartDirectives.Count > 0) {
784                         GenerateDirectives(currentMember.StartDirectives);
785                     }
786                     GenerateCommentStatements(currentMember.Comments);
787                     CodeMemberMethod imp = (CodeMemberMethod)en.Current;
788                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
789                     if (en.Current is CodeEntryPointMethod) {
790                         GenerateEntryPointMethod((CodeEntryPointMethod)en.Current, e);
791                     } 
792                     else {
793                         GenerateMethod(imp, e);
794                     }
795                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
796                     if (currentMember.EndDirectives.Count > 0) {
797                         GenerateDirectives(currentMember.EndDirectives);
798                     }
799                 }
800             }
801         }
802
803         private void GenerateNestedTypes(CodeTypeDeclaration e) {
804             IEnumerator en = e.Members.GetEnumerator();
805             while (en.MoveNext()) {
806                 if (en.Current is CodeTypeDeclaration) {
807                     if (options.BlankLinesBetweenMembers) {
808                         Output.WriteLine();
809                     }
810                     CodeTypeDeclaration currentClass = (CodeTypeDeclaration)en.Current;
811                     ((ICodeGenerator)this).GenerateCodeFromType(currentClass, output.InnerWriter, options);
812                 }
813             }
814         }
815
816         /// <devdoc>
817         ///    <para> Generates code for the specified CodeDom
818         ///       compile unit representation.</para>
819         /// </devdoc>
820         protected virtual void GenerateCompileUnit(CodeCompileUnit e) {
821             GenerateCompileUnitStart(e);
822             GenerateNamespaces(e);
823             GenerateCompileUnitEnd(e);
824         }
825
826         /// <devdoc>
827         ///    <para> Generates code for the specified CodeDom
828         ///       namespace representation.</para>
829         /// </devdoc>
830         protected virtual void GenerateNamespace(CodeNamespace e) {
831             GenerateCommentStatements(e.Comments);
832             GenerateNamespaceStart(e);
833
834             GenerateNamespaceImports(e);
835             Output.WriteLine("");
836
837             GenerateTypes(e);
838             GenerateNamespaceEnd(e);
839         }
840
841         /// <devdoc>
842         ///    <para>
843         ///       Generates code for the specified CodeDom based namespace import
844         ///       representation.
845         ///    </para>
846         /// </devdoc>
847         protected void GenerateNamespaceImports(CodeNamespace e) {
848             IEnumerator en = e.Imports.GetEnumerator();
849             while (en.MoveNext()) {
850                 CodeNamespaceImport imp = (CodeNamespaceImport)en.Current;
851                 if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
852                 GenerateNamespaceImport(imp);
853                 if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
854             }
855         }
856
857         private void GenerateProperties(CodeTypeDeclaration e) {
858             IEnumerator en = e.Members.GetEnumerator();
859             while (en.MoveNext()) {
860                 if (en.Current is CodeMemberProperty) {
861                     currentMember = (CodeTypeMember)en.Current;
862
863                     if (options.BlankLinesBetweenMembers) {
864                         Output.WriteLine();
865                     }
866                     if (currentMember.StartDirectives.Count > 0) {
867                         GenerateDirectives(currentMember.StartDirectives);
868                     }
869                     GenerateCommentStatements(currentMember.Comments);
870                     CodeMemberProperty imp = (CodeMemberProperty)en.Current;
871                     if (imp.LinePragma != null) GenerateLinePragmaStart(imp.LinePragma);
872                     GenerateProperty(imp, e);
873                     if (imp.LinePragma != null) GenerateLinePragmaEnd(imp.LinePragma);
874                     if (currentMember.EndDirectives.Count > 0) {
875                         GenerateDirectives(currentMember.EndDirectives);
876                     }
877                 }
878             }
879         }
880
881         /// <devdoc>
882         ///    <para>
883         ///       Generates code for
884         ///       the specified CodeDom based statement representation.
885         ///    </para>
886         /// </devdoc>
887         protected void GenerateStatement(CodeStatement e) {        
888             if (e.StartDirectives.Count > 0) {
889                 GenerateDirectives(e.StartDirectives);
890             }
891         
892             if (e.LinePragma != null) {
893                 GenerateLinePragmaStart(e.LinePragma);
894             }
895
896             if (e is CodeCommentStatement) {
897                 GenerateCommentStatement((CodeCommentStatement)e);
898             }
899             else if (e is CodeMethodReturnStatement) {
900                 GenerateMethodReturnStatement((CodeMethodReturnStatement)e);
901             }
902             else if (e is CodeConditionStatement) {
903                 GenerateConditionStatement((CodeConditionStatement)e);
904             }
905             else if (e is CodeTryCatchFinallyStatement) {
906                 GenerateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e);
907             }
908             else if (e is CodeAssignStatement) {
909                 GenerateAssignStatement((CodeAssignStatement)e);
910             }
911             else if (e is CodeExpressionStatement) {
912                 GenerateExpressionStatement((CodeExpressionStatement)e);
913             }
914             else if (e is CodeIterationStatement) {
915                 GenerateIterationStatement((CodeIterationStatement)e);
916             }
917             else if (e is CodeThrowExceptionStatement) {
918                 GenerateThrowExceptionStatement((CodeThrowExceptionStatement)e);
919             }
920             else if (e is CodeSnippetStatement) {
921                 // Don't indent snippet statements, in order to preserve the column
922                 // information from the original code.  This improves the debugging
923                 // experience.
924                 int savedIndent = Indent;
925                 Indent=0;
926
927                 GenerateSnippetStatement((CodeSnippetStatement)e);
928
929                 // Restore the indent
930                 Indent=savedIndent;
931             }
932             else if (e is CodeVariableDeclarationStatement) {
933                 GenerateVariableDeclarationStatement((CodeVariableDeclarationStatement)e);
934             }
935             else if (e is CodeAttachEventStatement) {
936                 GenerateAttachEventStatement((CodeAttachEventStatement)e);
937             }
938             else if (e is CodeRemoveEventStatement) {
939                 GenerateRemoveEventStatement((CodeRemoveEventStatement)e);
940             }
941             else if (e is CodeGotoStatement) {
942                 GenerateGotoStatement((CodeGotoStatement)e);
943             }
944             else if (e is CodeLabeledStatement) {
945                 GenerateLabeledStatement((CodeLabeledStatement)e);
946             }
947             else {
948                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
949             }
950
951             if (e.LinePragma != null) {
952                 GenerateLinePragmaEnd(e.LinePragma);
953             }
954             if (e.EndDirectives.Count > 0) {
955                 GenerateDirectives(e.EndDirectives);
956             }            
957         }
958
959         /// <devdoc>
960         ///    <para>
961         ///       Generates code for the specified CodeDom based statement representations.
962         ///    </para>
963         /// </devdoc>
964         protected void GenerateStatements(CodeStatementCollection stms) {
965             IEnumerator en = stms.GetEnumerator();
966             while (en.MoveNext()) {
967                 ((ICodeGenerator)this).GenerateCodeFromStatement((CodeStatement)en.Current, output.InnerWriter, options);
968             }
969         }
970
971         /// <devdoc>
972         ///    <para>
973         ///       Generates code for the specified System.CodeDom.CodeAttributeBlock.
974         ///    </para>
975         /// </devdoc>
976         protected virtual void OutputAttributeDeclarations(CodeAttributeDeclarationCollection attributes) {
977             if (attributes.Count == 0) return;
978             GenerateAttributeDeclarationsStart(attributes);
979             bool first = true;
980             IEnumerator en = attributes.GetEnumerator();
981             while (en.MoveNext()) {
982                 if (first) {
983                     first = false;
984                 }
985                 else {
986                     ContinueOnNewLine(", ");
987                 }
988
989                 CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
990                 Output.Write(current.Name);
991                 Output.Write("(");
992
993                 bool firstArg = true;
994                 foreach (CodeAttributeArgument arg in current.Arguments) {
995                     if (firstArg) {
996                         firstArg = false;
997                     }
998                     else {
999                         Output.Write(", ");
1000                     }
1001
1002                     OutputAttributeArgument(arg);
1003                 }
1004
1005                 Output.Write(")");
1006
1007             }
1008             GenerateAttributeDeclarationsEnd(attributes);
1009         }
1010
1011
1012         /// <devdoc>
1013         ///    <para>
1014         ///       Outputs an argument in a attribute block.
1015         ///    </para>
1016         /// </devdoc>
1017         protected virtual void OutputAttributeArgument(CodeAttributeArgument arg) {
1018             if (arg.Name != null && arg.Name.Length > 0) {
1019                 OutputIdentifier(arg.Name);
1020                 Output.Write("=");
1021             }
1022             ((ICodeGenerator)this).GenerateCodeFromExpression(arg.Value, output.InnerWriter, options);
1023         }
1024
1025         /// <devdoc>
1026         ///    <para>
1027         ///       Generates code for the specified System.CodeDom.FieldDirection.
1028         ///    </para>
1029         /// </devdoc>
1030         protected virtual void OutputDirection(FieldDirection dir) {
1031             switch (dir) {
1032                 case FieldDirection.In:
1033                     break;
1034                 case FieldDirection.Out:
1035                     Output.Write("out ");
1036                     break;
1037                 case FieldDirection.Ref:
1038                     Output.Write("ref ");
1039                     break;
1040             }
1041         }
1042
1043         /// <devdoc>
1044         ///    <para>[To be supplied.]</para>
1045         /// </devdoc>
1046         protected virtual void OutputFieldScopeModifier(MemberAttributes attributes) {
1047             switch (attributes & MemberAttributes.VTableMask) {
1048                 case MemberAttributes.New:
1049                     Output.Write("new ");
1050                     break;
1051             }
1052
1053             switch (attributes & MemberAttributes.ScopeMask) {
1054                 case MemberAttributes.Final:
1055                     break;
1056                 case MemberAttributes.Static:
1057                     Output.Write("static ");
1058                     break;
1059                 case MemberAttributes.Const:
1060                     Output.Write("const ");
1061                     break;
1062                 default:
1063                     break;
1064             }
1065         }
1066
1067         /// <devdoc>
1068         ///    <para>
1069         ///       Generates code for the specified member access modifier.
1070         ///    </para>
1071         /// </devdoc>
1072         protected virtual void OutputMemberAccessModifier(MemberAttributes attributes) {
1073             switch (attributes & MemberAttributes.AccessMask) {
1074                 case MemberAttributes.Assembly:
1075                     Output.Write("internal ");
1076                     break;
1077                 case MemberAttributes.FamilyAndAssembly:
1078                     Output.Write("internal ");  /*FamANDAssem*/ 
1079                     break;
1080                 case MemberAttributes.Family:
1081                     Output.Write("protected ");
1082                     break;
1083                 case MemberAttributes.FamilyOrAssembly:
1084                     Output.Write("protected internal ");
1085                     break;
1086                 case MemberAttributes.Private:
1087                     Output.Write("private ");
1088                     break;
1089                 case MemberAttributes.Public:
1090                     Output.Write("public ");
1091                     break;
1092             }
1093         }
1094
1095         /// <devdoc>
1096         ///    <para>
1097         ///       Generates code for the specified member scope modifier.
1098         ///    </para>
1099         /// </devdoc>
1100         protected virtual void OutputMemberScopeModifier(MemberAttributes attributes) {
1101             switch (attributes & MemberAttributes.VTableMask) {
1102                 case MemberAttributes.New:
1103                     Output.Write("new ");
1104                     break;
1105             }
1106
1107             switch (attributes & MemberAttributes.ScopeMask) {
1108                 case MemberAttributes.Abstract:
1109                     Output.Write("abstract ");
1110                     break;
1111                 case MemberAttributes.Final:
1112                     Output.Write("");
1113                     break;
1114                 case MemberAttributes.Static:
1115                     Output.Write("static ");
1116                     break;
1117                 case MemberAttributes.Override:
1118                     Output.Write("override ");
1119                     break;
1120                 default:
1121                     switch (attributes & MemberAttributes.AccessMask) {
1122                         case MemberAttributes.Family:
1123                         case MemberAttributes.Public:
1124                             Output.Write("virtual ");
1125                             break;
1126                         default:
1127                             // nothing;
1128                             break;
1129                     }
1130                     break;
1131             }
1132         }
1133
1134         /// <devdoc>
1135         ///    <para>
1136         ///       Generates code for the specified type.
1137         ///    </para>
1138         /// </devdoc>
1139         protected abstract void OutputType(CodeTypeReference typeRef);
1140
1141         /// <devdoc>
1142         ///    <para>
1143         ///       Generates code for the specified type attributes.
1144         ///    </para>
1145         /// </devdoc>
1146         protected virtual void OutputTypeAttributes(TypeAttributes attributes, bool isStruct, bool isEnum) {
1147             switch(attributes & TypeAttributes.VisibilityMask) {
1148                 case TypeAttributes.Public:                  
1149                 case TypeAttributes.NestedPublic:                    
1150                     Output.Write("public ");
1151                     break;
1152                 case TypeAttributes.NestedPrivate:
1153                     Output.Write("private ");
1154                     break;
1155             }
1156             
1157             if (isStruct) {
1158                 Output.Write("struct ");
1159             }
1160             else if (isEnum) {
1161                 Output.Write("enum ");
1162             }     
1163             else {            
1164                 switch (attributes & TypeAttributes.ClassSemanticsMask) {
1165                     case TypeAttributes.Class:
1166                         if ((attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed) {
1167                             Output.Write("sealed ");
1168                         }
1169                         if ((attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract) {
1170                             Output.Write("abstract ");
1171                         }
1172                         Output.Write("class ");
1173                         break;                
1174                     case TypeAttributes.Interface:
1175                         Output.Write("interface ");
1176                         break;
1177                 }     
1178             }   
1179         }
1180
1181         /// <devdoc>
1182         ///    <para>
1183         ///       Generates code for the specified object type and name pair.
1184         ///    </para>
1185         /// </devdoc>
1186         protected virtual void OutputTypeNamePair(CodeTypeReference typeRef, string name) {
1187             OutputType(typeRef);
1188             Output.Write(" ");
1189             OutputIdentifier(name);
1190         }
1191
1192         /// <devdoc>
1193         ///    <para>[To be supplied.]</para>
1194         /// </devdoc>
1195         protected virtual void OutputIdentifier(string ident) {
1196             Output.Write(ident);
1197         }
1198
1199         /// <devdoc>
1200         ///    <para>
1201         ///       Generates code for the specified expression list.
1202         ///    </para>
1203         /// </devdoc>
1204         protected virtual void OutputExpressionList(CodeExpressionCollection expressions) {
1205             OutputExpressionList(expressions, false /*newlineBetweenItems*/);
1206         }
1207
1208         /// <devdoc>
1209         ///    <para>
1210         ///       Generates code for the specified expression list.
1211         ///    </para>
1212         /// </devdoc>
1213         protected virtual void OutputExpressionList(CodeExpressionCollection expressions, bool newlineBetweenItems) {
1214             bool first = true;
1215             IEnumerator en = expressions.GetEnumerator();
1216             Indent++;
1217             while (en.MoveNext()) {
1218                 if (first) {
1219                     first = false;
1220                 }
1221                 else {
1222                     if (newlineBetweenItems)
1223                         ContinueOnNewLine(",");
1224                     else
1225                         Output.Write(", ");
1226                 }
1227                 ((ICodeGenerator)this).GenerateCodeFromExpression((CodeExpression)en.Current, output.InnerWriter, options);
1228             }
1229             Indent--;
1230         }
1231
1232         /// <devdoc>
1233         ///    <para>
1234         ///       Generates code for the specified operator.
1235         ///    </para>
1236         /// </devdoc>
1237         protected virtual void OutputOperator(CodeBinaryOperatorType op) {
1238             switch (op) {
1239                 case CodeBinaryOperatorType.Add:
1240                     Output.Write("+");
1241                     break;
1242                 case CodeBinaryOperatorType.Subtract:
1243                     Output.Write("-");
1244                     break;
1245                 case CodeBinaryOperatorType.Multiply:
1246                     Output.Write("*");
1247                     break;
1248                 case CodeBinaryOperatorType.Divide:
1249                     Output.Write("/");
1250                     break;
1251                 case CodeBinaryOperatorType.Modulus:
1252                     Output.Write("%");
1253                     break;
1254                 case CodeBinaryOperatorType.Assign:
1255                     Output.Write("=");
1256                     break;
1257                 case CodeBinaryOperatorType.IdentityInequality:
1258                     Output.Write("!=");
1259                     break;
1260                 case CodeBinaryOperatorType.IdentityEquality:
1261                     Output.Write("==");
1262                     break;
1263                 case CodeBinaryOperatorType.ValueEquality:
1264                     Output.Write("==");
1265                     break;
1266                 case CodeBinaryOperatorType.BitwiseOr:
1267                     Output.Write("|");
1268                     break;
1269                 case CodeBinaryOperatorType.BitwiseAnd:
1270                     Output.Write("&");
1271                     break;
1272                 case CodeBinaryOperatorType.BooleanOr:
1273                     Output.Write("||");
1274                     break;
1275                 case CodeBinaryOperatorType.BooleanAnd:
1276                     Output.Write("&&");
1277                     break;
1278                 case CodeBinaryOperatorType.LessThan:
1279                     Output.Write("<");
1280                     break;
1281                 case CodeBinaryOperatorType.LessThanOrEqual:
1282                     Output.Write("<=");
1283                     break;
1284                 case CodeBinaryOperatorType.GreaterThan:
1285                     Output.Write(">");
1286                     break;
1287                 case CodeBinaryOperatorType.GreaterThanOrEqual:
1288                     Output.Write(">=");
1289                     break;
1290             }
1291         }
1292
1293         /// <devdoc>
1294         ///    <para>
1295         ///       Generates code for the specified parameters.
1296         ///    </para>
1297         /// </devdoc>
1298         protected virtual void OutputParameters(CodeParameterDeclarationExpressionCollection parameters) {
1299             bool first = true;
1300             bool multiline = parameters.Count > ParameterMultilineThreshold;
1301             if (multiline) {
1302                 Indent += 3;
1303             }
1304             IEnumerator en = parameters.GetEnumerator();
1305             while (en.MoveNext()) {
1306                 CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current;
1307                 if (first) {
1308                     first = false;
1309                 }
1310                 else {
1311                     Output.Write(", ");
1312                 }
1313                 if (multiline) {
1314                     ContinueOnNewLine("");
1315                 }
1316                 GenerateExpression(current);
1317             }
1318             if (multiline) {
1319                 Indent -= 3;
1320             }
1321         }
1322
1323         /// <devdoc>
1324         ///    <para>
1325         ///       Generates code for the specified CodeDom based array creation expression
1326         ///       representation.
1327         ///    </para>
1328         /// </devdoc>
1329         protected abstract void GenerateArrayCreateExpression(CodeArrayCreateExpression e);
1330         /// <devdoc>
1331         ///    <para>
1332         ///       Generates code for the specified CodeDom based base reference expression
1333         ///       representation.
1334         ///    </para>
1335         /// </devdoc>
1336         protected abstract void GenerateBaseReferenceExpression(CodeBaseReferenceExpression e);
1337
1338         /// <devdoc>
1339         ///    <para>
1340         ///       Generates code for the specified CodeDom based binary operator
1341         ///       expression representation.
1342         ///    </para>
1343         /// </devdoc>
1344         protected virtual void GenerateBinaryOperatorExpression(CodeBinaryOperatorExpression e) {
1345             bool indentedExpression = false;
1346             Output.Write("(");
1347
1348             GenerateExpression(e.Left);
1349             Output.Write(" ");
1350
1351             if (e.Left is CodeBinaryOperatorExpression || e.Right is CodeBinaryOperatorExpression) {
1352                 // In case the line gets too long with nested binary operators, we need to output them on
1353                 // different lines. However we want to indent them to maintain readability, but this needs
1354                 // to be done only once;
1355                 if (!inNestedBinary) {
1356                     indentedExpression = true;
1357                     inNestedBinary = true;
1358                     Indent += 3;
1359                 }
1360                 ContinueOnNewLine("");
1361             }
1362  
1363             OutputOperator(e.Operator);
1364
1365             Output.Write(" ");
1366             GenerateExpression(e.Right);
1367
1368             Output.Write(")");
1369             if (indentedExpression) {
1370                 Indent -= 3;
1371                 inNestedBinary = false;
1372             }
1373         }
1374
1375         /// <devdoc>
1376         ///    <para>[To be supplied.]</para>
1377         /// </devdoc>
1378         protected virtual void ContinueOnNewLine(string st) {
1379             Output.WriteLine(st);
1380         }
1381
1382         /// <devdoc>
1383         ///    <para>
1384         ///       Generates code for the specified CodeDom based cast expression
1385         ///       representation.
1386         ///    </para>
1387         /// </devdoc>
1388         protected abstract void GenerateCastExpression(CodeCastExpression e);
1389         /// <devdoc>
1390         ///    <para>
1391         ///       Generates code for the specified CodeDom based delegate creation expression
1392         ///       representation.
1393         ///    </para>
1394         /// </devdoc>
1395         protected abstract void GenerateDelegateCreateExpression(CodeDelegateCreateExpression e);
1396         /// <devdoc>
1397         ///    <para>
1398         ///       Generates code for the specified CodeDom based field reference
1399         ///       expression representation.
1400         ///    </para>
1401         /// </devdoc>
1402         protected abstract void GenerateFieldReferenceExpression(CodeFieldReferenceExpression e);
1403
1404         /// <devdoc>
1405         ///    <para>[To be supplied.]</para>
1406         /// </devdoc>
1407         protected abstract void GenerateArgumentReferenceExpression(CodeArgumentReferenceExpression e);
1408
1409         /// <devdoc>
1410         ///    <para>[To be supplied.]</para>
1411         /// </devdoc>
1412         protected abstract void GenerateVariableReferenceExpression(CodeVariableReferenceExpression e);
1413         
1414         /// <devdoc>
1415         ///    <para>
1416         ///       Generates code for the specified CodeDom based indexer expression
1417         ///       representation.
1418         ///    </para>
1419         /// </devdoc>
1420         protected abstract void GenerateIndexerExpression(CodeIndexerExpression e);
1421
1422         /// <devdoc>
1423         ///    <para>[To be supplied.]</para>
1424         /// </devdoc>
1425         protected abstract void GenerateArrayIndexerExpression(CodeArrayIndexerExpression e);
1426
1427         /// <devdoc>
1428         ///    <para>
1429         ///       Generates code for the specified CodeDom based snippet
1430         ///       expression representation.
1431         ///    </para>
1432         /// </devdoc>
1433         protected abstract void GenerateSnippetExpression(CodeSnippetExpression e);
1434         /// <devdoc>
1435         ///    <para>
1436         ///       Generates code for the specified CodeDom based method invoke expression
1437         ///       representation.
1438         ///    </para>
1439         /// </devdoc>
1440         protected abstract void GenerateMethodInvokeExpression(CodeMethodInvokeExpression e);
1441
1442         /// <devdoc>
1443         ///    <para>[To be supplied.]</para>
1444         /// </devdoc>
1445         protected abstract void GenerateMethodReferenceExpression(CodeMethodReferenceExpression e);
1446
1447         /// <devdoc>
1448         ///    <para>[To be supplied.]</para>
1449         /// </devdoc>
1450         protected abstract void GenerateEventReferenceExpression(CodeEventReferenceExpression e);
1451
1452         /// <devdoc>
1453         ///    <para>
1454         ///       Generates code for the specified CodeDom based delegate invoke expression
1455         ///       representation.
1456         ///    </para>
1457         /// </devdoc>
1458         protected abstract void GenerateDelegateInvokeExpression(CodeDelegateInvokeExpression e);
1459         /// <devdoc>
1460         ///    <para>
1461         ///       Generates code for the specified CodeDom
1462         ///       based object creation expression representation.
1463         ///    </para>
1464         /// </devdoc>
1465         protected abstract void GenerateObjectCreateExpression(CodeObjectCreateExpression e);
1466
1467         /// <devdoc>
1468         ///    <para>
1469         ///       Generates code for the specified CodeDom
1470         ///       based parameter declaration expression representation.
1471         ///    </para>
1472         /// </devdoc>
1473         protected virtual void GenerateParameterDeclarationExpression(CodeParameterDeclarationExpression e) {
1474             if (e.CustomAttributes.Count > 0) {
1475                 OutputAttributeDeclarations(e.CustomAttributes);
1476                 Output.Write(" ");
1477             }
1478
1479             OutputDirection(e.Direction);
1480             OutputTypeNamePair(e.Type, e.Name);
1481         }
1482
1483         /// <devdoc>
1484         ///    <para>[To be supplied.]</para>
1485         /// </devdoc>
1486         protected virtual void GenerateDirectionExpression(CodeDirectionExpression e) {
1487             OutputDirection(e.Direction);
1488             GenerateExpression(e.Expression);
1489         }
1490
1491
1492         /// <devdoc>
1493         ///    <para>
1494         ///       Generates code for the specified CodeDom based primitive expression
1495         ///       representation.
1496         ///    </para>
1497         /// </devdoc>
1498         protected virtual void GeneratePrimitiveExpression(CodePrimitiveExpression e) {
1499             if (e.Value == null) {
1500                 Output.Write(NullToken);
1501             }
1502             else if (e.Value is string) {
1503                 Output.Write(QuoteSnippetString((string)e.Value));
1504             }
1505             else if (e.Value is char) {
1506                 Output.Write("'" + e.Value.ToString() + "'");
1507             }
1508             else if (e.Value is byte) {
1509                 Output.Write(((byte)e.Value).ToString(CultureInfo.InvariantCulture));
1510             }
1511             else if (e.Value is Int16) {
1512                 Output.Write(((Int16)e.Value).ToString(CultureInfo.InvariantCulture));
1513             }
1514             else if (e.Value is Int32) {
1515                 Output.Write(((Int32)e.Value).ToString(CultureInfo.InvariantCulture));
1516             }
1517             else if (e.Value is Int64) {
1518                 Output.Write(((Int64)e.Value).ToString(CultureInfo.InvariantCulture));
1519             }
1520             else if (e.Value is Single) {
1521                 GenerateSingleFloatValue((Single)e.Value);
1522             }
1523             else if (e.Value is Double) {
1524                 GenerateDoubleValue((Double)e.Value);
1525             }
1526             else if (e.Value is Decimal) {
1527                 GenerateDecimalValue((Decimal)e.Value);
1528             }
1529             else if (e.Value is bool) {
1530                 if ((bool)e.Value) {
1531                     Output.Write("true");
1532                 }
1533                 else {
1534                     Output.Write("false");
1535                 }
1536             }
1537             else {
1538                 throw new ArgumentException(SR.GetString(SR.InvalidPrimitiveType, e.Value.GetType().ToString()));
1539             }
1540         }
1541
1542         /// <devdoc>
1543         ///    <para>[To be supplied.]</para>
1544         /// </devdoc>
1545         protected virtual void GenerateSingleFloatValue(Single s) {
1546             Output.Write(s.ToString("R", CultureInfo.InvariantCulture));
1547         }
1548
1549         /// <devdoc>
1550         ///    <para>[To be supplied.]</para>
1551         /// </devdoc>
1552         protected virtual void GenerateDoubleValue(Double d) {
1553             Output.Write(d.ToString("R", CultureInfo.InvariantCulture));
1554         }
1555
1556         /// <devdoc>
1557         ///    <para>[To be supplied.]</para>
1558         /// </devdoc>
1559         protected virtual void GenerateDecimalValue(Decimal d) {
1560             Output.Write(d.ToString(CultureInfo.InvariantCulture));
1561         }
1562
1563         // 
1564         protected virtual void GenerateDefaultValueExpression(CodeDefaultValueExpression e) {
1565         }
1566
1567         /// <devdoc>
1568         ///    <para>
1569         ///       Generates code for the specified CodeDom based property reference
1570         ///       expression representation.
1571         ///    </para>
1572         /// </devdoc>
1573         protected abstract void GeneratePropertyReferenceExpression(CodePropertyReferenceExpression e);
1574
1575         /// <devdoc>
1576         ///    <para>[To be supplied.]</para>
1577         /// </devdoc>
1578         protected abstract void GeneratePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e);
1579
1580         /// <devdoc>
1581         ///    <para>
1582         ///       Generates code for the specified CodeDom based this reference expression
1583         ///       representation.
1584         ///    </para>
1585         /// </devdoc>
1586         protected abstract void GenerateThisReferenceExpression(CodeThisReferenceExpression e);
1587
1588         /// <devdoc>
1589         ///    <para>
1590         ///       Generates code for the specified CodeDom based type reference expression
1591         ///       representation.
1592         ///    </para>
1593         /// </devdoc>
1594         protected virtual void GenerateTypeReferenceExpression(CodeTypeReferenceExpression e) {
1595             OutputType(e.Type);
1596         }
1597
1598         /// <devdoc>
1599         ///    <para>
1600         ///       Generates code for the specified CodeDom based type of expression
1601         ///       representation.
1602         ///    </para>
1603         /// </devdoc>
1604         protected virtual void GenerateTypeOfExpression(CodeTypeOfExpression e) {
1605             Output.Write("typeof(");
1606             OutputType(e.Type);
1607             Output.Write(")");
1608         }
1609
1610         /// <devdoc>
1611         ///    <para>
1612         ///       Generates code for the specified CodeDom based method
1613         ///       invoke statement representation.
1614         ///    </para>
1615         /// </devdoc>
1616         protected abstract void GenerateExpressionStatement(CodeExpressionStatement e);
1617         /// <devdoc>
1618         ///    <para>
1619         ///       Generates code for the specified CodeDom based for loop statement
1620         ///       representation.
1621         ///    </para>
1622         /// </devdoc>
1623         protected abstract void GenerateIterationStatement(CodeIterationStatement e);
1624         /// <devdoc>
1625         ///    <para>
1626         ///       Generates code for the specified CodeDom based throw exception statement
1627         ///       representation.
1628         ///    </para>
1629         /// </devdoc>
1630         protected abstract void GenerateThrowExceptionStatement(CodeThrowExceptionStatement e);
1631         /// <devdoc>
1632         ///    <para>
1633         ///       Generates code for the specified CodeDom based comment statement
1634         ///       representation.
1635         ///    </para>
1636         /// </devdoc>
1637         protected virtual void GenerateCommentStatement(CodeCommentStatement e) {
1638             if(e.Comment == null)
1639                 throw new ArgumentException(SR.GetString(SR.Argument_NullComment, "e"), "e");
1640             GenerateComment(e.Comment);
1641         }
1642
1643         /// <devdoc>
1644         ///    <para>[To be supplied.]</para>
1645         /// </devdoc>
1646         protected virtual void GenerateCommentStatements(CodeCommentStatementCollection e) {
1647             foreach (CodeCommentStatement comment in e) {
1648                 GenerateCommentStatement(comment);
1649             }
1650         }
1651
1652         /// <devdoc>
1653         ///    <para>[To be supplied.]</para>
1654         /// </devdoc>
1655         protected abstract void GenerateComment(CodeComment e);
1656
1657         /// <devdoc>
1658         ///    <para>
1659         ///       Generates code for the specified CodeDom based method return statement
1660         ///       representation.
1661         ///    </para>
1662         /// </devdoc>
1663         protected abstract void GenerateMethodReturnStatement(CodeMethodReturnStatement e);
1664         /// <devdoc>
1665         ///    <para>
1666         ///       Generates code for the specified CodeDom based if statement representation.
1667         ///    </para>
1668         /// </devdoc>
1669         protected abstract void GenerateConditionStatement(CodeConditionStatement e);
1670         /// <devdoc>
1671         ///    <para>
1672         ///       Generates code for the specified CodeDom based try catch finally
1673         ///       statement representation.
1674         ///    </para>
1675         /// </devdoc>
1676         protected abstract void GenerateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e);
1677         /// <devdoc>
1678         ///    <para>
1679         ///       Generates code for the specified CodeDom based assignment statement
1680         ///       representation.
1681         ///    </para>
1682         /// </devdoc>
1683         protected abstract void GenerateAssignStatement(CodeAssignStatement e);
1684         /// <devdoc>
1685         ///    <para>
1686         ///       Generates code for the specified CodeDom based attach event statement
1687         ///       representation.
1688         ///    </para>
1689         /// </devdoc>
1690         protected abstract void GenerateAttachEventStatement(CodeAttachEventStatement e);
1691         /// <devdoc>
1692         ///    <para>
1693         ///       Generates code for the specified CodeDom based detach event statement
1694         ///       representation.
1695         ///    </para>
1696         /// </devdoc>
1697         protected abstract void GenerateRemoveEventStatement(CodeRemoveEventStatement e);
1698
1699         /// <devdoc>
1700         ///    <para>[To be supplied.]</para>
1701         /// </devdoc>
1702         protected abstract void GenerateGotoStatement(CodeGotoStatement e);
1703
1704         /// <devdoc>
1705         ///    <para>[To be supplied.]</para>
1706         /// </devdoc>
1707         protected abstract void GenerateLabeledStatement(CodeLabeledStatement e);
1708
1709         /// <devdoc>
1710         ///    <para>
1711         ///       Generates code for the specified CodeDom based snippet statement
1712         ///       representation.
1713         ///    </para>
1714         /// </devdoc>
1715         protected virtual void GenerateSnippetStatement(CodeSnippetStatement e) {
1716             Output.WriteLine(e.Value);
1717         }
1718
1719         /// <devdoc>
1720         ///    <para>
1721         ///       Generates code for the specified CodeDom based variable declaration statement
1722         ///       representation.
1723         ///    </para>
1724         /// </devdoc>
1725         protected abstract void GenerateVariableDeclarationStatement(CodeVariableDeclarationStatement e);
1726
1727         /// <devdoc>
1728         ///    <para>
1729         ///       Generates code for the specified CodeDom based line pragma start
1730         ///       representation.
1731         ///    </para>
1732         /// </devdoc>
1733         protected abstract void GenerateLinePragmaStart(CodeLinePragma e);
1734         /// <devdoc>
1735         ///    <para>
1736         ///       Generates code for the specified CodeDom based line pragma end
1737         ///       representation.
1738         ///    </para>
1739         /// </devdoc>
1740         protected abstract void GenerateLinePragmaEnd(CodeLinePragma e);
1741         /// <devdoc>
1742         ///    <para>
1743         ///       Generates code for the specified CodeDom based event
1744         ///       representation.
1745         ///    </para>
1746         /// </devdoc>
1747         protected abstract void GenerateEvent(CodeMemberEvent e, CodeTypeDeclaration c);
1748         /// <devdoc>
1749         ///    <para>
1750         ///       Generates code for the specified CodeDom based member field
1751         ///       representation.
1752         ///    </para>
1753         /// </devdoc>
1754         protected abstract void GenerateField(CodeMemberField e);
1755         /// <devdoc>
1756         ///    <para>
1757         ///       Generates code for the specified CodeDom based snippet class member
1758         ///       representation.
1759         ///    </para>
1760         /// </devdoc>
1761         protected abstract void GenerateSnippetMember(CodeSnippetTypeMember e);
1762
1763         /// <devdoc>
1764         ///    <para>[To be supplied.]</para>
1765         /// </devdoc>
1766         protected abstract void GenerateEntryPointMethod(CodeEntryPointMethod e, CodeTypeDeclaration c);
1767
1768         /// <devdoc>
1769         ///    <para>
1770         ///       Generates code for the specified CodeDom based method
1771         ///       representation.
1772         ///    </para>
1773         /// </devdoc>
1774         protected abstract void GenerateMethod(CodeMemberMethod e, CodeTypeDeclaration c);
1775         /// <devdoc>
1776         ///    <para>
1777         ///       Generates code for the specified CodeDom based property
1778         ///       representation.
1779         ///    </para>
1780         /// </devdoc>
1781         protected abstract void GenerateProperty(CodeMemberProperty e, CodeTypeDeclaration c);
1782         /// <devdoc>
1783         ///    <para>
1784         ///       Generates code for the specified CodeDom based constructor
1785         ///       representation.
1786         ///    </para>
1787         /// </devdoc>
1788         protected abstract void GenerateConstructor(CodeConstructor e, CodeTypeDeclaration c);
1789         /// <devdoc>
1790         ///    <para>
1791         ///       Generates code for the specified CodeDom based class constructor
1792         ///       representation.
1793         ///    </para>
1794         /// </devdoc>
1795         protected abstract void GenerateTypeConstructor(CodeTypeConstructor e);
1796         /// <devdoc>
1797         ///    <para>
1798         ///       Generates code for the specified CodeDom based start class representation.
1799         ///    </para>
1800         /// </devdoc>
1801         protected abstract void GenerateTypeStart(CodeTypeDeclaration e);
1802         /// <devdoc>
1803         ///    <para>
1804         ///       Generates code for the specified CodeDom based end class representation.
1805         ///    </para>
1806         /// </devdoc>
1807         protected abstract void GenerateTypeEnd(CodeTypeDeclaration e);
1808         /// <devdoc>
1809         ///    <para>
1810         ///       Generates code for the specified CodeDom based compile unit start
1811         ///       representation.
1812         ///    </para>
1813         /// </devdoc>
1814         protected virtual void GenerateCompileUnitStart(CodeCompileUnit e) {
1815             if (e.StartDirectives.Count > 0) {
1816                 GenerateDirectives(e.StartDirectives);
1817             }
1818         }
1819         /// <devdoc>
1820         ///    <para>
1821         ///       Generates code for the specified CodeDom based compile unit end
1822         ///       representation.
1823         ///    </para>
1824         /// </devdoc>
1825         protected virtual void GenerateCompileUnitEnd(CodeCompileUnit e) {
1826             if (e.EndDirectives.Count > 0) {
1827                 GenerateDirectives(e.EndDirectives);
1828             }
1829         }
1830          /// <devdoc>
1831         ///    <para>
1832         ///       Generates code for the specified CodeDom based namespace start
1833         ///       representation.
1834         ///    </para>
1835         /// </devdoc>
1836         protected abstract void GenerateNamespaceStart(CodeNamespace e);
1837         /// <devdoc>
1838         ///    <para>
1839         ///       Generates code for the specified CodeDom based namespace end
1840         ///       representation.
1841         ///    </para>
1842         /// </devdoc>
1843         protected abstract void GenerateNamespaceEnd(CodeNamespace e);
1844         /// <devdoc>
1845         ///    <para>
1846         ///       Generates code for the specified CodeDom based namespace import
1847         ///       representation.
1848         ///    </para>
1849         /// </devdoc>
1850         protected abstract void GenerateNamespaceImport(CodeNamespaceImport e);
1851         /// <devdoc>
1852         ///    <para>
1853         ///       Generates code for the specified CodeDom based attribute block start
1854         ///       representation.
1855         ///    </para>
1856         /// </devdoc>
1857         protected abstract void GenerateAttributeDeclarationsStart(CodeAttributeDeclarationCollection attributes);
1858         /// <devdoc>
1859         ///    <para>
1860         ///       Generates code for the specified CodeDom based attribute block end
1861         ///       representation.
1862         ///    </para>
1863         /// </devdoc>
1864         protected abstract void GenerateAttributeDeclarationsEnd(CodeAttributeDeclarationCollection attributes);
1865
1866         /// <devdoc>
1867         ///    <para>[To be supplied.]</para>
1868         /// </devdoc>
1869         protected abstract bool Supports(GeneratorSupport support);
1870
1871         /// <devdoc>
1872         ///    <para>
1873         ///       Gets or sets whether the specified value is a value identifier.
1874         ///    </para>
1875         /// </devdoc>
1876         protected abstract bool IsValidIdentifier(string value);
1877         /// <devdoc>
1878         ///    <para>
1879         ///       Gets whether the specified identifier is valid.
1880         ///    </para>
1881         /// </devdoc>
1882         protected virtual void ValidateIdentifier(string value) {
1883             if (!IsValidIdentifier(value)) {
1884                 throw new ArgumentException(SR.GetString(SR.InvalidIdentifier, value));
1885             }
1886         }
1887
1888         /// <devdoc>
1889         ///    <para>[To be supplied.]</para>
1890         /// </devdoc>
1891         protected abstract string CreateEscapedIdentifier(string value);
1892
1893         /// <devdoc>
1894         ///    <para>[To be supplied.]</para>
1895         /// </devdoc>
1896         protected abstract string CreateValidIdentifier(string value);
1897
1898         /// <devdoc>
1899         ///    <para>[To be supplied.]</para>
1900         /// </devdoc>
1901         protected abstract string GetTypeOutput(CodeTypeReference value);
1902
1903         /// <devdoc>
1904         ///    <para>
1905         ///       Provides conversion to formatting with escape codes.
1906         ///    </para>
1907         /// </devdoc>
1908         protected abstract string QuoteSnippetString(string value);
1909
1910         /// <devdoc>
1911         ///    <para>
1912         ///       Gets a value indicating whether the specified value is a valid language
1913         ///       independent identifier.
1914         ///    </para>
1915         /// </devdoc>
1916         public static bool IsValidLanguageIndependentIdentifier(string value)
1917         {
1918             return IsValidTypeNameOrIdentifier(value, false);
1919         }
1920
1921         internal static bool IsValidLanguageIndependentTypeName(string value)
1922         {
1923             return IsValidTypeNameOrIdentifier(value, true);
1924         }
1925
1926         private static bool IsValidTypeNameOrIdentifier(string value, bool isTypeName) {
1927             bool nextMustBeStartChar = true;
1928             
1929             if (value.Length == 0) 
1930                 return false;
1931
1932             // each char must be Lu, Ll, Lt, Lm, Lo, Nd, Mn, Mc, Pc
1933             // 
1934             for(int i = 0; i < value.Length; i++) {
1935                 char ch = value[i];
1936                 UnicodeCategory uc = Char.GetUnicodeCategory(ch);
1937                 switch (uc) {
1938                     case UnicodeCategory.UppercaseLetter:        // Lu
1939                     case UnicodeCategory.LowercaseLetter:        // Ll
1940                     case UnicodeCategory.TitlecaseLetter:        // Lt
1941                     case UnicodeCategory.ModifierLetter:         // Lm
1942                     case UnicodeCategory.LetterNumber:           // Lm
1943                     case UnicodeCategory.OtherLetter:            // Lo
1944                         nextMustBeStartChar = false;
1945                         break;
1946
1947                     case UnicodeCategory.NonSpacingMark:         // Mn
1948                     case UnicodeCategory.SpacingCombiningMark:   // Mc
1949                     case UnicodeCategory.ConnectorPunctuation:   // Pc
1950                     case UnicodeCategory.DecimalDigitNumber:     // Nd
1951                         // Underscore is a valid starting character, even though it is a ConnectorPunctuation.
1952                         if (nextMustBeStartChar && ch != '_')
1953                             return false;
1954                         
1955                         nextMustBeStartChar = false;
1956                         break;
1957                     default:
1958                         // We only check the special Type chars for type names. 
1959                         if (isTypeName && IsSpecialTypeChar(ch, ref nextMustBeStartChar)) {
1960                             break;
1961                         }
1962
1963                         return false;
1964                 }
1965             }
1966
1967             return true;
1968         }
1969
1970         // This can be a special character like a separator that shows up in a type name
1971         // This is an odd set of characters.  Some come from characters that are allowed by C++, like < and >.
1972         // Others are characters that are specified in the type and assembly name grammer. 
1973         private static bool IsSpecialTypeChar(char ch, ref bool nextMustBeStartChar) {
1974             switch(ch) {
1975                 case ':':
1976                 case '.':
1977                 case '$':
1978                 case '+':
1979                 case '<':
1980                 case '>':
1981                 case '-':
1982                 case '[':
1983                 case ']':
1984                 case ',':
1985                 case '&':
1986                 case '*':
1987                     nextMustBeStartChar = true;
1988                     return true;
1989
1990                 case '`':
1991                     return true;
1992             }
1993             return false;
1994         }
1995
1996         /// <devdoc>
1997         ///    <para>
1998         ///       Validates a tree to check if all the types and idenfier names follow the rules of an identifier
1999         ///       in a langauge independent manner.
2000         ///    </para>
2001         /// </devdoc>
2002         public static void ValidateIdentifiers(CodeObject e) {
2003             CodeValidator codeValidator = new CodeValidator(); // This has internal state and hence is not static
2004             codeValidator.ValidateIdentifiers(e);
2005         }
2006
2007     }
2008 }