2008-04-08 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System / Microsoft.CSharp / CSharpCodeGenerator.cs
1 //
2 // Mono.CSharp CSharpCodeProvider Class implementation
3 //
4 // Author:
5 //   Daniel Stodden (stodden@in.tum.de)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // (C) 2002 Ximian, Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 namespace Mono.CSharp
33 {
34         using System;
35         using System.CodeDom;
36         using System.CodeDom.Compiler;
37         using System.Globalization;
38         using System.IO;
39         using System.Reflection;
40         using System.Collections;
41         using System.Text;
42
43 #if NET_2_0
44         using System.Collections.Generic;
45 #endif
46         
47         internal class CSharpCodeGenerator
48                 : CodeGenerator
49         {
50 #if NET_2_0
51                 Dictionary <string, string> providerOptions;
52 #endif
53                 
54                 // It is used for beautiful "for" syntax
55                 bool dont_write_semicolon;
56
57                 //
58                 // Constructors
59                 //
60                 public CSharpCodeGenerator()
61                 {
62                         dont_write_semicolon = false;
63                 }
64
65 #if NET_2_0
66                 public CSharpCodeGenerator (Dictionary <string, string> providerOptions)
67                 {
68                         this.providerOptions = providerOptions;
69                 }
70
71                 protected Dictionary <string, string> ProviderOptions {
72                         get { return providerOptions; }
73                 }
74 #endif
75                 
76                 //
77                 // Properties
78                 //
79                 protected override string NullToken {
80                         get {
81                                 return "null";
82                         }
83                 }
84
85                 //
86                 // Methods
87                 //
88
89                 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
90                 {
91                         //
92                         // This tries to replicate MS behavior as good as
93                         // possible.
94                         //
95                         // The Code-Array stuff in ms.net seems to be broken
96                         // anyways, or I'm too stupid to understand it.
97                         //
98                         // I'm sick of it. If you try to develop array
99                         // creations, test them on windows. If it works there
100                         // but not in mono, drop me a note.  I'd be especially
101                         // interested in jagged-multidimensional combinations
102                         // with proper initialization :}
103                         //
104
105                         TextWriter output = Output;
106
107                         output.Write ("new ");
108
109                         CodeExpressionCollection initializers = expression.Initializers;
110                         CodeTypeReference createType = expression.CreateType;
111
112                         if (initializers.Count > 0) {
113
114                                 OutputType (createType);
115
116                                 if (expression.CreateType.ArrayRank == 0) {
117                                         output.Write ("[]");
118                                 }
119
120                                 OutputStartBrace ();
121                                 ++Indent;
122                                 OutputExpressionList (initializers, true);
123                                 --Indent;
124                                 output.Write ("}");
125                         } else {
126                                 CodeTypeReference arrayType = createType.ArrayElementType;
127                                 while (arrayType != null) {
128                                         createType = arrayType;
129                                         arrayType = arrayType.ArrayElementType;
130                                 }
131
132                                 OutputType (createType);
133
134                                 output.Write ('[');
135
136                                 CodeExpression size = expression.SizeExpression;
137                                 if (size != null)
138                                         GenerateExpression (size);
139                                 else
140                                         output.Write (expression.Size);
141
142                                 output.Write(']');
143                         }
144                 }
145                 
146                 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
147                 {
148                         Output.Write ("base");
149                 }
150                 
151                 protected override void GenerateCastExpression (CodeCastExpression expression)
152                 {
153                         TextWriter output = Output;
154                         output.Write ("((");
155                         OutputType (expression.TargetType);
156                         output.Write (")(");
157                         GenerateExpression (expression.Expression);
158                         output.Write ("))");
159                 }
160
161
162                 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
163                 {
164                         GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
165                         GenerateComment (new CodeComment (" <autogenerated>"));
166                         GenerateComment (new CodeComment ("     This code was generated by a tool."));
167                         GenerateComment (new CodeComment ("     Mono Runtime Version: " +  System.Environment.Version));
168                         GenerateComment (new CodeComment (""));
169                         GenerateComment (new CodeComment ("     Changes to this file may cause incorrect behavior and will be lost if "));
170                         GenerateComment (new CodeComment ("     the code is regenerated."));
171                         GenerateComment (new CodeComment (" </autogenerated>"));
172                         GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
173                         Output.WriteLine ();
174                         base.GenerateCompileUnitStart (compileUnit);
175                 }
176
177                 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
178                 {
179                         GenerateCompileUnitStart (compileUnit);
180
181                         if (compileUnit.AssemblyCustomAttributes.Count > 0) {
182                                 OutputAttributes (compileUnit.AssemblyCustomAttributes, 
183                                         "assembly: ", false);
184                                 Output.WriteLine ("");
185                         }
186
187                         foreach (CodeNamespace ns in compileUnit.Namespaces)
188                                 GenerateNamespace (ns);
189
190                         GenerateCompileUnitEnd (compileUnit);
191                 }
192
193                 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
194                 {
195                         TextWriter output = Output;
196
197                         output.Write ("new ");
198                         OutputType (expression.DelegateType);
199                         output.Write ('(');
200
201                         CodeExpression targetObject = expression.TargetObject;
202                         if (targetObject != null) {
203                                 GenerateExpression (targetObject);
204                                 Output.Write ('.');
205                         }
206                         output.Write (GetSafeName (expression.MethodName));
207
208                         output.Write (')');
209                 }
210
211                 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
212                 {
213                         CodeExpression targetObject = expression.TargetObject;
214                         if (targetObject != null) {
215                                 GenerateExpression (targetObject);
216                                 Output.Write ('.');
217                         }
218                         Output.Write (GetSafeName (expression.FieldName));
219                 }
220                 
221                 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
222                 {
223                         Output.Write (GetSafeName (expression.ParameterName));
224                 }
225
226                 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
227                 {
228                         Output.Write (GetSafeName (expression.VariableName));
229                 }
230                         
231                 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
232                 {
233                         TextWriter output = Output;
234
235                         GenerateExpression (expression.TargetObject);
236                         output.Write ('[');
237                         OutputExpressionList (expression.Indices);
238                         output.Write (']');
239                 }
240                 
241                 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
242                 {
243                         TextWriter output = Output;
244
245                         GenerateExpression (expression.TargetObject);
246                         output.Write ('[');
247                         OutputExpressionList (expression.Indices);
248                         output.Write (']');
249                 }
250                 
251                 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
252                 {
253                         Output.Write (expression.Value);
254                 }
255                 
256                 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
257                 {
258                         TextWriter output = Output;
259
260                         GenerateMethodReferenceExpression (expression.Method);
261
262                         output.Write ('(');
263                         OutputExpressionList (expression.Parameters);
264                         output.Write (')');
265                 }
266
267                 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
268                 {
269                         if (expression.TargetObject != null)
270                         {
271                                 GenerateExpression (expression.TargetObject);
272                                 Output.Write ('.');
273                         };
274                         Output.Write (GetSafeName (expression.MethodName));
275 #if NET_2_0
276                         if (expression.TypeArguments.Count > 0)
277                                 Output.Write (GetTypeArguments (expression.TypeArguments));
278 #endif
279                 }
280
281                 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
282                 {
283                         if (expression.TargetObject != null) {
284                                 GenerateExpression (expression.TargetObject);
285                                 Output.Write ('.');
286                         }
287                         Output.Write (GetSafeName (expression.EventName));
288                 }
289
290                 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
291                 {
292                         if (expression.TargetObject != null)
293                                 GenerateExpression (expression.TargetObject);
294                         Output.Write ('(');
295                         OutputExpressionList (expression.Parameters);
296                         Output.Write (')');
297                 }
298                 
299                 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
300                 {
301                         Output.Write ("new ");
302                         OutputType (expression.CreateType);
303                         Output.Write ('(');
304                         OutputExpressionList (expression.Parameters);
305                         Output.Write (')');
306                 }
307
308                 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
309                 {
310                         CodeExpression targetObject = expression.TargetObject;
311                         if (targetObject != null) {
312                                 GenerateExpression (targetObject);
313                                 Output.Write ('.');
314                         }
315                         Output.Write (GetSafeName (expression.PropertyName ));
316                 }
317
318                 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
319                 {
320                         Output.Write ("value");
321                 }
322
323                 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
324                 {
325                         Output.Write ("this");
326                 }
327
328                 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
329                 {
330                         GenerateExpression (statement.Expression);
331                         if (dont_write_semicolon)
332                                 return;
333                         Output.WriteLine(';');
334                 }
335
336                 protected override void GenerateIterationStatement (CodeIterationStatement statement)
337                 {
338                         TextWriter output = Output;
339
340                         dont_write_semicolon = true;
341                         output.Write ("for (");
342                         GenerateStatement (statement.InitStatement);
343                         output.Write ("; ");
344                         GenerateExpression (statement.TestExpression);
345                         output.Write ("; ");
346                         GenerateStatement (statement.IncrementStatement);
347                         output.Write (")");
348                         dont_write_semicolon = false;
349                         OutputStartBrace ();
350                         ++Indent;
351                         GenerateStatements (statement.Statements);
352                         --Indent;
353                         output.WriteLine ('}');
354                 }
355
356                 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
357                 {
358                         Output.Write ("throw");
359                         if (statement.ToThrow != null) {
360                                 Output.Write (' ');
361                                 GenerateExpression (statement.ToThrow);
362                         }
363                         Output.WriteLine (";");
364                 }
365
366                 protected override void GenerateComment (CodeComment comment)
367                 {
368                         TextWriter output = Output;
369
370                         string commentChars = null;
371
372                         if (comment.DocComment) {
373                                 commentChars = "///";
374                         } else {
375                                 commentChars = "//";
376                         }
377
378                         output.Write (commentChars);
379                         output.Write (' ');
380                         string text = comment.Text;
381
382                         for (int i = 0; i < text.Length; i++) {
383                                 output.Write (text[i]);
384                                 if (text[i] == '\r') {
385                                         if (i < (text.Length - 1) && text[i + 1] == '\n') {
386                                                 continue;
387                                         }
388                                         output.Write (commentChars);
389                                 } else if (text[i] == '\n') {
390                                         output.Write (commentChars);
391                                 }
392                         }
393
394                         output.WriteLine ();
395                 }
396
397                 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
398                 {
399                         TextWriter output = Output;
400
401                         if (statement.Expression != null) {
402                                 output.Write ("return ");
403                                 GenerateExpression (statement.Expression);
404                                 output.WriteLine (";");
405                         } else {
406                                 output.WriteLine ("return;");
407                         }
408                 }
409
410                 protected override void GenerateConditionStatement (CodeConditionStatement statement)
411                 {
412                         TextWriter output = Output;
413                         output.Write ("if (");
414                         GenerateExpression (statement.Condition);
415                         output.Write (")");
416                         OutputStartBrace ();
417
418                         ++Indent;
419                         GenerateStatements (statement.TrueStatements);
420                         --Indent;
421
422                         CodeStatementCollection falses = statement.FalseStatements;
423                         if (falses.Count > 0) {
424                                 output.Write ('}');
425                                 if (Options.ElseOnClosing)
426                                         output.Write (' ');
427                                 else
428                                         output.WriteLine ();
429                                 output.Write ("else");
430                                 OutputStartBrace ();
431                                 ++Indent;
432                                 GenerateStatements (falses);
433                                 --Indent;
434                         }
435                         output.WriteLine ('}');
436                 }
437
438                 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
439                 {
440                         TextWriter output = Output;
441                         CodeGeneratorOptions options = Options;
442
443                         output.Write ("try");
444                         OutputStartBrace ();
445                         ++Indent;
446                         GenerateStatements (statement.TryStatements);
447                         --Indent;
448                         
449                         foreach (CodeCatchClause clause in statement.CatchClauses) {
450                                 output.Write ('}');
451                                 if (options.ElseOnClosing)
452                                         output.Write (' ');
453                                 else
454                                         output.WriteLine ();
455                                 output.Write ("catch (");
456                                 OutputTypeNamePair (clause.CatchExceptionType, GetSafeName(clause.LocalName));
457                                 output.Write (")");
458                                 OutputStartBrace ();
459                                 ++Indent;
460                                 GenerateStatements (clause.Statements);
461                                 --Indent;
462                         }
463
464                         CodeStatementCollection finallies = statement.FinallyStatements;
465                         if (finallies.Count > 0) {
466                                 output.Write ('}');
467                                 if (options.ElseOnClosing)
468                                         output.Write (' ');
469                                 else
470                                         output.WriteLine ();
471                                 output.Write ("finally");
472                                 OutputStartBrace ();
473                                 ++Indent;
474                                 GenerateStatements (finallies);
475                                 --Indent;
476                         }
477
478                         output.WriteLine('}');
479                 }
480
481                 protected override void GenerateAssignStatement (CodeAssignStatement statement)
482                 {
483                         TextWriter output = Output;
484                         GenerateExpression (statement.Left);
485                         output.Write (" = ");
486                         GenerateExpression (statement.Right);
487                         if (dont_write_semicolon)
488                                 return;
489                         output.WriteLine (';');
490                 }
491
492                 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
493                 {
494                         TextWriter output = Output;
495
496                         GenerateEventReferenceExpression (statement.Event);
497                         output.Write (" += ");
498                         GenerateExpression (statement.Listener);
499                         output.WriteLine (';');
500                 }
501
502                 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
503                 {
504                         TextWriter output = Output;
505                         GenerateEventReferenceExpression (statement.Event);
506                         output.Write (" -= ");
507                         GenerateExpression (statement.Listener);
508                         output.WriteLine (';');
509                 }
510
511                 protected override void GenerateGotoStatement (CodeGotoStatement statement)
512                 {
513                         TextWriter output = Output;
514
515                         output.Write ("goto ");
516                         output.Write (GetSafeName (statement.Label));
517                         output.WriteLine (";");
518                 }
519                 
520                 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
521                 {
522                         Indent--;
523                         Output.Write (statement.Label);
524                         Output.WriteLine (":");
525                         Indent++;
526
527                         if (statement.Statement != null) {
528                                 GenerateStatement (statement.Statement);
529                         }
530                 }
531
532                 protected override void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement statement)
533                 {
534                         TextWriter output = Output;
535
536                         OutputTypeNamePair (statement.Type, GetSafeName (statement.Name));
537
538                         CodeExpression initExpression = statement.InitExpression;
539                         if (initExpression != null) {
540                                 output.Write (" = ");
541                                 GenerateExpression (initExpression);
542                         }
543
544                         if (!dont_write_semicolon) {
545                                 output.WriteLine (';');
546                         }
547                 }
548
549                 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
550                 {
551                         Output.WriteLine ();
552                         Output.Write ("#line ");
553                         Output.Write (linePragma.LineNumber);
554                         Output.Write (" \"");
555                         Output.Write (linePragma.FileName);
556                         Output.Write ("\"");
557                         Output.WriteLine ();
558                 }
559
560                 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
561                 {
562                         Output.WriteLine ();
563                         Output.WriteLine ("#line default");
564                 }
565
566                 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
567                 {
568                         if (IsCurrentDelegate || IsCurrentEnum) {
569                                 return;
570                         }
571
572                         OutputAttributes (eventRef.CustomAttributes, null, false);
573
574                         if (eventRef.PrivateImplementationType == null) {
575                                 OutputMemberAccessModifier (eventRef.Attributes);
576                         }
577
578                         Output.Write ("event ");
579
580                         if (eventRef.PrivateImplementationType != null) {
581                                 OutputTypeNamePair (eventRef.Type,
582                                         eventRef.PrivateImplementationType.BaseType + "." + 
583                                         eventRef.Name);
584                         } else {
585                                 OutputTypeNamePair (eventRef.Type, GetSafeName (eventRef.Name));
586                         }
587                         Output.WriteLine (';');
588                 }
589
590                 protected override void GenerateField (CodeMemberField field)
591                 {
592                         if (IsCurrentDelegate || IsCurrentInterface) {
593                                 return;
594                         }
595
596                         TextWriter output = Output;
597
598                         OutputAttributes (field.CustomAttributes, null, false);
599
600                         if (IsCurrentEnum) {
601                                 Output.Write (GetSafeName (field.Name));
602                         } else {
603                                 MemberAttributes attributes = field.Attributes;
604                                 OutputMemberAccessModifier (attributes);
605                                 OutputVTableModifier (attributes);
606                                 OutputFieldScopeModifier (attributes);
607
608                                 OutputTypeNamePair (field.Type, GetSafeName (field.Name));
609                         }
610
611                         CodeExpression initExpression = field.InitExpression;
612                         if (initExpression != null) {
613                                 output.Write (" = ");
614                                 GenerateExpression (initExpression);
615                         }
616
617                         if (IsCurrentEnum)
618                                 output.WriteLine (',');
619                         else
620                                 output.WriteLine (';');
621                 }
622                 
623                 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
624                 {
625                         Output.Write (member.Text);
626                 }
627                 
628                 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, 
629                                                                   CodeTypeDeclaration declaration)
630                 {
631 #if NET_2_0
632                         OutputAttributes (method.CustomAttributes, null, false);
633 #endif
634
635                         Output.Write ("public static ");
636 #if NET_2_0
637                         OutputType (method.ReturnType);
638 #else
639                         Output.Write ("void");
640 #endif
641                         Output.Write (" Main()");
642                         OutputStartBrace ();
643                         Indent++;
644                         GenerateStatements (method.Statements);
645                         Indent--;
646                         Output.WriteLine ("}");
647                 }
648                 
649                 protected override void GenerateMethod (CodeMemberMethod method,
650                                                         CodeTypeDeclaration declaration)
651                 {
652                         if (IsCurrentDelegate || IsCurrentEnum) {
653                                 return;
654                         }
655
656                         TextWriter output = Output;
657
658                         OutputAttributes (method.CustomAttributes, null, false);
659
660                         OutputAttributes (method.ReturnTypeCustomAttributes, 
661                                 "return: ", false);
662
663                         MemberAttributes attributes = method.Attributes;
664
665                         if (!IsCurrentInterface) {
666                                 if (method.PrivateImplementationType == null) {
667                                         OutputMemberAccessModifier (attributes);
668                                         OutputVTableModifier (attributes);
669                                         OutputMemberScopeModifier (attributes);
670                                 }
671                         } else {
672                                 OutputVTableModifier (attributes);
673                         }
674
675                         OutputType (method.ReturnType);
676                         output.Write (' ');
677
678                         CodeTypeReference privateType = method.PrivateImplementationType;
679                         if (privateType != null) {
680                                 output.Write (privateType.BaseType);
681                                 output.Write ('.');
682                         }
683                         output.Write (GetSafeName (method.Name));
684
685 #if NET_2_0
686                         GenerateGenericsParameters (method.TypeParameters);
687 #endif
688
689                         output.Write ('(');
690                         OutputParameters (method.Parameters);
691                         output.Write (')');
692
693 #if NET_2_0
694                         GenerateGenericsConstraints (method.TypeParameters);
695 #endif
696
697                         if ((attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract || declaration.IsInterface)
698                                 output.WriteLine (';');
699                         else {
700                                 OutputStartBrace ();
701                                 ++Indent;
702                                 GenerateStatements (method.Statements);
703                                 --Indent;
704                                 output.WriteLine ('}');
705                         }
706                 }
707
708                 static bool IsAbstract (MemberAttributes attributes)
709                 {
710                         return (attributes & MemberAttributes.Abstract) == MemberAttributes.Abstract;
711                 }
712
713                 protected override void GenerateProperty (CodeMemberProperty property,
714                                                           CodeTypeDeclaration declaration)
715                 {
716                         if (IsCurrentDelegate || IsCurrentEnum) {
717                                 return;
718                         }
719
720                         TextWriter output = Output;
721
722                         OutputAttributes (property.CustomAttributes, null, false);
723
724                         MemberAttributes attributes = property.Attributes;
725
726                         if (!IsCurrentInterface) {
727                                 if (property.PrivateImplementationType == null) {
728                                         OutputMemberAccessModifier (attributes);
729                                         OutputVTableModifier (attributes);
730                                         OutputMemberScopeModifier (attributes);
731                                 }
732                         } else {
733                                 OutputVTableModifier (attributes);
734                         }
735
736                         OutputType (property.Type);
737                         output.Write (' ');
738
739                         if (!IsCurrentInterface && property.PrivateImplementationType != null) {
740                                 output.Write (property.PrivateImplementationType.BaseType);
741                                 output.Write ('.');
742                         }
743
744                         // only consider property indexer if name is Item (case-insensitive 
745                         // comparison) AND property has parameters
746                         if (string.Compare(property.Name, "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
747                                 output.Write ("this[");
748                                 OutputParameters(property.Parameters);
749                                 output.Write(']');
750                         } else {
751                                 output.Write (GetSafeName (property.Name));
752                         }
753                         OutputStartBrace ();
754                         ++Indent;
755
756                         if (declaration.IsInterface || IsAbstract (property.Attributes))
757                         {
758                                 if (property.HasGet) output.WriteLine("get;");
759                                 if (property.HasSet) output.WriteLine("set;");
760                         }
761                         else
762                         {
763                                 if (property.HasGet)
764                                 {
765                                         output.Write ("get");
766                                         OutputStartBrace ();
767                                         ++Indent;
768
769                                         GenerateStatements (property.GetStatements);
770
771                                         --Indent;
772                                         output.WriteLine ('}');
773                                 }
774
775                                 if (property.HasSet)
776                                 {
777                                         output.Write ("set");
778                                         OutputStartBrace ();
779                                         ++Indent;
780
781                                         GenerateStatements (property.SetStatements);
782
783                                         --Indent;
784                                         output.WriteLine ('}');
785                                 }
786                         }
787
788                         --Indent;
789                         output.WriteLine ('}');
790                 }
791
792                 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
793                 {
794                         if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
795                                 return;
796                         }
797
798                         OutputAttributes (constructor.CustomAttributes, null, false);
799
800                         OutputMemberAccessModifier (constructor.Attributes);
801                         Output.Write (GetSafeName (CurrentTypeName) + "(");
802                         OutputParameters (constructor.Parameters);
803                         Output.Write (")");
804                         if (constructor.BaseConstructorArgs.Count > 0) {
805                                 Output.WriteLine (" : ");
806                                 Indent += 2;
807                                 Output.Write ("base(");
808                                 OutputExpressionList (constructor.BaseConstructorArgs);
809                                 Output.Write (')');
810                                 Indent -= 2;
811                         }
812                         if (constructor.ChainedConstructorArgs.Count > 0) {
813                                 Output.WriteLine (" : ");
814                                 Indent += 2;
815                                 Output.Write("this(");
816                                 OutputExpressionList (constructor.ChainedConstructorArgs);
817                                 Output.Write(')');
818                                 Indent -= 2;
819                         }
820                         OutputStartBrace ();
821                         Indent++;
822                         GenerateStatements (constructor.Statements);
823                         Indent--;
824                         Output.WriteLine ('}');
825                 }
826
827                 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
828                 {
829                         if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
830                                 return;
831                         }
832
833 #if NET_2_0
834                         OutputAttributes (constructor.CustomAttributes, null, false);
835 #endif
836
837                         Output.Write ("static " + GetSafeName (CurrentTypeName) + "()");
838                         OutputStartBrace ();
839                         Indent++;
840                         GenerateStatements (constructor.Statements);
841                         Indent--;
842                         Output.WriteLine ('}');
843                 }
844
845                 protected override void GenerateTypeStart(CodeTypeDeclaration declaration)
846                 {
847                         TextWriter output = Output;
848
849                         OutputAttributes (declaration.CustomAttributes, null, false);
850
851                         if (!IsCurrentDelegate) {
852                                 OutputTypeAttributes (declaration);
853
854                                 output.Write (GetSafeName (declaration.Name));
855
856 #if NET_2_0
857                                 GenerateGenericsParameters (declaration.TypeParameters);
858 #endif
859
860                                 IEnumerator enumerator = declaration.BaseTypes.GetEnumerator ();
861                                 if (enumerator.MoveNext ()) {
862                                         CodeTypeReference type = (CodeTypeReference) enumerator.Current;
863
864                                         output.Write (" : ");
865                                         OutputType (type);
866
867                                         while (enumerator.MoveNext ()) {
868                                                 type = (CodeTypeReference) enumerator.Current;
869
870                                                 output.Write (", ");
871                                                 OutputType (type);
872                                         }
873                                 }
874
875 #if NET_2_0
876                                 GenerateGenericsConstraints (declaration.TypeParameters);
877 #endif
878                                 OutputStartBrace ();
879                                 ++Indent;
880                         } else {
881                                 if ((declaration.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
882                                         output.Write ("public ");
883                                 }
884
885                                 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
886                                 output.Write ("delegate ");
887                                 OutputType (delegateDecl.ReturnType);
888                                 output.Write (" ");
889                                 output.Write (GetSafeName (declaration.Name));
890                                 output.Write ("(");
891                                 OutputParameters (delegateDecl.Parameters);
892                                 output.WriteLine (");");
893                         }
894                 }
895
896                 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
897                 {
898                         if (!IsCurrentDelegate) {
899                                 --Indent;
900                                 Output.WriteLine ("}");
901                         }
902                 }
903
904                 protected override void GenerateNamespaceStart (CodeNamespace ns)
905                 {
906                         TextWriter output = Output;
907                         
908                         string name = ns.Name;
909                         if (name != null && name.Length != 0) {
910                                 output.Write ("namespace ");
911                                 output.Write (GetSafeName (name));
912                                 OutputStartBrace ();
913                                 ++Indent;
914                         }
915                 }
916
917                 protected override void GenerateNamespaceEnd (CodeNamespace ns)
918                 {
919                         string name = ns.Name;
920                         if (name != null && name.Length != 0) {
921                                 --Indent;
922                                 Output.WriteLine ("}");
923                         }
924                 }
925
926                 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
927                 {
928                         TextWriter output = Output;
929
930                         output.Write ("using ");
931                         output.Write (GetSafeName (import.Namespace));
932                         output.WriteLine (';');
933                 }
934                 
935                 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
936                 {
937                         Output.Write ('[');
938                 }
939                 
940                 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
941                 {
942                         Output.Write (']');
943                 }
944
945                 private void OutputStartBrace ()
946                 {
947                         if (Options.BracingStyle == "C") {
948                                 Output.WriteLine ("");
949                                 Output.WriteLine ("{");
950                         } else {
951                                 Output.WriteLine (" {");
952                         }
953                 }
954
955                 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, bool inline)
956                 {
957                         foreach (CodeAttributeDeclaration att in attributes) {
958                                 GenerateAttributeDeclarationsStart (attributes);
959                                 if (prefix != null) {
960                                         Output.Write (prefix);
961                                 }
962                                 OutputAttributeDeclaration (att);
963                                 GenerateAttributeDeclarationsEnd (attributes);
964                                 if (inline) {
965                                         Output.Write (" ");
966                                 } else {
967                                         Output.WriteLine ();
968                                 }
969                         }
970                 }
971
972                 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
973                 {
974                         Output.Write (attribute.Name.Replace ('+', '.'));
975                         Output.Write ('(');
976                         IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
977                         if (enumerator.MoveNext ()) {
978                                 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
979                                 OutputAttributeArgument (argument);
980
981                                 while (enumerator.MoveNext ()) {
982                                         Output.Write (", ");
983                                         argument = (CodeAttributeArgument) enumerator.Current;
984                                         OutputAttributeArgument (argument);
985                                 }
986                         }
987                         Output.Write (')');
988                 }
989
990                 protected override void OutputType (CodeTypeReference type)
991                 {
992                         Output.Write (GetTypeOutput (type));
993                 }
994
995                 private void OutputVTableModifier (MemberAttributes attributes)
996                 {
997                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New) {
998                                 Output.Write ("new ");
999                         }
1000                 }
1001
1002                 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1003                 {
1004                         switch (attributes & MemberAttributes.ScopeMask) {
1005                                 case MemberAttributes.Static:
1006                                         Output.Write ("static ");
1007                                         break;
1008                                 case MemberAttributes.Const:
1009                                         Output.Write ("const ");
1010                                         break;
1011                         }
1012                 }
1013
1014 #if NET_2_0
1015
1016                 // Note: this method should in fact be private as in .NET 2.0, the 
1017                 // CSharpCodeGenerator no longer derives from CodeGenerator but we
1018                 // still need to make this change.
1019                 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1020                 {
1021                         switch (attributes & MemberAttributes.AccessMask) {
1022                                 case MemberAttributes.Assembly:
1023                                 case MemberAttributes.FamilyAndAssembly:
1024                                         Output.Write ("internal "); 
1025                                         break;
1026                                 case MemberAttributes.Family:
1027                                         Output.Write ("protected ");
1028                                         break;
1029                                 case MemberAttributes.FamilyOrAssembly:
1030                                         Output.Write ("protected internal ");
1031                                         break;
1032                                 case MemberAttributes.Private:
1033                                         Output.Write ("private ");
1034                                         break;
1035                                 case MemberAttributes.Public:
1036                                         Output.Write ("public ");
1037                                         break;
1038                         }
1039                 }
1040
1041                 // Note: this method should in fact be private as in .NET 2.0, the 
1042                 // CSharpCodeGenerator no longer derives from CodeGenerator but we
1043                 // still need to make this change.
1044                 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1045                 {
1046                         switch (attributes & MemberAttributes.ScopeMask) {
1047                                 case MemberAttributes.Abstract:
1048                                         Output.Write ("abstract ");
1049                                         break;
1050                                 case MemberAttributes.Final:
1051                                         // do nothing
1052                                         break;
1053                                 case MemberAttributes.Static:
1054                                         Output.Write ("static ");
1055                                         break;
1056                                 case MemberAttributes.Override:
1057                                         Output.Write ("override ");
1058                                         break;
1059                                 default:
1060                                         MemberAttributes access = attributes & MemberAttributes.AccessMask;
1061                                         if (access == MemberAttributes.Assembly || access == MemberAttributes.Family || access == MemberAttributes.Public) {
1062                                                 Output.Write ("virtual ");
1063                                         }
1064                                         break;
1065                         }
1066                 }
1067 #endif
1068
1069                 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1070                 {
1071                         TextWriter output = Output;
1072                         TypeAttributes attributes = declaration.TypeAttributes;
1073
1074                         switch (attributes & TypeAttributes.VisibilityMask) {
1075                                 case TypeAttributes.Public:
1076                                 case TypeAttributes.NestedPublic:
1077                                         output.Write ("public ");
1078                                         break;
1079                                 case TypeAttributes.NestedPrivate:
1080                                         output.Write ("private ");
1081                                         break;
1082 #if NET_2_0
1083                                 case TypeAttributes.NotPublic:
1084                                 case TypeAttributes.NestedFamANDAssem:
1085                                 case TypeAttributes.NestedAssembly:
1086                                         output.Write ("internal ");
1087                                         break; 
1088                                 case TypeAttributes.NestedFamily:
1089                                         output.Write ("protected ");
1090                                         break;
1091                                 case TypeAttributes.NestedFamORAssem:
1092                                         output.Write ("protected internal ");
1093                                         break;
1094 #endif
1095                         }
1096
1097                         if (declaration.IsStruct) {
1098 #if NET_2_0
1099                                 if (declaration.IsPartial) {
1100                                         output.Write ("partial ");
1101                                 }
1102 #endif
1103                                 output.Write ("struct ");
1104                         } else if (declaration.IsEnum) {
1105                                 output.Write ("enum ");
1106                         } else {
1107                                 if ((attributes & TypeAttributes.Interface) != 0) {
1108 #if NET_2_0
1109                                         if (declaration.IsPartial) {
1110                                                 output.Write ("partial ");
1111                                         }
1112 #endif
1113                                         output.Write ("interface ");
1114                                 } else {
1115                                         if ((attributes & TypeAttributes.Sealed) != 0)
1116                                                 output.Write ("sealed ");
1117                                         if ((attributes & TypeAttributes.Abstract) != 0)
1118                                                 output.Write ("abstract ");
1119 #if NET_2_0
1120                                         if (declaration.IsPartial) {
1121                                                 output.Write ("partial ");
1122                                         }
1123 #endif
1124                                         output.Write ("class ");
1125                                 }
1126                         }
1127                 }
1128
1129                 [MonoTODO ("Implement missing special characters")]
1130                 protected override string QuoteSnippetString (string value)
1131                 {
1132                         // FIXME: this is weird, but works.
1133                         string output = value.Replace ("\\", "\\\\");
1134                         output = output.Replace ("\"", "\\\"");
1135                         output = output.Replace ("\t", "\\t");
1136                         output = output.Replace ("\r", "\\r");
1137                         output = output.Replace ("\n", "\\n");
1138
1139                         return "\"" + output + "\"";
1140                 }
1141
1142                 protected override void GeneratePrimitiveExpression(CodePrimitiveExpression e)
1143                 {
1144                         if (e.Value is char) {
1145                                 this.GenerateCharValue ((char) e.Value);
1146 #if NET_2_0
1147                         } else if (e.Value is ushort) {
1148                                 ushort uc = (ushort) e.Value;
1149                                 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
1150                         } else if (e.Value is uint) {
1151                                 uint ui = (uint) e.Value;
1152                                 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
1153                                 Output.Write ("u");
1154                         } else if (e.Value is ulong) {
1155                                 ulong ul = (ulong) e.Value;
1156                                 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
1157                                 Output.Write ("ul");
1158                         } else if (e.Value is sbyte) {
1159                                 sbyte sb = (sbyte) e.Value;
1160                                 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
1161 #endif
1162                         } else {
1163                                 base.GeneratePrimitiveExpression (e);
1164                         }
1165                 }
1166
1167                 private void GenerateCharValue (char c)
1168                 {
1169                         Output.Write ('\'');
1170
1171                         switch (c) {
1172                                 case '\0':
1173                                         Output.Write ("\\0");
1174                                         break;
1175                                 case '\t':
1176                                         Output.Write ("\\t");
1177                                         break;
1178                                 case '\n':
1179                                         Output.Write ("\\n");
1180                                         break;
1181                                 case '\r':
1182                                         Output.Write ("\\r");
1183                                         break;
1184                                 case '"':
1185                                         Output.Write ("\\\"");
1186                                         break;
1187                                 case '\'':
1188                                         Output.Write ("\\'");
1189                                         break;
1190                                 case '\\':
1191                                         Output.Write ("\\\\");
1192                                         break;
1193                                 case '\u2028':
1194                                         Output.Write ("\\u");
1195 #if NET_2_0
1196                                         Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1197 #else
1198                                         Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1199 #endif
1200                                         break;
1201                                 case '\u2029':
1202                                         Output.Write ("\\u");
1203 #if NET_2_0
1204                                         Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1205 #else
1206                                         Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1207 #endif
1208                                         break;
1209                                 default:
1210                                         Output.Write (c);
1211                                         break;
1212                         }
1213
1214                         Output.Write ('\'');
1215                 }
1216
1217                 protected override void GenerateSingleFloatValue (float f)
1218                 {
1219                         base.GenerateSingleFloatValue (f);
1220                         base.Output.Write ('F');
1221                 }
1222
1223                 protected override void GenerateDecimalValue (decimal d)
1224                 {
1225                         base.GenerateDecimalValue (d);
1226                         base.Output.Write ('m');
1227                 }
1228
1229                 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
1230                 {
1231                         OutputAttributes (e.CustomAttributes, null, true);
1232                         OutputDirection (e.Direction);
1233                         OutputType (e.Type);
1234                         Output.Write (' ');
1235                         Output.Write (GetSafeName (e.Name));
1236                 }
1237
1238                 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
1239                 {
1240                         Output.Write ("typeof(");
1241                         OutputType (e.Type);
1242                         Output.Write (")");
1243                 }
1244
1245                 /* 
1246                  * ICodeGenerator
1247                  */
1248
1249                 protected override string CreateEscapedIdentifier (string value)
1250                 {
1251                         if (value == null)
1252                                 throw new NullReferenceException ("Argument identifier is null.");
1253                         return GetSafeName (value);
1254                 }
1255
1256                 protected override string CreateValidIdentifier (string value)
1257                 {
1258                         if (value == null)
1259                                 throw new NullReferenceException ();
1260
1261                         if (keywordsTable == null)
1262                                 FillKeywordTable ();
1263
1264                         if (keywordsTable.Contains (value))
1265                                 return "_" + value;
1266                         else
1267                                 return value;
1268                 }
1269     
1270                 protected override string GetTypeOutput (CodeTypeReference type)
1271                 {
1272 #if NET_2_0
1273                         if ((type.Options & CodeTypeReferenceOptions.GenericTypeParameter) != 0)
1274                                 return type.BaseType;
1275 #endif
1276
1277                         string typeOutput = null;
1278
1279                         if (type.ArrayElementType != null) {
1280                                 typeOutput = GetTypeOutput (type.ArrayElementType);
1281                         } else {
1282                                 typeOutput = DetermineTypeOutput (type);
1283                         }
1284
1285                         int rank = type.ArrayRank;
1286                         if (rank > 0) {
1287                                 typeOutput += '[';
1288                                 for (--rank; rank > 0; --rank) {
1289                                         typeOutput += ',';
1290                                 }
1291                                 typeOutput += ']';
1292                         }
1293
1294                         return typeOutput;
1295                 }
1296
1297                 private string DetermineTypeOutput (CodeTypeReference type)
1298                 {
1299                         string typeOutput = null;
1300                         string baseType = type.BaseType;
1301
1302                         switch (baseType.ToLower (System.Globalization.CultureInfo.InvariantCulture)) {
1303                                 case "system.int32":
1304                                         typeOutput = "int";
1305                                         break;
1306                                 case "system.int64":
1307                                         typeOutput = "long";
1308                                         break;
1309                                 case "system.int16":
1310                                         typeOutput = "short";
1311                                         break;
1312                                 case "system.boolean":
1313                                         typeOutput = "bool";
1314                                         break;
1315                                 case "system.char":
1316                                         typeOutput = "char";
1317                                         break;
1318                                 case "system.string":
1319                                         typeOutput = "string";
1320                                         break;
1321                                 case "system.object":
1322                                         typeOutput = "object";
1323                                         break;
1324                                 case "system.void":
1325                                         typeOutput = "void";
1326                                         break;
1327 #if NET_2_0
1328                                 case "system.byte":
1329                                         typeOutput = "byte";
1330                                         break;
1331                                 case "system.sbyte":
1332                                         typeOutput = "sbyte";
1333                                         break;
1334                                 case "system.decimal":
1335                                         typeOutput = "decimal";
1336                                         break;
1337                                 case "system.double":
1338                                         typeOutput = "double";
1339                                         break;
1340                                 case "system.single":
1341                                         typeOutput = "float";
1342                                         break;
1343                                 case "system.uint16":
1344                                         typeOutput = "ushort";
1345                                         break;
1346                                 case "system.uint32":
1347                                         typeOutput = "uint";
1348                                         break;
1349                                 case "system.uint64":
1350                                         typeOutput = "ulong";
1351                                         break;
1352 #endif
1353                                 default:
1354 #if NET_2_0
1355                                         StringBuilder sb = new StringBuilder (baseType.Length);
1356                                         if (type.Options == CodeTypeReferenceOptions.GlobalReference) {
1357                                                 sb.Append ("global::");
1358                                         }
1359
1360                                         int lastProcessedChar = 0;
1361                                         for (int i = 0; i < baseType.Length; i++) {
1362                                                 char currentChar = baseType[i];
1363                                                 if (currentChar != '+' && currentChar != '.') {
1364                                                         if (currentChar == '`') {
1365                                                                 sb.Append (CreateEscapedIdentifier (baseType.Substring (
1366                                                                         lastProcessedChar, i - lastProcessedChar)));
1367                                                                 // skip ` character
1368                                                                 i++;
1369                                                                 // determine number of type arguments to output
1370                                                                 int typeArgCount = baseType[i] - '0';
1371                                                                 // output type arguments
1372                                                                 OutputTypeArguments (type.TypeArguments, sb, typeArgCount);
1373                                                                 // skip type argument indicator
1374                                                                 i++;
1375                                                                 // if next character is . or +, then append .
1376                                                                 if ((i < baseType.Length) && ((baseType[i] == '+') || (baseType[i] == '.'))) {
1377                                                                         sb.Append ('.');
1378                                                                         // skip character that we just processed
1379                                                                         i++;
1380                                                                 }
1381                                                                 // save postion of last processed character
1382                                                                 lastProcessedChar = i;
1383                                                         }
1384                                                 } else {
1385                                                         sb.Append (CreateEscapedIdentifier (baseType.Substring (
1386                                                                 lastProcessedChar, i - lastProcessedChar)));
1387                                                         sb.Append ('.');
1388                                                         // skip separator
1389                                                         i++;
1390                                                         // save postion of last processed character
1391                                                         lastProcessedChar = i;
1392                                                 }
1393                                         }
1394
1395                                         // add characters that have not yet been processed 
1396                                         if (lastProcessedChar < baseType.Length) {
1397                                                 sb.Append (CreateEscapedIdentifier (baseType.Substring (lastProcessedChar)));
1398                                         }
1399
1400                                         typeOutput = sb.ToString ();
1401 #else
1402                                         typeOutput = GetSafeName (baseType);
1403                                         typeOutput = typeOutput.Replace ('+', '.');
1404 #endif
1405                                         break;
1406                         }
1407                         return typeOutput;
1408                 }
1409
1410                 static bool is_identifier_start_character (char c)
1411                 {
1412                         return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter (c);
1413                 }
1414
1415                 static bool is_identifier_part_character (char c)
1416                 {
1417                         return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c)
1418 ;
1419                 }
1420                 
1421                 protected override bool IsValidIdentifier (string identifier)
1422                 {
1423                         if (identifier == null || identifier.Length == 0)
1424                                 return false;
1425                         
1426                         if (keywordsTable == null)
1427                                 FillKeywordTable ();
1428
1429                         if (keywordsTable.Contains (identifier))
1430                                 return false;
1431
1432                         if (!is_identifier_start_character (identifier [0]))
1433                                 return false;
1434                         
1435                         for (int i = 1; i < identifier.Length; i ++)
1436                                 if (! is_identifier_part_character (identifier [i]))
1437                                         return false;
1438                         
1439                         return true;
1440                 }
1441
1442                 protected override bool Supports (GeneratorSupport supports)
1443                 {
1444                         return true;
1445                 }
1446
1447 #if NET_2_0
1448                 protected override void GenerateDirectives (CodeDirectiveCollection directives)
1449                 {
1450                         foreach (CodeDirective d in directives) {
1451                                 if (d is CodeChecksumPragma) {
1452                                         GenerateCodeChecksumPragma ((CodeChecksumPragma)d);
1453                                         continue;
1454                                 }
1455                                 if (d is CodeRegionDirective) {
1456                                         GenerateCodeRegionDirective ((CodeRegionDirective)d);
1457                                         continue;
1458                                 }
1459                                 throw new NotImplementedException ("Unknown CodeDirective");
1460                         }
1461                 }
1462
1463                 void GenerateCodeChecksumPragma (CodeChecksumPragma pragma)
1464                 {
1465                         Output.Write ("#pragma checksum \"");
1466                         Output.Write (pragma.FileName);
1467                         Output.Write ("\" \"");
1468                         Output.Write (pragma.ChecksumAlgorithmId.ToString ("B"));
1469                         Output.Write ("\" \"");
1470                         if (pragma.ChecksumData != null) {
1471                                 foreach (byte b in pragma.ChecksumData) {
1472                                         Output.Write (b.ToString ("X2"));
1473                                 }
1474                         }
1475                         Output.WriteLine ("\"");
1476                 }
1477
1478                 void GenerateCodeRegionDirective (CodeRegionDirective region)
1479                 {
1480                         switch (region.RegionMode) {
1481                                 case CodeRegionMode.Start:
1482                                         Output.Write ("#region ");
1483                                         Output.WriteLine (region.RegionText);
1484                                         return;
1485                                 case CodeRegionMode.End:
1486                                         Output.WriteLine ("#endregion");
1487                                         return;
1488                         }
1489                 }
1490
1491                 void GenerateGenericsParameters (CodeTypeParameterCollection parameters)
1492                 {
1493                         int count = parameters.Count;
1494                         if (count == 0)
1495                                 return;
1496
1497                         Output.Write ('<');
1498                         for (int i = 0; i < count - 1; ++i) {
1499                                 Output.Write (parameters [i].Name);
1500                                 Output.Write (", ");
1501                         }
1502                         Output.Write (parameters [count - 1].Name);
1503                         Output.Write ('>');
1504                 }
1505
1506                 void GenerateGenericsConstraints (CodeTypeParameterCollection parameters)
1507                 {
1508                         int count = parameters.Count;
1509                         if (count == 0)
1510                                 return;
1511
1512                         bool indented = false;
1513                         
1514                         for (int i = 0; i < count; i++) {
1515                                 CodeTypeParameter p = parameters [i];
1516                                 bool hasConstraints = (p.Constraints.Count != 0);
1517                                 Output.WriteLine ();
1518                                 if (!hasConstraints && !p.HasConstructorConstraint)
1519                                         continue;
1520
1521                                 if (!indented) {
1522                                         ++Indent;
1523                                         indented = true;
1524                                 }
1525
1526                                 Output.Write ("where ");
1527                                 Output.Write (p.Name);
1528                                 Output.Write (" : ");
1529
1530                                 for (int j = 0; j < p.Constraints.Count; j++) {
1531                                         if (j > 0)
1532                                                 Output.Write (", ");
1533                                         OutputType (p.Constraints [j]);
1534                                 }
1535
1536                                 if (p.HasConstructorConstraint) {
1537                                         if (hasConstraints)
1538                                                 Output.Write (", ");
1539                                         Output.Write ("new");
1540                                         if (hasConstraints)
1541                                                 Output.Write (" ");
1542                                         Output.Write ("()");
1543                                 }
1544                         }
1545
1546                         if (indented)
1547                                 --Indent;
1548                 }
1549
1550                 string GetTypeArguments (CodeTypeReferenceCollection collection)
1551                 {
1552                         StringBuilder sb = new StringBuilder (" <");
1553                         foreach (CodeTypeReference r in collection) {
1554                                 sb.Append (GetTypeOutput (r));
1555                                 sb.Append (", ");
1556                         }
1557                         sb.Length--;
1558                         sb [sb.Length - 1] = '>';
1559                         return sb.ToString ();
1560                 }
1561
1562                 private void OutputTypeArguments (CodeTypeReferenceCollection typeArguments, StringBuilder sb, int count)
1563                 {
1564                         if (count == 0) {
1565                                 return;
1566                         } else if (typeArguments.Count == 0) {
1567                                 // generic type definition
1568                                 sb.Append ("<>");
1569                                 return;
1570                         }
1571
1572                         sb.Append ('<');
1573
1574                         // write first type argument
1575                         sb.Append (GetTypeOutput (typeArguments[0]));
1576                         // subsequent type argument are prefixed by ', ' separator
1577                         for (int i = 1; i < count; i++) {
1578                                 sb.Append (", ");
1579                                 sb.Append (GetTypeOutput (typeArguments[i]));
1580                         }
1581
1582                         sb.Append ('>');
1583                 }
1584 #endif
1585
1586 #if false
1587                 //[MonoTODO]
1588                 public override void ValidateIdentifier (string identifier)
1589                 {
1590                 }
1591 #endif
1592
1593                 private string GetSafeName (string id)
1594                 {
1595                         if (keywordsTable == null) {
1596                                 FillKeywordTable ();
1597                         }
1598                         if (keywordsTable.Contains (id)) {
1599                                 return "@" + id;
1600                         } else {
1601                                 return id;
1602                         }
1603                 }
1604
1605                 static void FillKeywordTable ()
1606                 {
1607                         keywordsTable = new Hashtable ();
1608                         foreach (string keyword in keywords) {
1609                                 keywordsTable.Add (keyword, keyword);
1610                         }
1611                 }
1612
1613                 private static Hashtable keywordsTable;
1614                 private static string[] keywords = new string[] {
1615                         "abstract","event","new","struct","as","explicit","null","switch","base","extern",
1616                         "this","false","operator","throw","break","finally","out","true",
1617                         "fixed","override","try","case","params","typeof","catch","for",
1618                         "private","foreach","protected","checked","goto","public",
1619                         "unchecked","class","if","readonly","unsafe","const","implicit","ref",
1620                         "continue","in","return","using","virtual","default",
1621                         "interface","sealed","volatile","delegate","internal","do","is",
1622                         "sizeof","while","lock","stackalloc","else","static","enum",
1623                         "namespace",
1624                         "object","bool","byte","float","uint","char","ulong","ushort",
1625                         "decimal","int","sbyte","short","double","long","string","void",
1626 #if NET_2_0
1627                         "partial", "yield", "where"
1628 #endif
1629                 };
1630         }
1631 }