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