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