2 // Mono.CSharp CSharpCodeProvider Class implementation
5 // Daniel Stodden (stodden@in.tum.de)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2002 Ximian, Inc.
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.CodeDom.Compiler;
37 using System.Globalization;
39 using System.Reflection;
40 using System.Collections;
43 internal class CSharpCodeGenerator
46 // It is used for beautiful "for" syntax
47 bool dont_write_semicolon;
52 public CSharpCodeGenerator()
54 dont_write_semicolon = false;
60 protected override string NullToken {
70 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
73 // This tries to replicate MS behavior as good as
76 // The Code-Array stuff in ms.net seems to be broken
77 // anyways, or I'm too stupid to understand it.
79 // I'm sick of it. If you try to develop array
80 // creations, test them on windows. If it works there
81 // but not in mono, drop me a note. I'd be especially
82 // interested in jagged-multidimensional combinations
83 // with proper initialization :}
86 TextWriter output = Output;
88 output.Write ("new ");
90 CodeExpressionCollection initializers = expression.Initializers;
91 CodeTypeReference createType = expression.CreateType;
93 if (initializers.Count > 0) {
95 OutputType (createType);
97 if (expression.CreateType.ArrayRank == 0) {
103 OutputExpressionList (initializers, true);
107 CodeTypeReference arrayType = createType.ArrayElementType;
108 while (arrayType != null) {
109 createType = arrayType;
110 arrayType = arrayType.ArrayElementType;
113 OutputType (createType);
117 CodeExpression size = expression.SizeExpression;
119 GenerateExpression (size);
121 output.Write (expression.Size);
127 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
129 Output.Write ("base");
132 protected override void GenerateCastExpression (CodeCastExpression expression)
134 TextWriter output = Output;
136 OutputType (expression.TargetType);
138 GenerateExpression (expression.Expression);
143 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
145 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
146 GenerateComment (new CodeComment (" <autogenerated>"));
147 GenerateComment (new CodeComment (" This code was generated by a tool."));
148 GenerateComment (new CodeComment (" Mono Runtime Version: " + System.Environment.Version));
149 GenerateComment (new CodeComment (""));
150 GenerateComment (new CodeComment (" Changes to this file may cause incorrect behavior and will be lost if "));
151 GenerateComment (new CodeComment (" the code is regenerated."));
152 GenerateComment (new CodeComment (" </autogenerated>"));
153 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
155 base.GenerateCompileUnitStart (compileUnit);
158 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
160 GenerateCompileUnitStart (compileUnit);
162 if (compileUnit.AssemblyCustomAttributes.Count > 0) {
163 OutputAttributes (compileUnit.AssemblyCustomAttributes,
164 "assembly: ", false);
165 Output.WriteLine ("");
168 foreach (CodeNamespace ns in compileUnit.Namespaces)
169 GenerateNamespace (ns);
171 GenerateCompileUnitEnd (compileUnit);
174 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
176 TextWriter output = Output;
178 output.Write ("new ");
179 OutputType (expression.DelegateType);
182 CodeExpression targetObject = expression.TargetObject;
183 if (targetObject != null) {
184 GenerateExpression (targetObject);
187 output.Write (GetSafeName (expression.MethodName));
192 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
194 CodeExpression targetObject = expression.TargetObject;
195 if (targetObject != null) {
196 GenerateExpression (targetObject);
199 Output.Write (GetSafeName (expression.FieldName));
202 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
204 Output.Write (GetSafeName (expression.ParameterName));
207 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
209 Output.Write (GetSafeName (expression.VariableName));
212 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
214 TextWriter output = Output;
216 GenerateExpression (expression.TargetObject);
218 OutputExpressionList (expression.Indices);
222 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
224 TextWriter output = Output;
226 GenerateExpression (expression.TargetObject);
228 OutputExpressionList (expression.Indices);
232 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
234 Output.Write (expression.Value);
237 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
239 TextWriter output = Output;
241 GenerateMethodReferenceExpression (expression.Method);
244 OutputExpressionList (expression.Parameters);
248 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
250 if (expression.TargetObject != null)
252 GenerateExpression (expression.TargetObject);
255 Output.Write (GetSafeName (expression.MethodName));
257 if (expression.TypeArguments.Count > 0)
258 Output.Write (GetTypeArguments (expression.TypeArguments));
262 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
264 if (expression.TargetObject != null) {
265 GenerateExpression (expression.TargetObject);
268 Output.Write (GetSafeName (expression.EventName));
271 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
273 GenerateExpression (expression.TargetObject);
275 OutputExpressionList (expression.Parameters);
279 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
281 Output.Write ("new ");
282 OutputType (expression.CreateType);
284 OutputExpressionList (expression.Parameters);
288 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
290 CodeExpression targetObject = expression.TargetObject;
291 if (targetObject != null) {
292 GenerateExpression (targetObject);
295 Output.Write (GetSafeName (expression.PropertyName ));
298 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
300 Output.Write ("value");
303 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
305 Output.Write ("this");
308 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
310 GenerateExpression (statement.Expression);
311 if (dont_write_semicolon)
313 Output.WriteLine(';');
316 protected override void GenerateIterationStatement (CodeIterationStatement statement)
318 TextWriter output = Output;
320 dont_write_semicolon = true;
321 output.Write ("for (");
322 GenerateStatement (statement.InitStatement);
324 GenerateExpression (statement.TestExpression);
326 GenerateStatement (statement.IncrementStatement);
328 dont_write_semicolon = false;
331 GenerateStatements (statement.Statements);
333 output.WriteLine ('}');
336 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
338 Output.Write ("throw");
339 if (statement.ToThrow != null) {
341 GenerateExpression (statement.ToThrow);
343 Output.WriteLine (";");
346 protected override void GenerateComment (CodeComment comment)
348 TextWriter output = Output;
350 string commentChars = null;
352 if (comment.DocComment) {
353 commentChars = "///";
358 output.Write (commentChars);
360 string text = comment.Text;
362 for (int i = 0; i < text.Length; i++) {
363 output.Write (text[i]);
364 if (text[i] == '\r') {
365 if (i < (text.Length - 1) && text[i + 1] == '\n') {
368 output.Write (commentChars);
369 } else if (text[i] == '\n') {
370 output.Write (commentChars);
377 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
379 TextWriter output = Output;
381 if (statement.Expression != null) {
382 output.Write ("return ");
383 GenerateExpression (statement.Expression);
384 output.WriteLine (";");
386 output.WriteLine ("return;");
390 protected override void GenerateConditionStatement (CodeConditionStatement statement)
392 TextWriter output = Output;
393 output.Write ("if (");
394 GenerateExpression (statement.Condition);
399 GenerateStatements (statement.TrueStatements);
402 CodeStatementCollection falses = statement.FalseStatements;
403 if (falses.Count > 0) {
405 if (Options.ElseOnClosing)
409 output.Write ("else");
412 GenerateStatements (falses);
415 output.WriteLine ('}');
418 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
420 TextWriter output = Output;
421 CodeGeneratorOptions options = Options;
423 output.Write ("try");
426 GenerateStatements (statement.TryStatements);
429 foreach (CodeCatchClause clause in statement.CatchClauses) {
431 if (options.ElseOnClosing)
435 output.Write ("catch (");
436 OutputTypeNamePair (clause.CatchExceptionType, GetSafeName(clause.LocalName));
440 GenerateStatements (clause.Statements);
444 CodeStatementCollection finallies = statement.FinallyStatements;
445 if (finallies.Count > 0) {
447 if (options.ElseOnClosing)
451 output.Write ("finally");
454 GenerateStatements (finallies);
458 output.WriteLine('}');
461 protected override void GenerateAssignStatement (CodeAssignStatement statement)
463 TextWriter output = Output;
464 GenerateExpression (statement.Left);
465 output.Write (" = ");
466 GenerateExpression (statement.Right);
467 if (dont_write_semicolon)
469 output.WriteLine (';');
472 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
474 TextWriter output = Output;
476 GenerateEventReferenceExpression (statement.Event);
477 output.Write (" += ");
478 GenerateExpression (statement.Listener);
479 output.WriteLine (';');
482 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
484 TextWriter output = Output;
485 GenerateEventReferenceExpression (statement.Event);
486 output.Write (" -= ");
487 GenerateExpression (statement.Listener);
488 output.WriteLine (';');
491 protected override void GenerateGotoStatement (CodeGotoStatement statement)
493 TextWriter output = Output;
495 output.Write ("goto ");
496 output.Write (GetSafeName (statement.Label));
497 output.WriteLine (";");
500 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
503 Output.Write (statement.Label);
504 Output.WriteLine (":");
507 if (statement.Statement != null) {
508 GenerateStatement (statement.Statement);
512 protected override void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement statement)
514 TextWriter output = Output;
516 OutputTypeNamePair (statement.Type, GetSafeName (statement.Name));
518 CodeExpression initExpression = statement.InitExpression;
519 if (initExpression != null) {
520 output.Write (" = ");
521 GenerateExpression (initExpression);
524 if (!dont_write_semicolon) {
525 output.WriteLine (';');
529 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
532 Output.Write ("#line ");
533 Output.Write (linePragma.LineNumber);
534 Output.Write (" \"");
535 Output.Write (linePragma.FileName);
540 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
543 Output.WriteLine ("#line default");
546 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
548 if (IsCurrentDelegate || IsCurrentEnum) {
552 OutputAttributes (eventRef.CustomAttributes, null, false);
554 if (eventRef.PrivateImplementationType == null) {
555 OutputMemberAccessModifier (eventRef.Attributes);
558 Output.Write ("event ");
560 if (eventRef.PrivateImplementationType != null) {
561 OutputTypeNamePair (eventRef.Type,
562 eventRef.PrivateImplementationType.BaseType + "." +
565 OutputTypeNamePair (eventRef.Type, GetSafeName (eventRef.Name));
567 Output.WriteLine (';');
570 protected override void GenerateField (CodeMemberField field)
572 if (IsCurrentDelegate || IsCurrentInterface) {
576 TextWriter output = Output;
578 OutputAttributes (field.CustomAttributes, null, false);
581 Output.Write (GetSafeName (field.Name));
583 MemberAttributes attributes = field.Attributes;
584 OutputMemberAccessModifier (attributes);
585 OutputVTableModifier (attributes);
586 OutputFieldScopeModifier (attributes);
588 OutputTypeNamePair (field.Type, GetSafeName (field.Name));
591 CodeExpression initExpression = field.InitExpression;
592 if (initExpression != null) {
593 output.Write (" = ");
594 GenerateExpression (initExpression);
598 output.WriteLine (',');
600 output.WriteLine (';');
603 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
605 Output.Write (member.Text);
608 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method,
609 CodeTypeDeclaration declaration)
612 OutputAttributes (method.CustomAttributes, null, false);
615 Output.Write ("public static ");
617 OutputType (method.ReturnType);
619 Output.Write ("void");
621 Output.Write (" Main()");
624 GenerateStatements (method.Statements);
626 Output.WriteLine ("}");
629 protected override void GenerateMethod (CodeMemberMethod method,
630 CodeTypeDeclaration declaration)
632 if (IsCurrentDelegate || IsCurrentEnum) {
636 TextWriter output = Output;
638 OutputAttributes (method.CustomAttributes, null, false);
640 OutputAttributes (method.ReturnTypeCustomAttributes,
643 MemberAttributes attributes = method.Attributes;
645 if (!IsCurrentInterface) {
646 if (method.PrivateImplementationType == null) {
647 OutputMemberAccessModifier (attributes);
648 OutputVTableModifier (attributes);
649 OutputMemberScopeModifier (attributes);
652 OutputVTableModifier (attributes);
655 OutputType (method.ReturnType);
658 CodeTypeReference privateType = method.PrivateImplementationType;
659 if (privateType != null) {
660 output.Write (privateType.BaseType);
663 output.Write (GetSafeName (method.Name));
666 GenerateGenericsParameters (method.TypeParameters);
670 OutputParameters (method.Parameters);
674 GenerateGenericsConstraints (method.TypeParameters);
677 if ((attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract || declaration.IsInterface)
678 output.WriteLine (';');
682 GenerateStatements (method.Statements);
684 output.WriteLine ('}');
688 protected override void GenerateProperty (CodeMemberProperty property,
689 CodeTypeDeclaration declaration)
691 if (IsCurrentDelegate || IsCurrentEnum) {
695 TextWriter output = Output;
697 OutputAttributes (property.CustomAttributes, null, false);
699 MemberAttributes attributes = property.Attributes;
701 if (!IsCurrentInterface) {
702 if (property.PrivateImplementationType == null) {
703 OutputMemberAccessModifier (attributes);
704 OutputVTableModifier (attributes);
705 OutputMemberScopeModifier (attributes);
708 OutputVTableModifier (attributes);
711 OutputType (property.Type);
714 if (!IsCurrentInterface && property.PrivateImplementationType != null) {
715 output.Write (property.PrivateImplementationType.BaseType);
719 // only consider property indexer if name is Item (case-insensitive
720 // comparison) AND property has parameters
721 if (string.Compare(property.Name, "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
722 output.Write ("this[");
723 OutputParameters(property.Parameters);
726 output.Write (property.Name);
731 if (declaration.IsInterface)
733 if (property.HasGet) output.WriteLine("get;");
734 if (property.HasSet) output.WriteLine("set;");
740 output.Write ("get");
744 GenerateStatements (property.GetStatements);
747 output.WriteLine ('}');
752 output.Write ("set");
756 GenerateStatements (property.SetStatements);
759 output.WriteLine ('}');
764 output.WriteLine ('}');
767 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
769 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
773 OutputAttributes (constructor.CustomAttributes, null, false);
775 OutputMemberAccessModifier (constructor.Attributes);
776 Output.Write (GetSafeName (CurrentTypeName) + "(");
777 OutputParameters (constructor.Parameters);
779 if (constructor.BaseConstructorArgs.Count > 0) {
780 Output.WriteLine (" : ");
782 Output.Write ("base(");
783 OutputExpressionList (constructor.BaseConstructorArgs);
787 if (constructor.ChainedConstructorArgs.Count > 0) {
788 Output.WriteLine (" : ");
790 Output.Write("this(");
791 OutputExpressionList (constructor.ChainedConstructorArgs);
797 GenerateStatements (constructor.Statements);
799 Output.WriteLine ('}');
802 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
804 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
809 OutputAttributes (constructor.CustomAttributes, null, false);
812 Output.Write ("static " + GetSafeName (CurrentTypeName) + "()");
815 GenerateStatements (constructor.Statements);
817 Output.WriteLine ('}');
820 protected override void GenerateTypeStart(CodeTypeDeclaration declaration)
822 TextWriter output = Output;
824 OutputAttributes (declaration.CustomAttributes, null, false);
826 if (!IsCurrentDelegate) {
827 OutputTypeAttributes (declaration);
829 output.Write (GetSafeName (declaration.Name));
832 GenerateGenericsParameters (declaration.TypeParameters);
835 IEnumerator enumerator = declaration.BaseTypes.GetEnumerator ();
836 if (enumerator.MoveNext ()) {
837 CodeTypeReference type = (CodeTypeReference) enumerator.Current;
839 output.Write (" : ");
842 while (enumerator.MoveNext ()) {
843 type = (CodeTypeReference) enumerator.Current;
851 GenerateGenericsConstraints (declaration.TypeParameters);
856 if ((declaration.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
857 output.Write ("public ");
860 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
861 output.Write ("delegate ");
862 OutputType (delegateDecl.ReturnType);
864 output.Write (GetSafeName (declaration.Name));
866 OutputParameters (delegateDecl.Parameters);
867 output.WriteLine (");");
871 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
873 if (!IsCurrentDelegate) {
875 Output.WriteLine ("}");
879 protected override void GenerateNamespaceStart (CodeNamespace ns)
881 TextWriter output = Output;
883 string name = ns.Name;
884 if (name != null && name.Length != 0) {
885 output.Write ("namespace ");
886 output.Write (GetSafeName (name));
892 protected override void GenerateNamespaceEnd (CodeNamespace ns)
894 string name = ns.Name;
895 if (name != null && name.Length != 0) {
897 Output.WriteLine ("}");
901 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
903 TextWriter output = Output;
905 output.Write ("using ");
906 output.Write (GetSafeName (import.Namespace));
907 output.WriteLine (';');
910 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
915 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
920 private void OutputStartBrace ()
922 if (Options.BracingStyle == "C") {
923 Output.WriteLine ("");
924 Output.WriteLine ("{");
926 Output.WriteLine (" {");
930 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, bool inline)
932 foreach (CodeAttributeDeclaration att in attributes) {
933 GenerateAttributeDeclarationsStart (attributes);
934 if (prefix != null) {
935 Output.Write (prefix);
937 OutputAttributeDeclaration (att);
938 GenerateAttributeDeclarationsEnd (attributes);
947 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
949 Output.Write (attribute.Name.Replace ('+', '.'));
951 IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
952 if (enumerator.MoveNext ()) {
953 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
954 OutputAttributeArgument (argument);
956 while (enumerator.MoveNext ()) {
958 argument = (CodeAttributeArgument) enumerator.Current;
959 OutputAttributeArgument (argument);
965 protected override void OutputType (CodeTypeReference type)
967 Output.Write (GetTypeOutput (type));
970 private void OutputVTableModifier (MemberAttributes attributes)
972 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New) {
973 Output.Write ("new ");
977 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
979 switch (attributes & MemberAttributes.ScopeMask) {
980 case MemberAttributes.Static:
981 Output.Write ("static ");
983 case MemberAttributes.Const:
984 Output.Write ("const ");
991 // Note: this method should in fact be private as in .NET 2.0, the
992 // CSharpCodeGenerator no longer derives from CodeGenerator but we
993 // still need to make this change.
994 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
996 switch (attributes & MemberAttributes.AccessMask) {
997 case MemberAttributes.Assembly:
998 case MemberAttributes.FamilyAndAssembly:
999 Output.Write ("internal ");
1001 case MemberAttributes.Family:
1002 Output.Write ("protected ");
1004 case MemberAttributes.FamilyOrAssembly:
1005 Output.Write ("protected internal ");
1007 case MemberAttributes.Private:
1008 Output.Write ("private ");
1010 case MemberAttributes.Public:
1011 Output.Write ("public ");
1016 // Note: this method should in fact be private as in .NET 2.0, the
1017 // CSharpCodeGenerator no longer derives from CodeGenerator but we
1018 // still need to make this change.
1019 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1021 switch (attributes & MemberAttributes.ScopeMask) {
1022 case MemberAttributes.Abstract:
1023 Output.Write ("abstract ");
1025 case MemberAttributes.Final:
1028 case MemberAttributes.Static:
1029 Output.Write ("static ");
1031 case MemberAttributes.Override:
1032 Output.Write ("override ");
1035 MemberAttributes access = attributes & MemberAttributes.AccessMask;
1036 if (access == MemberAttributes.Assembly || access == MemberAttributes.Family || access == MemberAttributes.Public) {
1037 Output.Write ("virtual ");
1044 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1046 TextWriter output = Output;
1047 TypeAttributes attributes = declaration.TypeAttributes;
1049 switch (attributes & TypeAttributes.VisibilityMask) {
1050 case TypeAttributes.Public:
1051 case TypeAttributes.NestedPublic:
1052 output.Write ("public ");
1054 case TypeAttributes.NestedPrivate:
1055 output.Write ("private ");
1058 case TypeAttributes.NotPublic:
1059 case TypeAttributes.NestedFamANDAssem:
1060 case TypeAttributes.NestedAssembly:
1061 output.Write ("internal ");
1063 case TypeAttributes.NestedFamily:
1064 output.Write ("protected ");
1066 case TypeAttributes.NestedFamORAssem:
1067 output.Write ("protected internal ");
1072 if (declaration.IsStruct) {
1074 if (declaration.IsPartial) {
1075 output.Write ("partial ");
1078 output.Write ("struct ");
1079 } else if (declaration.IsEnum) {
1080 output.Write ("enum ");
1082 if ((attributes & TypeAttributes.Interface) != 0) {
1084 if (declaration.IsPartial) {
1085 output.Write ("partial ");
1088 output.Write ("interface ");
1090 if ((attributes & TypeAttributes.Sealed) != 0)
1091 output.Write ("sealed ");
1092 if ((attributes & TypeAttributes.Abstract) != 0)
1093 output.Write ("abstract ");
1095 if (declaration.IsPartial) {
1096 output.Write ("partial ");
1099 output.Write ("class ");
1104 [MonoTODO ("Implement missing special characters")]
1105 protected override string QuoteSnippetString (string value)
1107 // FIXME: this is weird, but works.
1108 string output = value.Replace ("\\", "\\\\");
1109 output = output.Replace ("\"", "\\\"");
1110 output = output.Replace ("\t", "\\t");
1111 output = output.Replace ("\r", "\\r");
1112 output = output.Replace ("\n", "\\n");
1114 return "\"" + output + "\"";
1117 protected override void GeneratePrimitiveExpression(CodePrimitiveExpression e)
1119 if (e.Value is char) {
1120 this.GenerateCharValue ((char) e.Value);
1122 } else if (e.Value is ushort) {
1123 ushort uc = (ushort) e.Value;
1124 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
1125 } else if (e.Value is uint) {
1126 uint ui = (uint) e.Value;
1127 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
1129 } else if (e.Value is ulong) {
1130 ulong ul = (ulong) e.Value;
1131 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
1132 Output.Write ("ul");
1133 } else if (e.Value is sbyte) {
1134 sbyte sb = (sbyte) e.Value;
1135 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
1138 base.GeneratePrimitiveExpression (e);
1142 private void GenerateCharValue (char c)
1144 Output.Write ('\'');
1148 Output.Write ("\\0");
1151 Output.Write ("\\t");
1154 Output.Write ("\\n");
1157 Output.Write ("\\r");
1160 Output.Write ("\\\"");
1163 Output.Write ("\\'");
1166 Output.Write ("\\\\");
1169 Output.Write ("\\u");
1171 Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1173 Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1177 Output.Write ("\\u");
1179 Output.Write (((int) c).ToString ("X4", CultureInfo.InvariantCulture));
1181 Output.Write (((int) c).ToString (CultureInfo.InvariantCulture));
1189 Output.Write ('\'');
1192 protected override void GenerateSingleFloatValue (float f)
1194 base.GenerateSingleFloatValue (f);
1195 base.Output.Write ('F');
1198 protected override void GenerateDecimalValue (decimal d)
1200 base.GenerateDecimalValue (d);
1201 base.Output.Write ('m');
1204 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
1206 OutputAttributes (e.CustomAttributes, null, true);
1207 OutputDirection (e.Direction);
1208 OutputType (e.Type);
1210 Output.Write (GetSafeName (e.Name));
1213 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
1215 Output.Write ("typeof(");
1216 OutputType (e.Type);
1224 protected override string CreateEscapedIdentifier (string value)
1227 throw new NullReferenceException ("Argument identifier is null.");
1228 return GetSafeName (value);
1231 protected override string CreateValidIdentifier (string value)
1234 throw new NullReferenceException ();
1236 if (keywordsTable == null)
1237 FillKeywordTable ();
1239 if (keywordsTable.Contains (value))
1245 protected override string GetTypeOutput (CodeTypeReference type)
1247 string typeOutput = null;
1249 if (type.ArrayElementType != null) {
1250 typeOutput = GetTypeOutput (type.ArrayElementType);
1252 typeOutput = DetermineTypeOutput (type);
1255 int rank = type.ArrayRank;
1258 for (--rank; rank > 0; --rank) {
1266 private string DetermineTypeOutput (CodeTypeReference type)
1268 string typeOutput = null;
1269 string baseType = type.BaseType;
1271 switch (baseType.ToLower (System.Globalization.CultureInfo.InvariantCulture)) {
1272 case "system.int32":
1275 case "system.int64":
1276 typeOutput = "long";
1278 case "system.int16":
1279 typeOutput = "short";
1281 case "system.boolean":
1282 typeOutput = "bool";
1285 typeOutput = "char";
1287 case "system.string":
1288 typeOutput = "string";
1290 case "system.object":
1291 typeOutput = "object";
1294 typeOutput = "void";
1298 typeOutput = "byte";
1300 case "system.sbyte":
1301 typeOutput = "sbyte";
1303 case "system.decimal":
1304 typeOutput = "decimal";
1306 case "system.double":
1307 typeOutput = "double";
1309 case "system.single":
1310 typeOutput = "float";
1312 case "system.uint16":
1313 typeOutput = "ushort";
1315 case "system.uint32":
1316 typeOutput = "uint";
1318 case "system.uint64":
1319 typeOutput = "ulong";
1324 StringBuilder sb = new StringBuilder (baseType.Length);
1325 if (type.Options == CodeTypeReferenceOptions.GlobalReference) {
1326 sb.Append ("global::");
1329 int lastProcessedChar = 0;
1330 for (int i = 0; i < baseType.Length; i++) {
1331 char currentChar = baseType[i];
1332 if (currentChar != '+' && currentChar != '.') {
1333 if (currentChar == '`') {
1334 sb.Append (CreateEscapedIdentifier (baseType.Substring (
1335 lastProcessedChar, i - lastProcessedChar)));
1338 // determine number of type arguments to output
1339 int typeArgCount = baseType[i] - '0';
1340 // output type arguments
1341 OutputTypeArguments (type.TypeArguments, sb, typeArgCount);
1342 // skip type argument indicator
1344 // if next character is . or +, then append .
1345 if ((i < baseType.Length) && ((baseType[i] == '+') || (baseType[i] == '.'))) {
1347 // skip character that we just processed
1350 // save postion of last processed character
1351 lastProcessedChar = i;
1354 sb.Append (CreateEscapedIdentifier (baseType.Substring (
1355 lastProcessedChar, i - lastProcessedChar)));
1359 // save postion of last processed character
1360 lastProcessedChar = i;
1364 // add characters that have not yet been processed
1365 if (lastProcessedChar < baseType.Length) {
1366 sb.Append (CreateEscapedIdentifier (baseType.Substring (lastProcessedChar)));
1369 typeOutput = sb.ToString ();
1371 typeOutput = GetSafeName (baseType);
1372 typeOutput = typeOutput.Replace ('+', '.');
1379 protected override bool IsValidIdentifier (string identifier)
1381 if (keywordsTable == null)
1382 FillKeywordTable ();
1384 return !keywordsTable.Contains (identifier);
1387 protected override bool Supports (GeneratorSupport supports)
1393 protected override void GenerateDirectives (CodeDirectiveCollection directives)
1395 foreach (CodeDirective d in directives) {
1396 if (d is CodeChecksumPragma) {
1397 GenerateCodeChecksumPragma ((CodeChecksumPragma)d);
1400 if (d is CodeRegionDirective) {
1401 GenerateCodeRegionDirective ((CodeRegionDirective)d);
1404 throw new NotImplementedException ("Unknown CodeDirective");
1408 void GenerateCodeChecksumPragma (CodeChecksumPragma pragma)
1410 Output.Write ("#pragma checksum \"");
1411 Output.Write (pragma.FileName);
1412 Output.Write ("\" \"");
1413 Output.Write (pragma.ChecksumAlgorithmId.ToString ("B"));
1414 Output.Write ("\" \"");
1415 if (pragma.ChecksumData != null) {
1416 foreach (byte b in pragma.ChecksumData) {
1417 Output.Write (b.ToString ("X2"));
1420 Output.WriteLine ("\"");
1423 void GenerateCodeRegionDirective (CodeRegionDirective region)
1425 switch (region.RegionMode) {
1426 case CodeRegionMode.Start:
1427 Output.Write ("#region ");
1428 Output.WriteLine (region.RegionText);
1430 case CodeRegionMode.End:
1431 Output.WriteLine ("#endregion");
1436 void GenerateGenericsParameters (CodeTypeParameterCollection parameters)
1438 int count = parameters.Count;
1443 for (int i = 0; i < count - 1; ++i) {
1444 Output.Write (parameters [i].Name);
1445 Output.Write (", ");
1447 Output.Write (parameters [count - 1].Name);
1451 void GenerateGenericsConstraints (CodeTypeParameterCollection parameters)
1453 int count = parameters.Count;
1458 foreach (CodeTypeParameter p in parameters) {
1459 if (p.Constraints.Count == 0)
1461 Output.WriteLine ();
1462 Output.Write ("where ");
1463 Output.Write (p.Name);
1464 Output.Write (" : ");
1466 bool is_first = true;
1467 foreach (CodeTypeReference r in p.Constraints) {
1471 Output.Write (", ");
1474 if (p.HasConstructorConstraint) {
1476 Output.Write (", ");
1477 Output.Write ("new ()");
1484 string GetTypeArguments (CodeTypeReferenceCollection collection)
1486 StringBuilder sb = new StringBuilder (" <");
1487 foreach (CodeTypeReference r in collection) {
1488 sb.Append (GetTypeOutput (r));
1492 sb [sb.Length - 1] = '>';
1493 return sb.ToString ();
1496 private void OutputTypeArguments (CodeTypeReferenceCollection typeArguments, StringBuilder sb, int count)
1504 // write first type argument
1505 sb.Append (GetTypeOutput (typeArguments[0]));
1506 // subsequent type argument are prefixed by ', ' separator
1507 for (int i = 1; i < count; i++) {
1509 sb.Append (GetTypeOutput (typeArguments[i]));
1518 public override void ValidateIdentifier (string identifier)
1523 private string GetSafeName (string id)
1525 if (keywordsTable == null) {
1526 FillKeywordTable ();
1528 if (keywordsTable.Contains (id)) {
1535 static void FillKeywordTable ()
1537 keywordsTable = new Hashtable ();
1538 foreach (string keyword in keywords) {
1539 keywordsTable.Add (keyword, keyword);
1543 private static Hashtable keywordsTable;
1544 private static string[] keywords = new string[] {
1545 "abstract","event","new","struct","as","explicit","null","switch","base","extern",
1546 "this","false","operator","throw","break","finally","out","true",
1547 "fixed","override","try","case","params","typeof","catch","for",
1548 "private","foreach","protected","checked","goto","public",
1549 "unchecked","class","if","readonly","unsafe","const","implicit","ref",
1550 "continue","in","return","using","virtual","default",
1551 "interface","sealed","volatile","delegate","internal","do","is",
1552 "sizeof","while","lock","stackalloc","else","static","enum",
1554 "object","bool","byte","float","uint","char","ulong","ushort",
1555 "decimal","int","sbyte","short","double","long","string","void",
1557 "partial", "yield", "where"