importing messaging-2008 branch to trunk [continued]
[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                 IDictionary <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 (IDictionary <string, string> providerOptions)
67                 {
68                         this.providerOptions = providerOptions;
69                 }
70
71                 protected IDictionary <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 #if NET_2_0
565                         Output.WriteLine ("#line hidden");
566 #endif
567                 }
568
569                 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
570                 {
571                         if (IsCurrentDelegate || IsCurrentEnum) {
572                                 return;
573                         }
574
575                         OutputAttributes (eventRef.CustomAttributes, null, false);
576
577                         if (eventRef.PrivateImplementationType == null) {
578                                 OutputMemberAccessModifier (eventRef.Attributes);
579                         }
580
581                         Output.Write ("event ");
582
583                         if (eventRef.PrivateImplementationType != null) {
584                                 OutputTypeNamePair (eventRef.Type,
585                                         eventRef.PrivateImplementationType.BaseType + "." + 
586                                         eventRef.Name);
587                         } else {
588                                 OutputTypeNamePair (eventRef.Type, GetSafeName (eventRef.Name));
589                         }
590                         Output.WriteLine (';');
591                 }
592
593                 protected override void GenerateField (CodeMemberField field)
594                 {
595                         if (IsCurrentDelegate || IsCurrentInterface) {
596                                 return;
597                         }
598
599                         TextWriter output = Output;
600
601                         OutputAttributes (field.CustomAttributes, null, false);
602
603                         if (IsCurrentEnum) {
604                                 Output.Write (GetSafeName (field.Name));
605                         } else {
606                                 MemberAttributes attributes = field.Attributes;
607                                 OutputMemberAccessModifier (attributes);
608                                 OutputVTableModifier (attributes);
609                                 OutputFieldScopeModifier (attributes);
610
611                                 OutputTypeNamePair (field.Type, GetSafeName (field.Name));
612                         }
613
614                         CodeExpression initExpression = field.InitExpression;
615                         if (initExpression != null) {
616                                 output.Write (" = ");
617                                 GenerateExpression (initExpression);
618                         }
619
620                         if (IsCurrentEnum)
621                                 output.WriteLine (',');
622                         else
623                                 output.WriteLine (';');
624                 }
625                 
626                 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
627                 {
628                         Output.Write (member.Text);
629                 }
630                 
631                 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, 
632                                                                   CodeTypeDeclaration declaration)
633                 {
634 #if NET_2_0
635                         OutputAttributes (method.CustomAttributes, null, false);
636 #endif
637
638                         Output.Write ("public static ");
639 #if NET_2_0
640                         OutputType (method.ReturnType);
641 #else
642                         Output.Write ("void");
643 #endif
644                         Output.Write (" Main()");
645                         OutputStartBrace ();
646                         Indent++;
647                         GenerateStatements (method.Statements);
648                         Indent--;
649                         Output.WriteLine ("}");
650                 }
651                 
652                 protected override void GenerateMethod (CodeMemberMethod method,
653                                                         CodeTypeDeclaration declaration)
654                 {
655                         if (IsCurrentDelegate || IsCurrentEnum) {
656                                 return;
657                         }
658
659                         TextWriter output = Output;
660
661                         OutputAttributes (method.CustomAttributes, null, false);
662
663                         OutputAttributes (method.ReturnTypeCustomAttributes, 
664                                 "return: ", false);
665
666                         MemberAttributes attributes = method.Attributes;
667
668                         if (!IsCurrentInterface) {
669                                 if (method.PrivateImplementationType == null) {
670                                         OutputMemberAccessModifier (attributes);
671                                         OutputVTableModifier (attributes);
672                                         OutputMemberScopeModifier (attributes);
673                                 }
674                         } else {
675                                 OutputVTableModifier (attributes);
676                         }
677
678                         OutputType (method.ReturnType);
679                         output.Write (' ');
680
681                         CodeTypeReference privateType = method.PrivateImplementationType;
682                         if (privateType != null) {
683                                 output.Write (privateType.BaseType);
684                                 output.Write ('.');
685                         }
686                         output.Write (GetSafeName (method.Name));
687
688 #if NET_2_0
689                         GenerateGenericsParameters (method.TypeParameters);
690 #endif
691
692                         output.Write ('(');
693                         OutputParameters (method.Parameters);
694                         output.Write (')');
695
696 #if NET_2_0
697                         GenerateGenericsConstraints (method.TypeParameters);
698 #endif
699
700                         if (IsAbstract (attributes) || declaration.IsInterface)
701                                 output.WriteLine (';');
702                         else {
703                                 OutputStartBrace ();
704                                 ++Indent;
705                                 GenerateStatements (method.Statements);
706                                 --Indent;
707                                 output.WriteLine ('}');
708                         }
709                 }
710
711                 static bool IsAbstract (MemberAttributes attributes)
712                 {
713                         return (attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract;
714                 }
715
716                 protected override void GenerateProperty (CodeMemberProperty property,
717                                                           CodeTypeDeclaration declaration)
718                 {
719                         if (IsCurrentDelegate || IsCurrentEnum) {
720                                 return;
721                         }
722
723                         TextWriter output = Output;
724
725                         OutputAttributes (property.CustomAttributes, null, false);
726
727                         MemberAttributes attributes = property.Attributes;
728
729                         if (!IsCurrentInterface) {
730                                 if (property.PrivateImplementationType == null) {
731                                         OutputMemberAccessModifier (attributes);
732                                         OutputVTableModifier (attributes);
733                                         OutputMemberScopeModifier (attributes);
734                                 }
735                         } else {
736                                 OutputVTableModifier (attributes);
737                         }
738
739                         OutputType (property.Type);
740                         output.Write (' ');
741
742                         if (!IsCurrentInterface && property.PrivateImplementationType != null) {
743                                 output.Write (property.PrivateImplementationType.BaseType);
744                                 output.Write ('.');
745                         }
746
747                         // only consider property indexer if name is Item (case-insensitive 
748                         // comparison) AND property has parameters
749                         if (string.Compare(property.Name, "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
750                                 output.Write ("this[");
751                                 OutputParameters(property.Parameters);
752                                 output.Write(']');
753                         } else {
754                                 output.Write (GetSafeName (property.Name));
755                         }
756                         OutputStartBrace ();
757                         ++Indent;
758
759                         if (declaration.IsInterface || IsAbstract (property.Attributes))
760                         {
761                                 if (property.HasGet) output.WriteLine("get;");
762                                 if (property.HasSet) output.WriteLine("set;");
763                         }
764                         else
765                         {
766                                 if (property.HasGet)
767                                 {
768                                         output.Write ("get");
769                                         OutputStartBrace ();
770                                         ++Indent;
771
772                                         GenerateStatements (property.GetStatements);
773
774                                         --Indent;
775                                         output.WriteLine ('}');
776                                 }
777
778                                 if (property.HasSet)
779                                 {
780                                         output.Write ("set");
781                                         OutputStartBrace ();
782                                         ++Indent;
783
784                                         GenerateStatements (property.SetStatements);
785
786                                         --Indent;
787                                         output.WriteLine ('}');
788                                 }
789                         }
790
791                         --Indent;
792                         output.WriteLine ('}');
793                 }
794
795                 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
796                 {
797                         if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
798                                 return;
799                         }
800
801                         OutputAttributes (constructor.CustomAttributes, null, false);
802
803                         OutputMemberAccessModifier (constructor.Attributes);
804                         Output.Write (GetSafeName (CurrentTypeName) + "(");
805                         OutputParameters (constructor.Parameters);
806                         Output.Write (")");
807                         if (constructor.BaseConstructorArgs.Count > 0) {
808                                 Output.WriteLine (" : ");
809                                 Indent += 2;
810                                 Output.Write ("base(");
811                                 OutputExpressionList (constructor.BaseConstructorArgs);
812                                 Output.Write (')');
813                                 Indent -= 2;
814                         }
815                         if (constructor.ChainedConstructorArgs.Count > 0) {
816                                 Output.WriteLine (" : ");
817                                 Indent += 2;
818                                 Output.Write("this(");
819                                 OutputExpressionList (constructor.ChainedConstructorArgs);
820                                 Output.Write(')');
821                                 Indent -= 2;
822                         }
823                         OutputStartBrace ();
824                         Indent++;
825                         GenerateStatements (constructor.Statements);
826                         Indent--;
827                         Output.WriteLine ('}');
828                 }
829
830                 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
831                 {
832                         if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
833                                 return;
834                         }
835
836 #if NET_2_0
837                         OutputAttributes (constructor.CustomAttributes, null, false);
838 #endif
839
840                         Output.Write ("static " + GetSafeName (CurrentTypeName) + "()");
841                         OutputStartBrace ();
842                         Indent++;
843                         GenerateStatements (constructor.Statements);
844                         Indent--;
845                         Output.WriteLine ('}');
846                 }
847
848                 protected override void GenerateTypeStart(CodeTypeDeclaration declaration)
849                 {
850                         TextWriter output = Output;
851
852                         OutputAttributes (declaration.CustomAttributes, null, false);
853
854                         if (!IsCurrentDelegate) {
855                                 OutputTypeAttributes (declaration);
856
857                                 output.Write (GetSafeName (declaration.Name));
858
859 #if NET_2_0
860                                 GenerateGenericsParameters (declaration.TypeParameters);
861 #endif
862
863                                 IEnumerator enumerator = declaration.BaseTypes.GetEnumerator ();
864                                 if (enumerator.MoveNext ()) {
865                                         CodeTypeReference type = (CodeTypeReference) enumerator.Current;
866
867                                         output.Write (" : ");
868                                         OutputType (type);
869
870                                         while (enumerator.MoveNext ()) {
871                                                 type = (CodeTypeReference) enumerator.Current;
872
873                                                 output.Write (", ");
874                                                 OutputType (type);
875                                         }
876                                 }
877
878 #if NET_2_0
879                                 GenerateGenericsConstraints (declaration.TypeParameters);
880 #endif
881                                 OutputStartBrace ();
882                                 ++Indent;
883                         } else {
884                                 if ((declaration.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
885                                         output.Write ("public ");
886                                 }
887
888                                 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
889                                 output.Write ("delegate ");
890                                 OutputType (delegateDecl.ReturnType);
891                                 output.Write (" ");
892                                 output.Write (GetSafeName (declaration.Name));
893                                 output.Write ("(");
894                                 OutputParameters (delegateDecl.Parameters);
895                                 output.WriteLine (");");
896                         }
897                 }
898
899                 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
900                 {
901                         if (!IsCurrentDelegate) {
902                                 --Indent;
903                                 Output.WriteLine ("}");
904                         }
905                 }
906
907                 protected override void GenerateNamespaceStart (CodeNamespace ns)
908                 {
909                         TextWriter output = Output;
910                         
911                         string name = ns.Name;
912                         if (name != null && name.Length != 0) {
913                                 output.Write ("namespace ");
914                                 output.Write (GetSafeName (name));
915                                 OutputStartBrace ();
916                                 ++Indent;
917                         }
918                 }
919
920                 protected override void GenerateNamespaceEnd (CodeNamespace ns)
921                 {
922                         string name = ns.Name;
923                         if (name != null && name.Length != 0) {
924                                 --Indent;
925                                 Output.WriteLine ("}");
926                         }
927                 }
928
929                 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
930                 {
931                         TextWriter output = Output;
932
933                         output.Write ("using ");
934                         output.Write (GetSafeName (import.Namespace));
935                         output.WriteLine (';');
936                 }
937                 
938                 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
939                 {
940                         Output.Write ('[');
941                 }
942                 
943                 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
944                 {
945                         Output.Write (']');
946                 }
947
948                 private void OutputStartBrace ()
949                 {
950                         if (Options.BracingStyle == "C") {
951                                 Output.WriteLine ("");
952                                 Output.WriteLine ("{");
953                         } else {
954                                 Output.WriteLine (" {");
955                         }
956                 }
957
958                 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, bool inline)
959                 {
960 #if NET_2_0
961                         bool params_set = false;
962 #endif
963
964                         foreach (CodeAttributeDeclaration att in attributes) {
965 #if NET_2_0
966                                 if (att.Name == "System.ParamArrayAttribute") {
967                                         params_set = true;
968                                         continue;
969                                 }
970 #endif
971
972                                 GenerateAttributeDeclarationsStart (attributes);
973                                 if (prefix != null) {
974                                         Output.Write (prefix);
975                                 }
976                                 OutputAttributeDeclaration (att);
977                                 GenerateAttributeDeclarationsEnd (attributes);
978                                 if (inline) {
979                                         Output.Write (" ");
980                                 } else {
981                                         Output.WriteLine ();
982                                 }
983                         }
984
985 #if NET_2_0
986                         if (params_set) {
987                                 if (prefix != null)
988                                         Output.Write (prefix);
989                                 Output.Write ("params");
990                                 if (inline)
991                                         Output.Write (" ");
992                                 else
993                                         Output.WriteLine ();
994                         }
995 #endif
996                 }
997
998                 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
999                 {
1000                         Output.Write (attribute.Name.Replace ('+', '.'));
1001                         Output.Write ('(');
1002                         IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
1003                         if (enumerator.MoveNext ()) {
1004                                 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
1005                                 OutputAttributeArgument (argument);
1006
1007                                 while (enumerator.MoveNext ()) {
1008                                         Output.Write (", ");
1009                                         argument = (CodeAttributeArgument) enumerator.Current;
1010                                         OutputAttributeArgument (argument);
1011                                 }
1012                         }
1013                         Output.Write (')');
1014                 }
1015
1016                 protected override void OutputType (CodeTypeReference type)
1017                 {
1018                         Output.Write (GetTypeOutput (type));
1019                 }
1020
1021                 private void OutputVTableModifier (MemberAttributes attributes)
1022                 {
1023                         if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New) {
1024                                 Output.Write ("new ");
1025                         }
1026                 }
1027
1028                 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1029                 {
1030                         switch (attributes & MemberAttributes.ScopeMask) {
1031                                 case MemberAttributes.Static:
1032                                         Output.Write ("static ");
1033                                         break;
1034                                 case MemberAttributes.Const:
1035                                         Output.Write ("const ");
1036                                         break;
1037                         }
1038                 }
1039
1040 #if NET_2_0
1041
1042                 // Note: this method should in fact be private as in .NET 2.0, the 
1043                 // CSharpCodeGenerator no longer derives from CodeGenerator but we
1044                 // still need to make this change.
1045                 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1046                 {
1047                         switch (attributes & MemberAttributes.AccessMask) {
1048                                 case MemberAttributes.Assembly:
1049                                 case MemberAttributes.FamilyAndAssembly:
1050                                         Output.Write ("internal "); 
1051                                         break;
1052                                 case MemberAttributes.Family:
1053                                         Output.Write ("protected ");
1054                                         break;
1055                                 case MemberAttributes.FamilyOrAssembly:
1056                                         Output.Write ("protected internal ");
1057                                         break;
1058                                 case MemberAttributes.Private:
1059                                         Output.Write ("private ");
1060                                         break;
1061                                 case MemberAttributes.Public:
1062                                         Output.Write ("public ");
1063                                         break;
1064                         }
1065                 }
1066
1067                 // Note: this method should in fact be private as in .NET 2.0, the 
1068                 // CSharpCodeGenerator no longer derives from CodeGenerator but we
1069                 // still need to make this change.
1070                 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1071                 {
1072                         switch (attributes & MemberAttributes.ScopeMask) {
1073                                 case MemberAttributes.Abstract:
1074                                         Output.Write ("abstract ");
1075                                         break;
1076                                 case MemberAttributes.Final:
1077                                         // do nothing
1078                                         break;
1079                                 case MemberAttributes.Static:
1080                                         Output.Write ("static ");
1081                                         break;
1082                                 case MemberAttributes.Override:
1083                                         Output.Write ("override ");
1084                                         break;
1085                                 default:
1086                                         MemberAttributes access = attributes & MemberAttributes.AccessMask;
1087                                         if (access == MemberAttributes.Assembly || access == MemberAttributes.Family || access == MemberAttributes.Public) {
1088                                                 Output.Write ("virtual ");
1089                                         }
1090                                         break;
1091                         }
1092                 }
1093 #endif
1094
1095                 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1096                 {
1097                         TextWriter output = Output;
1098                         TypeAttributes attributes = declaration.TypeAttributes;
1099
1100                         switch (attributes & TypeAttributes.VisibilityMask) {
1101                                 case TypeAttributes.Public:
1102                                 case TypeAttributes.NestedPublic:
1103                                         output.Write ("public ");
1104                                         break;
1105                                 case TypeAttributes.NestedPrivate:
1106                                         output.Write ("private ");
1107                                         break;
1108 #if NET_2_0
1109                                 case TypeAttributes.NotPublic:
1110                                 case TypeAttributes.NestedFamANDAssem:
1111                                 case TypeAttributes.NestedAssembly:
1112                                         output.Write ("internal ");
1113                                         break; 
1114                                 case TypeAttributes.NestedFamily:
1115                                         output.Write ("protected ");
1116                                         break;
1117                                 case TypeAttributes.NestedFamORAssem:
1118                                         output.Write ("protected internal ");
1119                                         break;
1120 #endif
1121                         }
1122
1123                         if (declaration.IsStruct) {
1124 #if NET_2_0
1125                                 if (declaration.IsPartial) {
1126                                         output.Write ("partial ");
1127                                 }
1128 #endif
1129                                 output.Write ("struct ");
1130                         } else if (declaration.IsEnum) {
1131                                 output.Write ("enum ");
1132                         } else {
1133                                 if ((attributes & TypeAttributes.Interface) != 0) {
1134 #if NET_2_0
1135                                         if (declaration.IsPartial) {
1136                                                 output.Write ("partial ");
1137                                         }
1138 #endif
1139                                         output.Write ("interface ");
1140                                 } else {
1141                                         if ((attributes & TypeAttributes.Sealed) != 0)
1142                                                 output.Write ("sealed ");
1143                                         if ((attributes & TypeAttributes.Abstract) != 0)
1144                                                 output.Write ("abstract ");
1145 #if NET_2_0
1146                                         if (declaration.IsPartial) {
1147                                                 output.Write ("partial ");
1148                                         }
1149 #endif
1150                                         output.Write ("class ");
1151                                 }
1152                         }
1153                 }
1154
1155                 [MonoTODO ("Implement missing special characters")]
1156                 protected override string QuoteSnippetString (string value)
1157                 {
1158                         // FIXME: this is weird, but works.
1159                         string output = value.Replace ("\\", "\\\\");
1160                         output = output.Replace ("\"", "\\\"");
1161                         output = output.Replace ("\t", "\\t");
1162                         output = output.Replace ("\r", "\\r");
1163                         output = output.Replace ("\n", "\\n");
1164
1165                         return "\"" + output + "\"";
1166                 }
1167
1168                 protected override void GeneratePrimitiveExpression(CodePrimitiveExpression e)
1169                 {
1170                         if (e.Value is char) {
1171                                 this.GenerateCharValue ((char) e.Value);
1172 #if NET_2_0
1173                         } else if (e.Value is ushort) {
1174                                 ushort uc = (ushort) e.Value;
1175                                 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
1176                         } else if (e.Value is uint) {
1177                                 uint ui = (uint) e.Value;
1178                                 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
1179                                 Output.Write ("u");
1180                         } else if (e.Value is ulong) {
1181                                 ulong ul = (ulong) e.Value;
1182                                 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
1183                                 Output.Write ("ul");
1184                         } else if (e.Value is sbyte) {
1185                                 sbyte sb = (sbyte) e.Value;
1186                                 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
1187 #endif
1188                         } else {
1189                                 base.GeneratePrimitiveExpression (e);
1190                         }
1191                 }
1192
1193                 private void GenerateCharValue (char c)
1194                 {
1195                         Output.Write ('\'');
1196
1197                         switch (c) {
1198                                 case '\0':
1199                                         Output.Write ("\\0");
1200                                         break;
1201                                 case '\t':
1202                                         Output.Write ("\\t");
1203                                         break;
1204                                 case '\n':
1205                                         Output.Write ("\\n");
1206                                         break;
1207                                 case '\r':
1208                                         Output.Write ("\\r");
1209                                         break;
1210                                 case '"':
1211                                         Output.Write ("\\\"");
1212                                         break;
1213                                 case '\'':
1214                                         Output.Write ("\\'");
1215                                         break;
1216                                 case '\\':
1217                                         Output.Write ("\\\\");
1218                                         break;
1219                                 case '\u2028':
1220                                         Output.Write ("\\u");
1221 #if NET_2_0
1222                                         Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1223 #else
1224                                         Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1225 #endif
1226                                         break;
1227                                 case '\u2029':
1228                                         Output.Write ("\\u");
1229 #if NET_2_0
1230                                         Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1231 #else
1232                                         Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1233 #endif
1234                                         break;
1235                                 default:
1236                                         Output.Write (c);
1237                                         break;
1238                         }
1239
1240                         Output.Write ('\'');
1241                 }
1242
1243                 protected override void GenerateSingleFloatValue (float f)
1244                 {
1245                         base.GenerateSingleFloatValue (f);
1246                         base.Output.Write ('F');
1247                 }
1248
1249                 protected override void GenerateDecimalValue (decimal d)
1250                 {
1251                         base.GenerateDecimalValue (d);
1252                         base.Output.Write ('m');
1253                 }
1254
1255                 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
1256                 {
1257                         OutputAttributes (e.CustomAttributes, null, true);
1258                         OutputDirection (e.Direction);
1259                         OutputType (e.Type);
1260                         Output.Write (' ');
1261                         Output.Write (GetSafeName (e.Name));
1262                 }
1263
1264                 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
1265                 {
1266                         Output.Write ("typeof(");
1267                         OutputType (e.Type);
1268                         Output.Write (")");
1269                 }
1270
1271                 /* 
1272                  * ICodeGenerator
1273                  */
1274
1275                 protected override string CreateEscapedIdentifier (string value)
1276                 {
1277                         if (value == null)
1278                                 throw new NullReferenceException ("Argument identifier is null.");
1279                         return GetSafeName (value);
1280                 }
1281
1282                 protected override string CreateValidIdentifier (string value)
1283                 {
1284                         if (value == null)
1285                                 throw new NullReferenceException ();
1286
1287                         if (keywordsTable == null)
1288                                 FillKeywordTable ();
1289
1290                         if (keywordsTable.Contains (value))
1291                                 return "_" + value;
1292                         else
1293                                 return value;
1294                 }
1295     
1296                 protected override string GetTypeOutput (CodeTypeReference type)
1297                 {
1298 #if NET_2_0
1299                         if ((type.Options & CodeTypeReferenceOptions.GenericTypeParameter) != 0)
1300                                 return type.BaseType;
1301 #endif
1302
1303                         string typeOutput = null;
1304
1305                         if (type.ArrayElementType != null) {
1306                                 typeOutput = GetTypeOutput (type.ArrayElementType);
1307                         } else {
1308                                 typeOutput = DetermineTypeOutput (type);
1309                         }
1310
1311                         int rank = type.ArrayRank;
1312                         if (rank > 0) {
1313                                 typeOutput += '[';
1314                                 for (--rank; rank > 0; --rank) {
1315                                         typeOutput += ',';
1316                                 }
1317                                 typeOutput += ']';
1318                         }
1319
1320                         return typeOutput;
1321                 }
1322
1323                 private string DetermineTypeOutput (CodeTypeReference type)
1324                 {
1325                         string typeOutput = null;
1326                         string baseType = type.BaseType;
1327
1328                         switch (baseType.ToLower (System.Globalization.CultureInfo.InvariantCulture)) {
1329                                 case "system.int32":
1330                                         typeOutput = "int";
1331                                         break;
1332                                 case "system.int64":
1333                                         typeOutput = "long";
1334                                         break;
1335                                 case "system.int16":
1336                                         typeOutput = "short";
1337                                         break;
1338                                 case "system.boolean":
1339                                         typeOutput = "bool";
1340                                         break;
1341                                 case "system.char":
1342                                         typeOutput = "char";
1343                                         break;
1344                                 case "system.string":
1345                                         typeOutput = "string";
1346                                         break;
1347                                 case "system.object":
1348                                         typeOutput = "object";
1349                                         break;
1350                                 case "system.void":
1351                                         typeOutput = "void";
1352                                         break;
1353 #if NET_2_0
1354                                 case "system.byte":
1355                                         typeOutput = "byte";
1356                                         break;
1357                                 case "system.sbyte":
1358                                         typeOutput = "sbyte";
1359                                         break;
1360                                 case "system.decimal":
1361                                         typeOutput = "decimal";
1362                                         break;
1363                                 case "system.double":
1364                                         typeOutput = "double";
1365                                         break;
1366                                 case "system.single":
1367                                         typeOutput = "float";
1368                                         break;
1369                                 case "system.uint16":
1370                                         typeOutput = "ushort";
1371                                         break;
1372                                 case "system.uint32":
1373                                         typeOutput = "uint";
1374                                         break;
1375                                 case "system.uint64":
1376                                         typeOutput = "ulong";
1377                                         break;
1378 #endif
1379                                 default:
1380 #if NET_2_0
1381                                         StringBuilder sb = new StringBuilder (baseType.Length);
1382                                         if (type.Options == CodeTypeReferenceOptions.GlobalReference) {
1383                                                 sb.Append ("global::");
1384                                         }
1385
1386                                         int lastProcessedChar = 0;
1387                                         for (int i = 0; i < baseType.Length; i++) {
1388                                                 char currentChar = baseType[i];
1389                                                 if (currentChar != '+' && currentChar != '.') {
1390                                                         if (currentChar == '`') {
1391                                                                 sb.Append (CreateEscapedIdentifier (baseType.Substring (
1392                                                                         lastProcessedChar, i - lastProcessedChar)));
1393                                                                 // skip ` character
1394                                                                 i++;
1395                                                                 // determine number of type arguments to output
1396                                                                 int end = i;
1397                                                                 while (end < baseType.Length && Char.IsDigit (baseType [end]))
1398                                                                         end++;
1399                                                                 int typeArgCount = Int32.Parse (baseType.Substring (i, end - i));
1400                                                                 // output type arguments
1401                                                                 OutputTypeArguments (type.TypeArguments, sb, typeArgCount);
1402                                                                 // skip type argument indicator
1403                                                                 i = end;
1404                                                                 // if next character is . or +, then append .
1405                                                                 if ((i < baseType.Length) && ((baseType[i] == '+') || (baseType[i] == '.'))) {
1406                                                                         sb.Append ('.');
1407                                                                         // skip character that we just processed
1408                                                                         i++;
1409                                                                 }
1410                                                                 // save postion of last processed character
1411                                                                 lastProcessedChar = i;
1412                                                         }
1413                                                 } else {
1414                                                         sb.Append (CreateEscapedIdentifier (baseType.Substring (
1415                                                                 lastProcessedChar, i - lastProcessedChar)));
1416                                                         sb.Append ('.');
1417                                                         // skip separator
1418                                                         i++;
1419                                                         // save postion of last processed character
1420                                                         lastProcessedChar = i;
1421                                                 }
1422                                         }
1423
1424                                         // add characters that have not yet been processed 
1425                                         if (lastProcessedChar < baseType.Length) {
1426                                                 sb.Append (CreateEscapedIdentifier (baseType.Substring (lastProcessedChar)));
1427                                         }
1428
1429                                         typeOutput = sb.ToString ();
1430 #else
1431                                         typeOutput = GetSafeName (baseType);
1432                                         typeOutput = typeOutput.Replace ('+', '.');
1433 #endif
1434                                         break;
1435                         }
1436                         return typeOutput;
1437                 }
1438
1439                 static bool is_identifier_start_character (char c)
1440                 {
1441                         return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter (c);
1442                 }
1443
1444                 static bool is_identifier_part_character (char c)
1445                 {
1446                         return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c)
1447 ;
1448                 }
1449                 
1450                 protected override bool IsValidIdentifier (string identifier)
1451                 {
1452                         if (identifier == null || identifier.Length == 0)
1453                                 return false;
1454                         
1455                         if (keywordsTable == null)
1456                                 FillKeywordTable ();
1457
1458                         if (keywordsTable.Contains (identifier))
1459                                 return false;
1460
1461                         if (!is_identifier_start_character (identifier [0]))
1462                                 return false;
1463                         
1464                         for (int i = 1; i < identifier.Length; i ++)
1465                                 if (! is_identifier_part_character (identifier [i]))
1466                                         return false;
1467                         
1468                         return true;
1469                 }
1470
1471                 protected override bool Supports (GeneratorSupport supports)
1472                 {
1473                         return true;
1474                 }
1475
1476 #if NET_2_0
1477                 protected override void GenerateDirectives (CodeDirectiveCollection directives)
1478                 {
1479                         foreach (CodeDirective d in directives) {
1480                                 if (d is CodeChecksumPragma) {
1481                                         GenerateCodeChecksumPragma ((CodeChecksumPragma)d);
1482                                         continue;
1483                                 }
1484                                 if (d is CodeRegionDirective) {
1485                                         GenerateCodeRegionDirective ((CodeRegionDirective)d);
1486                                         continue;
1487                                 }
1488                                 throw new NotImplementedException ("Unknown CodeDirective");
1489                         }
1490                 }
1491
1492                 void GenerateCodeChecksumPragma (CodeChecksumPragma pragma)
1493                 {
1494                         Output.Write ("#pragma checksum ");
1495                         Output.Write (QuoteSnippetString (pragma.FileName));
1496                         Output.Write (" \"");
1497                         Output.Write (pragma.ChecksumAlgorithmId.ToString ("B"));
1498                         Output.Write ("\" \"");
1499                         if (pragma.ChecksumData != null) {
1500                                 foreach (byte b in pragma.ChecksumData) {
1501                                         Output.Write (b.ToString ("X2"));
1502                                 }
1503                         }
1504                         Output.WriteLine ("\"");
1505                 }
1506
1507                 void GenerateCodeRegionDirective (CodeRegionDirective region)
1508                 {
1509                         switch (region.RegionMode) {
1510                                 case CodeRegionMode.Start:
1511                                         Output.Write ("#region ");
1512                                         Output.WriteLine (region.RegionText);
1513                                         return;
1514                                 case CodeRegionMode.End:
1515                                         Output.WriteLine ("#endregion");
1516                                         return;
1517                         }
1518                 }
1519
1520                 void GenerateGenericsParameters (CodeTypeParameterCollection parameters)
1521                 {
1522                         int count = parameters.Count;
1523                         if (count == 0)
1524                                 return;
1525
1526                         Output.Write ('<');
1527                         for (int i = 0; i < count - 1; ++i) {
1528                                 Output.Write (parameters [i].Name);
1529                                 Output.Write (", ");
1530                         }
1531                         Output.Write (parameters [count - 1].Name);
1532                         Output.Write ('>');
1533                 }
1534
1535                 void GenerateGenericsConstraints (CodeTypeParameterCollection parameters)
1536                 {
1537                         int count = parameters.Count;
1538                         if (count == 0)
1539                                 return;
1540
1541                         bool indented = false;
1542                         
1543                         for (int i = 0; i < count; i++) {
1544                                 CodeTypeParameter p = parameters [i];
1545                                 bool hasConstraints = (p.Constraints.Count != 0);
1546                                 Output.WriteLine ();
1547                                 if (!hasConstraints && !p.HasConstructorConstraint)
1548                                         continue;
1549
1550                                 if (!indented) {
1551                                         ++Indent;
1552                                         indented = true;
1553                                 }
1554
1555                                 Output.Write ("where ");
1556                                 Output.Write (p.Name);
1557                                 Output.Write (" : ");
1558
1559                                 for (int j = 0; j < p.Constraints.Count; j++) {
1560                                         if (j > 0)
1561                                                 Output.Write (", ");
1562                                         OutputType (p.Constraints [j]);
1563                                 }
1564
1565                                 if (p.HasConstructorConstraint) {
1566                                         if (hasConstraints)
1567                                                 Output.Write (", ");
1568                                         Output.Write ("new");
1569                                         if (hasConstraints)
1570                                                 Output.Write (" ");
1571                                         Output.Write ("()");
1572                                 }
1573                         }
1574
1575                         if (indented)
1576                                 --Indent;
1577                 }
1578
1579                 string GetTypeArguments (CodeTypeReferenceCollection collection)
1580                 {
1581                         StringBuilder sb = new StringBuilder (" <");
1582                         foreach (CodeTypeReference r in collection) {
1583                                 sb.Append (GetTypeOutput (r));
1584                                 sb.Append (", ");
1585                         }
1586                         sb.Length--;
1587                         sb [sb.Length - 1] = '>';
1588                         return sb.ToString ();
1589                 }
1590
1591                 private void OutputTypeArguments (CodeTypeReferenceCollection typeArguments, StringBuilder sb, int count)
1592                 {
1593                         if (count == 0) {
1594                                 return;
1595                         } else if (typeArguments.Count == 0) {
1596                                 // generic type definition
1597                                 sb.Append ("<>");
1598                                 return;
1599                         }
1600
1601                         sb.Append ('<');
1602
1603                         // write first type argument
1604                         sb.Append (GetTypeOutput (typeArguments[0]));
1605                         // subsequent type argument are prefixed by ', ' separator
1606                         for (int i = 1; i < count; i++) {
1607                                 sb.Append (", ");
1608                                 sb.Append (GetTypeOutput (typeArguments[i]));
1609                         }
1610
1611                         sb.Append ('>');
1612                 }
1613 #endif
1614
1615 #if false
1616                 //[MonoTODO]
1617                 public override void ValidateIdentifier (string identifier)
1618                 {
1619                 }
1620 #endif
1621
1622                 private string GetSafeName (string id)
1623                 {
1624                         if (keywordsTable == null) {
1625                                 FillKeywordTable ();
1626                         }
1627                         if (keywordsTable.Contains (id)) {
1628                                 return "@" + id;
1629                         } else {
1630                                 return id;
1631                         }
1632                 }
1633
1634                 static void FillKeywordTable ()
1635                 {
1636                         keywordsTable = new Hashtable ();
1637                         foreach (string keyword in keywords) {
1638                                 keywordsTable.Add (keyword, keyword);
1639                         }
1640                 }
1641
1642                 private static Hashtable keywordsTable;
1643                 private static string[] keywords = new string[] {
1644                         "abstract","event","new","struct","as","explicit","null","switch","base","extern",
1645                         "this","false","operator","throw","break","finally","out","true",
1646                         "fixed","override","try","case","params","typeof","catch","for",
1647                         "private","foreach","protected","checked","goto","public",
1648                         "unchecked","class","if","readonly","unsafe","const","implicit","ref",
1649                         "continue","in","return","using","virtual","default",
1650                         "interface","sealed","volatile","delegate","internal","do","is",
1651                         "sizeof","while","lock","stackalloc","else","static","enum",
1652                         "namespace",
1653                         "object","bool","byte","float","uint","char","ulong","ushort",
1654                         "decimal","int","sbyte","short","double","long","string","void",
1655 #if NET_2_0
1656                         "partial", "yield", "where"
1657 #endif
1658                 };
1659         }
1660 }