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