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