2 // System.CodeDom.Compiler.CodeGenerator.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Daniel Stodden (stodden@in.tum.de)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
10 // (C) 2001-2003 Ximian, Inc.
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Globalization;
36 using System.Reflection;
38 using System.Collections;
40 namespace System.CodeDom.Compiler {
42 public abstract class CodeGenerator : ICodeGenerator
44 private IndentedTextWriter output;
45 private CodeGeneratorOptions options;
46 private CodeTypeMember currentMember;
47 private CodeTypeDeclaration currentType;
52 protected CodeGenerator()
59 protected CodeTypeMember CurrentMember {
65 protected string CurrentMemberName {
67 if (currentType == null)
69 return currentMember.Name;
73 protected string CurrentTypeName {
75 if (currentType == null)
77 return currentType.Name;
81 protected int Indent {
86 output.Indent = value;
90 protected bool IsCurrentClass {
92 if (currentType == null)
94 return currentType.IsClass;
98 protected bool IsCurrentDelegate {
100 return currentType is CodeTypeDelegate;
104 protected bool IsCurrentEnum {
106 if (currentType == null)
108 return currentType.IsEnum;
112 protected bool IsCurrentInterface {
114 if (currentType == null)
116 return currentType.IsInterface;
120 protected bool IsCurrentStruct {
122 if (currentType == null)
124 return currentType.IsStruct;
128 protected abstract string NullToken {
133 protected CodeGeneratorOptions Options {
139 protected TextWriter Output {
148 protected virtual void ContinueOnNewLine (string st)
150 output.WriteLine (st);
154 * Code Generation methods
156 protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
157 protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
158 protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
159 protected abstract void GenerateAssignStatement (CodeAssignStatement s);
160 protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
161 protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
162 protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
163 protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
165 protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
168 GenerateExpression (e.Left);
170 OutputOperator (e.Operator);
172 GenerateExpression (e.Right);
176 protected abstract void GenerateCastExpression (CodeCastExpression e);
177 protected abstract void GenerateComment (CodeComment comment);
179 protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
181 GenerateComment (statement.Comment);
184 protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
186 foreach (CodeCommentStatement comment in statements)
187 GenerateCommentStatement (comment);
190 protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
192 GenerateCompileUnitStart (compileUnit);
194 CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
195 if (attributes.Count != 0) {
196 foreach (CodeAttributeDeclaration att in attributes) {
197 GenerateAttributeDeclarationsStart (attributes);
198 output.Write ("assembly: ");
199 OutputAttributeDeclaration (att);
200 GenerateAttributeDeclarationsEnd (attributes);
204 foreach (CodeNamespace ns in compileUnit.Namespaces)
205 GenerateNamespace (ns);
207 GenerateCompileUnitEnd (compileUnit);
210 protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
214 protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
218 protected abstract void GenerateConditionStatement (CodeConditionStatement s);
219 protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
221 protected virtual void GenerateDecimalValue (Decimal d)
223 Output.Write (d.ToString (CultureInfo.InvariantCulture));
226 protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
227 protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
229 protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
231 OutputDirection (e.Direction);
233 GenerateExpression (e.Expression);
236 protected virtual void GenerateDoubleValue (Double d)
238 Output.Write (d.ToString (CultureInfo.InvariantCulture));
241 protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
242 protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
243 protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
245 protected void GenerateExpression (CodeExpression e)
248 throw new ArgumentNullException ("Value cannot be null.");
250 CodeArgumentReferenceExpression argref = e as CodeArgumentReferenceExpression;
251 if (argref != null) {
252 GenerateArgumentReferenceExpression (argref);
255 CodeArrayCreateExpression mkarray = e as CodeArrayCreateExpression;
256 if (mkarray != null) {
257 GenerateArrayCreateExpression (mkarray);
260 CodeArrayIndexerExpression arrayidx = e as CodeArrayIndexerExpression;
261 if (arrayidx != null) {
262 GenerateArrayIndexerExpression (arrayidx);
265 CodeBaseReferenceExpression baseref = e as CodeBaseReferenceExpression;
266 if (baseref != null) {
267 GenerateBaseReferenceExpression (baseref);
270 CodeBinaryOperatorExpression binary = e as CodeBinaryOperatorExpression;
271 if (binary != null) {
272 GenerateBinaryOperatorExpression (binary);
275 CodeCastExpression cast = e as CodeCastExpression;
277 GenerateCastExpression (cast);
280 CodeDelegateCreateExpression mkdel = e as CodeDelegateCreateExpression;
282 GenerateDelegateCreateExpression (mkdel);
285 CodeDelegateInvokeExpression delinvoke = e as CodeDelegateInvokeExpression;
286 if (delinvoke != null) {
287 GenerateDelegateInvokeExpression (delinvoke);
290 CodeDirectionExpression direction = e as CodeDirectionExpression;
291 if (direction != null) {
292 GenerateDirectionExpression (direction);
295 CodeEventReferenceExpression eventref = e as CodeEventReferenceExpression;
296 if ( eventref != null ) {
297 GenerateEventReferenceExpression( eventref );
300 CodeFieldReferenceExpression fieldref = e as CodeFieldReferenceExpression;
301 if (fieldref != null) {
302 GenerateFieldReferenceExpression (fieldref);
305 CodeIndexerExpression idx = e as CodeIndexerExpression;
307 GenerateIndexerExpression (idx);
310 CodeMethodInvokeExpression methodinv = e as CodeMethodInvokeExpression;
311 if (methodinv != null) {
312 GenerateMethodInvokeExpression (methodinv);
315 CodeMethodReferenceExpression methodref = e as CodeMethodReferenceExpression;
316 if (methodref != null) {
317 GenerateMethodReferenceExpression (methodref);
320 CodeObjectCreateExpression objref = e as CodeObjectCreateExpression;
321 if (objref != null) {
322 GenerateObjectCreateExpression (objref);
325 CodeParameterDeclarationExpression param = e as CodeParameterDeclarationExpression;
327 GenerateParameterDeclarationExpression (param);
330 CodePrimitiveExpression primitive = e as CodePrimitiveExpression;
331 if (primitive != null) {
332 GeneratePrimitiveExpression (primitive);
335 CodePropertyReferenceExpression propref = e as CodePropertyReferenceExpression;
336 if (propref != null) {
337 GeneratePropertyReferenceExpression (propref);
340 CodePropertySetValueReferenceExpression propset = e as CodePropertySetValueReferenceExpression;
341 if (propset != null) {
342 GeneratePropertySetValueReferenceExpression (propset);
345 CodeSnippetExpression snippet = e as CodeSnippetExpression;
346 if (snippet != null) {
347 GenerateSnippetExpression (snippet);
350 CodeThisReferenceExpression thisref = e as CodeThisReferenceExpression;
351 if (thisref != null) {
352 GenerateThisReferenceExpression (thisref);
355 CodeTypeOfExpression typeOf = e as CodeTypeOfExpression;
356 if (typeOf != null) {
357 GenerateTypeOfExpression (typeOf);
360 CodeTypeReferenceExpression typeref = e as CodeTypeReferenceExpression;
361 if (typeref != null) {
362 GenerateTypeReferenceExpression (typeref);
365 CodeVariableReferenceExpression varref = e as CodeVariableReferenceExpression;
366 if (varref != null) {
367 GenerateVariableReferenceExpression (varref);
371 throw new ArgumentException ("Element type " + e + " is not supported.");
374 protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
375 protected abstract void GenerateField (CodeMemberField f);
376 protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
377 protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
378 protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
379 protected abstract void GenerateIterationStatement (CodeIterationStatement s);
380 protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
381 protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
382 protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
383 protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
384 protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
385 protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
386 protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
388 protected virtual void GenerateNamespace (CodeNamespace ns)
390 foreach (CodeCommentStatement statement in ns.Comments)
391 GenerateCommentStatement (statement);
393 GenerateNamespaceStart (ns);
395 foreach (CodeNamespaceImport import in ns.Imports) {
396 if (import.LinePragma != null)
397 GenerateLinePragmaStart (import.LinePragma);
399 GenerateNamespaceImport (import);
401 if (import.LinePragma != null)
402 GenerateLinePragmaEnd (import.LinePragma);
407 foreach (CodeTypeDeclaration type in ns.Types) {
412 GenerateNamespaceEnd (ns);
415 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
416 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
417 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
418 protected void GenerateNamespaceImports (CodeNamespace e)
420 foreach (CodeNamespaceImport import in e.Imports) {
421 if (import.LinePragma != null)
422 GenerateLinePragmaStart (import.LinePragma);
424 GenerateNamespaceImport (import);
426 if (import.LinePragma != null)
427 GenerateLinePragmaEnd (import.LinePragma);
431 protected void GenerateNamespaces (CodeCompileUnit e)
433 foreach (CodeNamespace ns in e.Namespaces)
434 GenerateNamespace (ns);
437 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
439 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
441 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
442 OutputAttributeDeclarations (e.CustomAttributes);
443 OutputDirection (e.Direction);
446 output.Write (e.Name);
449 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
451 if (e.Value == null) {
452 output.Write (NullToken);
456 Type type = e.Value.GetType ();
457 if (type == typeof (bool)) {
458 output.Write (e.Value.ToString ().ToLower (CultureInfo.InvariantCulture));
459 } else if (type == typeof (char)) {
460 output.Write ("'" + e.Value.ToString () + "'");
461 } else if (type == typeof (string)) {
462 output.Write (QuoteSnippetString ((string) e.Value));
463 } else if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) ||
464 type == typeof (int) || type == typeof (long) || type == typeof (float) ||
465 type == typeof (double) || type == typeof (decimal)) {
466 // All of these should be IFormatable, I am just being safe/slow
467 IFormattable formattable = e.Value as IFormattable;
468 if (formattable != null)
469 output.Write (formattable.ToString (null, CultureInfo.InvariantCulture));
471 output.Write (e.Value.ToString ());
473 throw new ArgumentException ("Value type (" + type + ") is not a primitive type");
477 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
478 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
479 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
480 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
482 protected virtual void GenerateSingleFloatValue (Single s)
484 output.Write (s.ToString(CultureInfo.InvariantCulture));
487 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
489 if (e.LinePragma != null)
490 GenerateLinePragmaStart (e.LinePragma);
492 output.WriteLine (e.Value);
494 if (e.LinePragma != null)
495 GenerateLinePragmaEnd (e.LinePragma);
499 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
500 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
501 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
503 output.WriteLine (s.Value);
506 protected void GenerateStatement (CodeStatement s)
508 bool handled = false;
510 if (s.LinePragma != null)
511 GenerateLinePragmaStart (s.LinePragma);
513 CodeAssignStatement assign = s as CodeAssignStatement;
514 if (assign != null) {
515 GenerateAssignStatement (assign);
518 CodeAttachEventStatement attach = s as CodeAttachEventStatement;
519 if (attach != null) {
520 GenerateAttachEventStatement (attach);
523 CodeCommentStatement comment = s as CodeCommentStatement;
524 if (comment != null) {
525 GenerateCommentStatement (comment);
528 CodeConditionStatement condition = s as CodeConditionStatement;
529 if (condition != null) {
530 GenerateConditionStatement (condition);
533 CodeExpressionStatement expression = s as CodeExpressionStatement;
534 if (expression != null) {
535 GenerateExpressionStatement (expression);
538 CodeGotoStatement gotostmt = s as CodeGotoStatement;
539 if (gotostmt != null) {
540 GenerateGotoStatement (gotostmt);
543 CodeIterationStatement iteration = s as CodeIterationStatement;
544 if (iteration != null) {
545 GenerateIterationStatement (iteration);
548 CodeLabeledStatement label = s as CodeLabeledStatement;
550 GenerateLabeledStatement (label);
553 CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
554 if (returnstmt != null) {
555 GenerateMethodReturnStatement (returnstmt);
558 CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
559 if (remove != null) {
560 GenerateRemoveEventStatement (remove);
563 CodeSnippetStatement snippet = s as CodeSnippetStatement;
564 if (snippet != null) {
565 GenerateSnippetStatement (snippet);
568 CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
569 if (exception != null) {
570 GenerateThrowExceptionStatement (exception);
573 CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
574 if (trycatch != null) {
575 GenerateTryCatchFinallyStatement (trycatch);
578 CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
579 if (declaration != null) {
580 GenerateVariableDeclarationStatement (declaration);
585 throw new ArgumentException ("Element type " + s + " is not supported.");
587 if (s.LinePragma != null)
588 GenerateLinePragmaEnd (s.LinePragma);
592 protected void GenerateStatements (CodeStatementCollection c)
594 foreach (CodeStatement statement in c)
595 GenerateStatement (statement);
598 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
599 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
600 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
601 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
602 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
604 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
606 output.Write ("typeof(");
611 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
616 protected void GenerateTypes (CodeNamespace e)
618 foreach (CodeTypeDeclaration type in e.Types)
622 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
623 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
624 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
633 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
635 string name = argument.Name;
640 GenerateExpression (argument.Value);
643 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
645 output.Write (attribute.Name);
647 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
648 if (enumerator.MoveNext()) {
649 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
650 OutputAttributeArgument (argument);
652 while (enumerator.MoveNext()) {
654 argument = (CodeAttributeArgument)enumerator.Current;
655 OutputAttributeArgument (argument);
661 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
663 GenerateAttributeDeclarationsStart (attributes);
665 IEnumerator enumerator = attributes.GetEnumerator();
666 if (enumerator.MoveNext()) {
667 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
669 OutputAttributeDeclaration (attribute);
671 while (enumerator.MoveNext()) {
672 attribute = (CodeAttributeDeclaration)enumerator.Current;
674 output.WriteLine (',');
675 OutputAttributeDeclaration (attribute);
679 GenerateAttributeDeclarationsEnd (attributes);
682 protected virtual void OutputDirection (FieldDirection direction)
685 case FieldDirection.In:
686 //output.Write ("in ");
688 case FieldDirection.Out:
689 output.Write ("out ");
691 case FieldDirection.Ref:
692 output.Write ("ref ");
697 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
699 OutputExpressionList (expressions, false);
702 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
703 bool newLineBetweenItems)
705 IEnumerator enumerator = expressions.GetEnumerator();
706 if (enumerator.MoveNext()) {
707 CodeExpression expression = (CodeExpression)enumerator.Current;
709 GenerateExpression (expression);
711 while (enumerator.MoveNext()) {
712 expression = (CodeExpression)enumerator.Current;
715 if (newLineBetweenItems)
720 GenerateExpression (expression);
725 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
727 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
728 output.Write ("new ");
730 switch (attributes & MemberAttributes.ScopeMask) {
731 case MemberAttributes.Static:
732 output.Write ("static ");
734 case MemberAttributes.Const:
735 output.Write ("const ");
740 protected virtual void OutputIdentifier (string ident)
742 output.Write (ident);
745 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
747 switch (attributes & MemberAttributes.AccessMask) {
748 case MemberAttributes.Assembly:
749 output.Write ("internal ");
751 case MemberAttributes.FamilyAndAssembly:
752 output.Write ("/* FamAndAssem */ internal ");
754 case MemberAttributes.Family:
755 output.Write ("protected ");
757 case MemberAttributes.FamilyOrAssembly:
758 output.Write ("protected internal ");
760 case MemberAttributes.Private:
761 output.Write ("private ");
763 case MemberAttributes.Public:
764 output.Write ("public ");
769 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
771 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
772 output.Write( "new " );
774 switch (attributes & MemberAttributes.ScopeMask) {
775 case MemberAttributes.Abstract:
776 output.Write ("abstract ");
778 case MemberAttributes.Final:
781 case MemberAttributes.Static:
782 output.Write ("static ");
784 case MemberAttributes.Override:
785 output.Write ("override ");
789 // FUNNY! if the scope value is
790 // rubbish (0 or >Const), and access
791 // is public or protected, make it
794 // i'm not sure whether this is 100%
795 // correct, but it seems to be MS
798 MemberAttributes access = attributes & MemberAttributes.AccessMask;
799 if (access == MemberAttributes.Public ||
800 access == MemberAttributes.Family)
801 output.Write ("virtual ");
806 protected virtual void OutputOperator (CodeBinaryOperatorType op)
809 case CodeBinaryOperatorType.Add:
812 case CodeBinaryOperatorType.Subtract:
815 case CodeBinaryOperatorType.Multiply:
818 case CodeBinaryOperatorType.Divide:
821 case CodeBinaryOperatorType.Modulus:
824 case CodeBinaryOperatorType.Assign:
827 case CodeBinaryOperatorType.IdentityInequality:
830 case CodeBinaryOperatorType.IdentityEquality:
833 case CodeBinaryOperatorType.ValueEquality:
836 case CodeBinaryOperatorType.BitwiseOr:
839 case CodeBinaryOperatorType.BitwiseAnd:
842 case CodeBinaryOperatorType.BooleanOr:
845 case CodeBinaryOperatorType.BooleanAnd:
848 case CodeBinaryOperatorType.LessThan:
851 case CodeBinaryOperatorType.LessThanOrEqual:
854 case CodeBinaryOperatorType.GreaterThan:
857 case CodeBinaryOperatorType.GreaterThanOrEqual:
863 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
866 foreach (CodeParameterDeclarationExpression expr in parameters) {
871 GenerateExpression (expr);
875 protected abstract void OutputType (CodeTypeReference t);
877 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
881 switch (attributes & TypeAttributes.VisibilityMask) {
882 case TypeAttributes.NotPublic:
883 // private by default
886 case TypeAttributes.Public:
887 case TypeAttributes.NestedPublic:
888 output.Write ("public ");
891 case TypeAttributes.NestedPrivate:
892 output.Write ("private ");
897 output.Write ("struct ");
900 output.Write ("enum ");
902 if ((attributes & TypeAttributes.Interface) != 0)
903 output.Write ("interface ");
904 else if (currentType is CodeTypeDelegate)
905 output.Write ("delegate ");
907 if ((attributes & TypeAttributes.Sealed) != 0)
908 output.Write ("sealed ");
909 if ((attributes & TypeAttributes.Abstract) != 0)
910 output.Write ("abstract ");
912 output.Write ("class ");
917 protected virtual void OutputTypeNamePair (CodeTypeReference type,
925 protected abstract string QuoteSnippetString (string value);
930 protected abstract string CreateEscapedIdentifier (string value);
931 string ICodeGenerator.CreateEscapedIdentifier (string value)
933 return CreateEscapedIdentifier (value);
936 protected abstract string CreateValidIdentifier (string value);
937 string ICodeGenerator.CreateValidIdentifier (string value)
939 return CreateValidIdentifier (value);
942 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
945 options = new CodeGeneratorOptions ();
947 this.output = new IndentedTextWriter (output, options.IndentString);
948 this.options = options;
951 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
953 CodeGeneratorOptions options)
955 InitOutput (output, options);
956 GenerateCompileUnit (compileUnit);
959 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
961 CodeGeneratorOptions options)
963 InitOutput (output, options);
964 GenerateExpression (expression);
967 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
969 CodeGeneratorOptions options)
971 InitOutput (output, options);
972 GenerateNamespace (ns);
975 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
977 CodeGeneratorOptions options)
979 InitOutput (output, options);
980 GenerateStatement (statement);
983 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
985 CodeGeneratorOptions options)
987 InitOutput (output, options);
991 private void GenerateType (CodeTypeDeclaration type)
993 if (type.LinePragma != null)
994 GenerateLinePragmaStart (type.LinePragma);
996 CodeTypeDelegate del = type as CodeTypeDelegate;
998 GenerateDelegate (del);
1000 GenerateNonDelegateType (type);
1002 if (type.LinePragma != null)
1003 GenerateLinePragmaEnd (type.LinePragma);
1006 private void GenerateDelegate (CodeTypeDelegate type)
1008 CodeTypeDeclaration prevType = this.currentType;
1009 this.currentType = type;
1011 foreach (CodeCommentStatement statement in type.Comments)
1012 GenerateCommentStatement (statement);
1014 GenerateTypeStart (type);
1016 OutputParameters (type.Parameters);
1018 GenerateTypeEnd (type);
1019 this.currentType = prevType;
1022 private void GenerateNonDelegateType (CodeTypeDeclaration type)
1024 CodeTypeDeclaration prevType = this.currentType;
1025 this.currentType = type;
1027 foreach (CodeCommentStatement statement in type.Comments)
1028 GenerateCommentStatement (statement);
1030 GenerateTypeStart (type);
1032 CodeTypeMember [] members = new CodeTypeMember [type.Members.Count];
1033 type.Members.CopyTo (members, 0);
1035 int[] order = new int[members.Length];
1036 for (int n=0; n<members.Length; n++)
1037 order[n] = Array.IndexOf(memberTypes, members[n].GetType()) * members.Length + n;
1039 Array.Sort (order, members);
1041 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
1042 // its corresponding place in CodeTypeMemberComparer class (below)
1044 foreach (CodeTypeMember member in members)
1047 CodeTypeMember prevMember = this.currentMember;
1048 this.currentMember = member;
1050 if (prevMember != null && prevMember.LinePragma != null)
1051 GenerateLinePragmaEnd (prevMember.LinePragma);
1053 if (options.BlankLinesBetweenMembers)
1054 output.WriteLine ();
1056 foreach (CodeCommentStatement statement in member.Comments)
1057 GenerateCommentStatement (statement);
1059 if (member.LinePragma != null)
1060 GenerateLinePragmaStart (member.LinePragma);
1062 CodeMemberEvent eventm = member as CodeMemberEvent;
1065 GenerateEvent (eventm, type);
1068 CodeMemberField field = member as CodeMemberField;
1071 GenerateField (field);
1074 CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
1075 if (epmethod != null)
1077 GenerateEntryPointMethod (epmethod, type);
1080 CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
1081 if (typeCtor != null)
1083 GenerateTypeConstructor (typeCtor);
1086 CodeConstructor ctor = member as CodeConstructor;
1089 GenerateConstructor (ctor, type);
1092 CodeMemberMethod method = member as CodeMemberMethod;
1095 GenerateMethod (method, type);
1098 CodeMemberProperty property = member as CodeMemberProperty;
1099 if (property != null)
1101 GenerateProperty (property, type);
1104 CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
1105 if (snippet != null)
1107 GenerateSnippetMember (snippet);
1110 CodeTypeDeclaration subtype = member as CodeTypeDeclaration;
1111 if (subtype != null)
1113 GenerateType (subtype);
1117 this.currentMember = prevMember;
1120 if (currentMember != null && currentMember.LinePragma != null)
1121 GenerateLinePragmaEnd (currentMember.LinePragma);
1123 GenerateTypeEnd (type);
1124 this.currentType = prevType;
1127 protected abstract string GetTypeOutput (CodeTypeReference type);
1129 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
1131 return GetTypeOutput (type);
1134 protected abstract bool IsValidIdentifier (string value);
1136 bool ICodeGenerator.IsValidIdentifier (string value)
1138 return IsValidIdentifier (value);
1141 public static bool IsValidLanguageIndependentIdentifier (string value)
1145 if (value.Equals (string.Empty))
1147 switch (char.GetUnicodeCategory (value[0]))
1149 case UnicodeCategory.LetterNumber:
1150 case UnicodeCategory.LowercaseLetter:
1151 case UnicodeCategory.TitlecaseLetter:
1152 case UnicodeCategory.UppercaseLetter:
1153 case UnicodeCategory.OtherLetter:
1154 case UnicodeCategory.ModifierLetter:
1155 case UnicodeCategory.ConnectorPunctuation:
1156 if (value.Length > 1)
1158 for (int x = 0; x < value.Length; x++)
1160 switch (char.GetUnicodeCategory (value[x]))
1162 case UnicodeCategory.LetterNumber:
1163 case UnicodeCategory.LowercaseLetter:
1164 case UnicodeCategory.TitlecaseLetter:
1165 case UnicodeCategory.UppercaseLetter:
1166 case UnicodeCategory.OtherLetter:
1167 case UnicodeCategory.ModifierLetter:
1168 case UnicodeCategory.ConnectorPunctuation:
1169 case UnicodeCategory.DecimalDigitNumber:
1170 case UnicodeCategory.NonSpacingMark:
1171 case UnicodeCategory.SpacingCombiningMark:
1172 case UnicodeCategory.Format:
1185 protected abstract bool Supports (GeneratorSupport supports);
1187 bool ICodeGenerator.Supports (GeneratorSupport value)
1189 return Supports (value);
1192 protected virtual void ValidateIdentifier (string value)
1194 if (!(IsValidIdentifier (value)))
1195 throw new ArgumentException ("Identifier is invalid", "value");
1199 public static void ValidateIdentifiers (CodeObject e)
1201 throw new NotImplementedException();
1204 void ICodeGenerator.ValidateIdentifier (string value)
1206 ValidateIdentifier (value);
1209 // The position in the array determines the order in which those
1210 // kind of CodeTypeMembers are generated. Less is more ;-)
1211 static Type [] memberTypes = { typeof (CodeMemberField),
1212 typeof (CodeSnippetTypeMember),
1213 typeof (CodeTypeConstructor),
1214 typeof (CodeConstructor),
1215 typeof (CodeMemberProperty),
1216 typeof (CodeMemberEvent),
1217 typeof (CodeMemberMethod),
1218 typeof (CodeTypeDeclaration),
1219 typeof (CodeEntryPointMethod)