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)
9 // Marek Safar (marek.safar@seznam.cz)
11 // (C) 2001-2003 Ximian, Inc.
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Globalization;
37 using System.Reflection;
39 using System.Collections;
41 namespace System.CodeDom.Compiler {
43 public abstract class CodeGenerator : ICodeGenerator
45 private IndentedTextWriter output;
46 private CodeGeneratorOptions options;
47 private CodeTypeMember currentMember;
48 private CodeTypeDeclaration currentType;
53 protected CodeGenerator()
60 protected CodeTypeMember CurrentMember {
66 protected string CurrentMemberName {
68 if (currentType == null)
70 return currentMember.Name;
74 protected string CurrentTypeName {
76 if (currentType == null)
78 return currentType.Name;
82 protected int Indent {
87 output.Indent = value;
91 protected bool IsCurrentClass {
93 if (currentType == null)
95 return currentType.IsClass;
99 protected bool IsCurrentDelegate {
101 return currentType is CodeTypeDelegate;
105 protected bool IsCurrentEnum {
107 if (currentType == null)
109 return currentType.IsEnum;
113 protected bool IsCurrentInterface {
115 if (currentType == null)
117 return currentType.IsInterface;
121 protected bool IsCurrentStruct {
123 if (currentType == null)
125 return currentType.IsStruct;
129 protected abstract string NullToken {
134 protected CodeGeneratorOptions Options {
140 protected TextWriter Output {
149 protected virtual void ContinueOnNewLine (string st)
151 output.WriteLine (st);
155 * Code Generation methods
157 protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
158 protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
159 protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
160 protected abstract void GenerateAssignStatement (CodeAssignStatement s);
161 protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
162 protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
163 protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
164 protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
166 protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
169 GenerateExpression (e.Left);
171 OutputOperator (e.Operator);
173 GenerateExpression (e.Right);
177 protected abstract void GenerateCastExpression (CodeCastExpression e);
178 protected abstract void GenerateComment (CodeComment comment);
180 protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
182 GenerateComment (statement.Comment);
185 protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
187 foreach (CodeCommentStatement comment in statements)
188 GenerateCommentStatement (comment);
191 protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
193 GenerateCompileUnitStart (compileUnit);
195 CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
196 if (attributes.Count != 0) {
197 foreach (CodeAttributeDeclaration att in attributes) {
198 GenerateAttributeDeclarationsStart (attributes);
199 output.Write ("assembly: ");
200 OutputAttributeDeclaration (att);
201 GenerateAttributeDeclarationsEnd (attributes);
206 foreach (CodeNamespace ns in compileUnit.Namespaces)
207 GenerateNamespace (ns);
209 GenerateCompileUnitEnd (compileUnit);
212 protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
215 if (compileUnit.EndDirectives.Count > 0)
216 GenerateDirectives (compileUnit.EndDirectives);
220 protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
223 if (compileUnit.StartDirectives.Count > 0) {
224 GenerateDirectives (compileUnit.StartDirectives);
230 protected abstract void GenerateConditionStatement (CodeConditionStatement s);
231 protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
233 protected virtual void GenerateDecimalValue (Decimal d)
235 Output.Write (d.ToString (CultureInfo.InvariantCulture));
238 protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
239 protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
241 protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
243 OutputDirection (e.Direction);
245 GenerateExpression (e.Expression);
248 protected virtual void GenerateDoubleValue (Double d)
250 Output.Write (d.ToString (CultureInfo.InvariantCulture));
253 protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
254 protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
255 protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
257 protected void GenerateExpression (CodeExpression e)
260 throw new ArgumentNullException ("Value cannot be null.");
262 CodeArgumentReferenceExpression argref = e as CodeArgumentReferenceExpression;
263 if (argref != null) {
264 GenerateArgumentReferenceExpression (argref);
267 CodeArrayCreateExpression mkarray = e as CodeArrayCreateExpression;
268 if (mkarray != null) {
269 GenerateArrayCreateExpression (mkarray);
272 CodeArrayIndexerExpression arrayidx = e as CodeArrayIndexerExpression;
273 if (arrayidx != null) {
274 GenerateArrayIndexerExpression (arrayidx);
277 CodeBaseReferenceExpression baseref = e as CodeBaseReferenceExpression;
278 if (baseref != null) {
279 GenerateBaseReferenceExpression (baseref);
282 CodeBinaryOperatorExpression binary = e as CodeBinaryOperatorExpression;
283 if (binary != null) {
284 GenerateBinaryOperatorExpression (binary);
287 CodeCastExpression cast = e as CodeCastExpression;
289 GenerateCastExpression (cast);
292 CodeDelegateCreateExpression mkdel = e as CodeDelegateCreateExpression;
294 GenerateDelegateCreateExpression (mkdel);
297 CodeDelegateInvokeExpression delinvoke = e as CodeDelegateInvokeExpression;
298 if (delinvoke != null) {
299 GenerateDelegateInvokeExpression (delinvoke);
302 CodeDirectionExpression direction = e as CodeDirectionExpression;
303 if (direction != null) {
304 GenerateDirectionExpression (direction);
307 CodeEventReferenceExpression eventref = e as CodeEventReferenceExpression;
308 if ( eventref != null ) {
309 GenerateEventReferenceExpression( eventref );
312 CodeFieldReferenceExpression fieldref = e as CodeFieldReferenceExpression;
313 if (fieldref != null) {
314 GenerateFieldReferenceExpression (fieldref);
317 CodeIndexerExpression idx = e as CodeIndexerExpression;
319 GenerateIndexerExpression (idx);
322 CodeMethodInvokeExpression methodinv = e as CodeMethodInvokeExpression;
323 if (methodinv != null) {
324 GenerateMethodInvokeExpression (methodinv);
327 CodeMethodReferenceExpression methodref = e as CodeMethodReferenceExpression;
328 if (methodref != null) {
329 GenerateMethodReferenceExpression (methodref);
332 CodeObjectCreateExpression objref = e as CodeObjectCreateExpression;
333 if (objref != null) {
334 GenerateObjectCreateExpression (objref);
337 CodeParameterDeclarationExpression param = e as CodeParameterDeclarationExpression;
339 GenerateParameterDeclarationExpression (param);
342 CodePrimitiveExpression primitive = e as CodePrimitiveExpression;
343 if (primitive != null) {
344 GeneratePrimitiveExpression (primitive);
347 CodePropertyReferenceExpression propref = e as CodePropertyReferenceExpression;
348 if (propref != null) {
349 GeneratePropertyReferenceExpression (propref);
352 CodePropertySetValueReferenceExpression propset = e as CodePropertySetValueReferenceExpression;
353 if (propset != null) {
354 GeneratePropertySetValueReferenceExpression (propset);
357 CodeSnippetExpression snippet = e as CodeSnippetExpression;
358 if (snippet != null) {
359 GenerateSnippetExpression (snippet);
362 CodeThisReferenceExpression thisref = e as CodeThisReferenceExpression;
363 if (thisref != null) {
364 GenerateThisReferenceExpression (thisref);
367 CodeTypeOfExpression typeOf = e as CodeTypeOfExpression;
368 if (typeOf != null) {
369 GenerateTypeOfExpression (typeOf);
372 CodeTypeReferenceExpression typeref = e as CodeTypeReferenceExpression;
373 if (typeref != null) {
374 GenerateTypeReferenceExpression (typeref);
377 CodeVariableReferenceExpression varref = e as CodeVariableReferenceExpression;
378 if (varref != null) {
379 GenerateVariableReferenceExpression (varref);
383 throw new ArgumentException ("Element type " + e + " is not supported.");
386 protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
387 protected abstract void GenerateField (CodeMemberField f);
388 protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
389 protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
390 protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
391 protected abstract void GenerateIterationStatement (CodeIterationStatement s);
392 protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
393 protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
394 protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
395 protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
396 protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
397 protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
398 protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
400 protected virtual void GenerateNamespace (CodeNamespace ns)
402 foreach (CodeCommentStatement statement in ns.Comments)
403 GenerateCommentStatement (statement);
405 GenerateNamespaceStart (ns);
407 foreach (CodeNamespaceImport import in ns.Imports) {
408 if (import.LinePragma != null)
409 GenerateLinePragmaStart (import.LinePragma);
411 GenerateNamespaceImport (import);
413 if (import.LinePragma != null)
414 GenerateLinePragmaEnd (import.LinePragma);
419 foreach (CodeTypeDeclaration type in ns.Types) {
424 GenerateNamespaceEnd (ns);
427 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
428 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
429 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
430 protected void GenerateNamespaceImports (CodeNamespace e)
432 foreach (CodeNamespaceImport import in e.Imports) {
433 if (import.LinePragma != null)
434 GenerateLinePragmaStart (import.LinePragma);
436 GenerateNamespaceImport (import);
438 if (import.LinePragma != null)
439 GenerateLinePragmaEnd (import.LinePragma);
443 protected void GenerateNamespaces (CodeCompileUnit e)
445 foreach (CodeNamespace ns in e.Namespaces)
446 GenerateNamespace (ns);
449 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
451 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
453 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
454 OutputAttributeDeclarations (e.CustomAttributes);
455 OutputDirection (e.Direction);
458 output.Write (e.Name);
461 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
463 if (e.Value == null) {
464 output.Write (NullToken);
468 Console.Write (e.Value.GetType ());
469 Type type = e.Value.GetType ();
470 if (type == typeof (bool)) {
471 output.Write (e.Value.ToString ().ToLower (CultureInfo.InvariantCulture));
472 } else if (type == typeof (char)) {
473 output.Write ("'" + e.Value.ToString () + "'");
474 } else if (type == typeof (string)) {
475 output.Write (QuoteSnippetString ((string) e.Value));
476 } else if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) ||
477 type == typeof (int) || type == typeof (long) || type == typeof (float) ||
478 type == typeof (double) || type == typeof (decimal)) {
479 // All of these should be IFormatable, I am just being safe/slow
480 IFormattable formattable = e.Value as IFormattable;
481 if (formattable != null)
482 output.Write (formattable.ToString (null, CultureInfo.InvariantCulture));
484 output.Write (e.Value.ToString ());
486 if (type == typeof (float))
489 throw new ArgumentException ("Value type (" + type + ") is not a primitive type");
493 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
494 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
495 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
496 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
498 protected virtual void GenerateSingleFloatValue (Single s)
500 output.Write (s.ToString(CultureInfo.InvariantCulture));
503 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
505 if (e.LinePragma != null)
506 GenerateLinePragmaStart (e.LinePragma);
508 output.WriteLine (e.Value);
510 if (e.LinePragma != null)
511 GenerateLinePragmaEnd (e.LinePragma);
515 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
516 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
517 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
519 output.WriteLine (s.Value);
522 protected void GenerateStatement (CodeStatement s)
524 bool handled = false;
527 if (s.StartDirectives.Count > 0)
528 GenerateDirectives (s.StartDirectives);
530 if (s.LinePragma != null)
531 GenerateLinePragmaStart (s.LinePragma);
533 CodeAssignStatement assign = s as CodeAssignStatement;
534 if (assign != null) {
535 GenerateAssignStatement (assign);
538 CodeAttachEventStatement attach = s as CodeAttachEventStatement;
539 if (attach != null) {
540 GenerateAttachEventStatement (attach);
543 CodeCommentStatement comment = s as CodeCommentStatement;
544 if (comment != null) {
545 GenerateCommentStatement (comment);
548 CodeConditionStatement condition = s as CodeConditionStatement;
549 if (condition != null) {
550 GenerateConditionStatement (condition);
553 CodeExpressionStatement expression = s as CodeExpressionStatement;
554 if (expression != null) {
555 GenerateExpressionStatement (expression);
558 CodeGotoStatement gotostmt = s as CodeGotoStatement;
559 if (gotostmt != null) {
560 GenerateGotoStatement (gotostmt);
563 CodeIterationStatement iteration = s as CodeIterationStatement;
564 if (iteration != null) {
565 GenerateIterationStatement (iteration);
568 CodeLabeledStatement label = s as CodeLabeledStatement;
570 GenerateLabeledStatement (label);
573 CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
574 if (returnstmt != null) {
575 GenerateMethodReturnStatement (returnstmt);
578 CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
579 if (remove != null) {
580 GenerateRemoveEventStatement (remove);
583 CodeSnippetStatement snippet = s as CodeSnippetStatement;
584 if (snippet != null) {
585 GenerateSnippetStatement (snippet);
588 CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
589 if (exception != null) {
590 GenerateThrowExceptionStatement (exception);
593 CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
594 if (trycatch != null) {
595 GenerateTryCatchFinallyStatement (trycatch);
598 CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
599 if (declaration != null) {
600 GenerateVariableDeclarationStatement (declaration);
605 throw new ArgumentException ("Element type " + s + " is not supported.");
607 if (s.LinePragma != null)
608 GenerateLinePragmaEnd (s.LinePragma);
611 if (s.EndDirectives.Count > 0)
612 GenerateDirectives (s.EndDirectives);
616 protected void GenerateStatements (CodeStatementCollection c)
618 foreach (CodeStatement statement in c)
619 GenerateStatement (statement);
622 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
623 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
624 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
625 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
626 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
628 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
630 output.Write ("typeof(");
635 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
640 protected void GenerateTypes (CodeNamespace e)
642 foreach (CodeTypeDeclaration type in e.Types)
646 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
647 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
648 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
657 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
659 string name = argument.Name;
664 GenerateExpression (argument.Value);
667 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
669 output.Write (attribute.Name.Replace ('+', '.'));
671 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
672 if (enumerator.MoveNext()) {
673 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
674 OutputAttributeArgument (argument);
676 while (enumerator.MoveNext()) {
678 argument = (CodeAttributeArgument)enumerator.Current;
679 OutputAttributeArgument (argument);
685 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
687 GenerateAttributeDeclarationsStart (attributes);
689 IEnumerator enumerator = attributes.GetEnumerator();
690 if (enumerator.MoveNext()) {
691 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
693 OutputAttributeDeclaration (attribute);
695 while (enumerator.MoveNext()) {
696 attribute = (CodeAttributeDeclaration)enumerator.Current;
698 output.WriteLine (',');
699 OutputAttributeDeclaration (attribute);
703 GenerateAttributeDeclarationsEnd (attributes);
706 protected virtual void OutputDirection (FieldDirection direction)
709 case FieldDirection.In:
710 //output.Write ("in ");
712 case FieldDirection.Out:
713 output.Write ("out ");
715 case FieldDirection.Ref:
716 output.Write ("ref ");
721 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
723 OutputExpressionList (expressions, false);
726 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
727 bool newLineBetweenItems)
729 IEnumerator enumerator = expressions.GetEnumerator();
730 if (enumerator.MoveNext()) {
731 CodeExpression expression = (CodeExpression)enumerator.Current;
733 GenerateExpression (expression);
735 while (enumerator.MoveNext()) {
736 expression = (CodeExpression)enumerator.Current;
739 if (newLineBetweenItems)
744 GenerateExpression (expression);
749 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
751 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
752 output.Write ("new ");
754 switch (attributes & MemberAttributes.ScopeMask) {
755 case MemberAttributes.Static:
756 output.Write ("static ");
758 case MemberAttributes.Const:
759 output.Write ("const ");
764 protected virtual void OutputIdentifier (string ident)
766 output.Write (ident);
769 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
771 switch (attributes & MemberAttributes.AccessMask) {
772 case MemberAttributes.Assembly:
773 output.Write ("internal ");
775 case MemberAttributes.FamilyAndAssembly:
776 output.Write ("/* FamAndAssem */ internal ");
778 case MemberAttributes.Family:
779 output.Write ("protected ");
781 case MemberAttributes.FamilyOrAssembly:
782 output.Write ("protected internal ");
784 case MemberAttributes.Private:
785 output.Write ("private ");
787 case MemberAttributes.Public:
788 output.Write ("public ");
793 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
795 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
796 output.Write( "new " );
798 switch (attributes & MemberAttributes.ScopeMask) {
799 case MemberAttributes.Abstract:
800 output.Write ("abstract ");
802 case MemberAttributes.Final:
805 case MemberAttributes.Static:
806 output.Write ("static ");
808 case MemberAttributes.Override:
809 output.Write ("override ");
813 // FUNNY! if the scope value is
814 // rubbish (0 or >Const), and access
815 // is public or protected, make it
818 // i'm not sure whether this is 100%
819 // correct, but it seems to be MS
822 MemberAttributes access = attributes & MemberAttributes.AccessMask;
823 if (access == MemberAttributes.Public ||
824 access == MemberAttributes.Family)
825 output.Write ("virtual ");
830 protected virtual void OutputOperator (CodeBinaryOperatorType op)
833 case CodeBinaryOperatorType.Add:
836 case CodeBinaryOperatorType.Subtract:
839 case CodeBinaryOperatorType.Multiply:
842 case CodeBinaryOperatorType.Divide:
845 case CodeBinaryOperatorType.Modulus:
848 case CodeBinaryOperatorType.Assign:
851 case CodeBinaryOperatorType.IdentityInequality:
854 case CodeBinaryOperatorType.IdentityEquality:
857 case CodeBinaryOperatorType.ValueEquality:
860 case CodeBinaryOperatorType.BitwiseOr:
863 case CodeBinaryOperatorType.BitwiseAnd:
866 case CodeBinaryOperatorType.BooleanOr:
869 case CodeBinaryOperatorType.BooleanAnd:
872 case CodeBinaryOperatorType.LessThan:
875 case CodeBinaryOperatorType.LessThanOrEqual:
878 case CodeBinaryOperatorType.GreaterThan:
881 case CodeBinaryOperatorType.GreaterThanOrEqual:
887 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
890 foreach (CodeParameterDeclarationExpression expr in parameters) {
895 GenerateExpression (expr);
899 protected abstract void OutputType (CodeTypeReference t);
901 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
905 switch (attributes & TypeAttributes.VisibilityMask) {
906 case TypeAttributes.NotPublic:
907 // private by default
910 case TypeAttributes.Public:
911 case TypeAttributes.NestedPublic:
912 output.Write ("public ");
915 case TypeAttributes.NestedPrivate:
916 output.Write ("private ");
921 OutputExtraTypeAttribute (currentType);
924 output.Write ("struct ");
927 output.Write ("enum ");
929 if ((attributes & TypeAttributes.Interface) != 0)
930 output.Write ("interface ");
931 else if (currentType is CodeTypeDelegate)
932 output.Write ("delegate ");
934 if ((attributes & TypeAttributes.Sealed) != 0)
935 output.Write ("sealed ");
936 if ((attributes & TypeAttributes.Abstract) != 0)
937 output.Write ("abstract ");
939 OutputExtraTypeAttribute (currentType);
940 output.Write ("class ");
945 internal virtual void OutputExtraTypeAttribute (CodeTypeDeclaration type)
949 protected virtual void OutputTypeNamePair (CodeTypeReference type,
957 protected abstract string QuoteSnippetString (string value);
962 protected abstract string CreateEscapedIdentifier (string value);
963 string ICodeGenerator.CreateEscapedIdentifier (string value)
965 return CreateEscapedIdentifier (value);
968 protected abstract string CreateValidIdentifier (string value);
969 string ICodeGenerator.CreateValidIdentifier (string value)
971 return CreateValidIdentifier (value);
974 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
977 options = new CodeGeneratorOptions ();
979 this.output = new IndentedTextWriter (output, options.IndentString);
980 this.options = options;
983 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
985 CodeGeneratorOptions options)
987 InitOutput (output, options);
989 if (compileUnit is CodeSnippetCompileUnit) {
990 GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
992 GenerateCompileUnit (compileUnit);
996 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
998 CodeGeneratorOptions options)
1000 InitOutput (output, options);
1001 GenerateExpression (expression);
1004 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
1006 CodeGeneratorOptions options)
1008 InitOutput (output, options);
1009 GenerateNamespace (ns);
1012 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
1014 CodeGeneratorOptions options)
1016 InitOutput (output, options);
1017 GenerateStatement (statement);
1020 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
1022 CodeGeneratorOptions options)
1024 InitOutput (output, options);
1025 GenerateType (type);
1028 private void GenerateType (CodeTypeDeclaration type)
1031 if (type.StartDirectives.Count > 0)
1032 GenerateDirectives (type.StartDirectives);
1034 foreach (CodeCommentStatement statement in type.Comments)
1035 GenerateCommentStatement (statement);
1037 if (type.LinePragma != null)
1038 GenerateLinePragmaStart (type.LinePragma);
1040 CodeTypeDelegate del = type as CodeTypeDelegate;
1042 GenerateDelegate (del);
1044 GenerateNonDelegateType (type);
1046 if (type.LinePragma != null)
1047 GenerateLinePragmaEnd (type.LinePragma);
1050 if (type.EndDirectives.Count > 0)
1051 GenerateDirectives (type.EndDirectives);
1055 private void GenerateDelegate (CodeTypeDelegate type)
1057 CodeTypeDeclaration prevType = this.currentType;
1058 this.currentType = type;
1060 GenerateTypeStart (type);
1062 OutputParameters (type.Parameters);
1064 GenerateTypeEnd (type);
1065 this.currentType = prevType;
1068 private void GenerateNonDelegateType (CodeTypeDeclaration type)
1070 CodeTypeDeclaration prevType = this.currentType;
1071 this.currentType = type;
1073 GenerateTypeStart (type);
1075 CodeTypeMember [] members = new CodeTypeMember [type.Members.Count];
1076 type.Members.CopyTo (members, 0);
1079 if (!Options.VerbatimOrder)
1082 int[] order = new int[members.Length];
1083 for (int n=0; n<members.Length; n++)
1084 order[n] = Array.IndexOf(memberTypes, members[n].GetType()) * members.Length + n;
1086 Array.Sort (order, members);
1089 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
1090 // its corresponding place in CodeTypeMemberComparer class (below)
1092 CodeTypeDeclaration subtype = null;
1093 foreach (CodeTypeMember member in members)
1095 CodeTypeMember prevMember = this.currentMember;
1096 this.currentMember = member;
1098 if (prevMember != null && subtype == null) {
1099 if (prevMember.LinePragma != null)
1100 GenerateLinePragmaEnd (prevMember.LinePragma);
1102 if (prevMember.EndDirectives.Count > 0)
1103 GenerateDirectives (prevMember.EndDirectives);
1107 if (options.BlankLinesBetweenMembers)
1108 output.WriteLine ();
1110 subtype = member as CodeTypeDeclaration;
1111 if (subtype != null) {
1112 GenerateType (subtype);
1117 if (currentMember.StartDirectives.Count > 0)
1118 GenerateDirectives (currentMember.StartDirectives);
1120 foreach (CodeCommentStatement statement in member.Comments)
1121 GenerateCommentStatement (statement);
1123 if (member.LinePragma != null)
1124 GenerateLinePragmaStart (member.LinePragma);
1126 CodeMemberEvent eventm = member as CodeMemberEvent;
1129 GenerateEvent (eventm, type);
1132 CodeMemberField field = member as CodeMemberField;
1135 GenerateField (field);
1138 CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
1139 if (epmethod != null)
1141 GenerateEntryPointMethod (epmethod, type);
1144 CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
1145 if (typeCtor != null)
1147 GenerateTypeConstructor (typeCtor);
1150 CodeConstructor ctor = member as CodeConstructor;
1153 GenerateConstructor (ctor, type);
1156 CodeMemberMethod method = member as CodeMemberMethod;
1159 GenerateMethod (method, type);
1162 CodeMemberProperty property = member as CodeMemberProperty;
1163 if (property != null)
1165 GenerateProperty (property, type);
1168 CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
1169 if (snippet != null)
1171 GenerateSnippetMember (snippet);
1175 this.currentMember = prevMember;
1178 // Hack because of previous continue usage
1179 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
1180 if (currentMember.LinePragma != null)
1181 GenerateLinePragmaEnd (currentMember.LinePragma);
1183 if (currentMember.EndDirectives.Count > 0)
1184 GenerateDirectives (currentMember.EndDirectives);
1188 GenerateTypeEnd (type);
1189 this.currentType = prevType;
1192 protected abstract string GetTypeOutput (CodeTypeReference type);
1194 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
1196 return GetTypeOutput (type);
1199 protected abstract bool IsValidIdentifier (string value);
1201 bool ICodeGenerator.IsValidIdentifier (string value)
1203 return IsValidIdentifier (value);
1206 public static bool IsValidLanguageIndependentIdentifier (string value)
1210 if (value.Equals (string.Empty))
1212 switch (char.GetUnicodeCategory (value[0]))
1214 case UnicodeCategory.LetterNumber:
1215 case UnicodeCategory.LowercaseLetter:
1216 case UnicodeCategory.TitlecaseLetter:
1217 case UnicodeCategory.UppercaseLetter:
1218 case UnicodeCategory.OtherLetter:
1219 case UnicodeCategory.ModifierLetter:
1220 case UnicodeCategory.ConnectorPunctuation:
1221 if (value.Length > 1)
1223 for (int x = 0; x < value.Length; x++)
1225 switch (char.GetUnicodeCategory (value[x]))
1227 case UnicodeCategory.LetterNumber:
1228 case UnicodeCategory.LowercaseLetter:
1229 case UnicodeCategory.TitlecaseLetter:
1230 case UnicodeCategory.UppercaseLetter:
1231 case UnicodeCategory.OtherLetter:
1232 case UnicodeCategory.ModifierLetter:
1233 case UnicodeCategory.ConnectorPunctuation:
1234 case UnicodeCategory.DecimalDigitNumber:
1235 case UnicodeCategory.NonSpacingMark:
1236 case UnicodeCategory.SpacingCombiningMark:
1237 case UnicodeCategory.Format:
1250 protected abstract bool Supports (GeneratorSupport supports);
1252 bool ICodeGenerator.Supports (GeneratorSupport value)
1254 return Supports (value);
1257 protected virtual void ValidateIdentifier (string value)
1259 if (!(IsValidIdentifier (value)))
1260 throw new ArgumentException ("Identifier is invalid", "value");
1264 public static void ValidateIdentifiers (CodeObject e)
1266 throw new NotImplementedException();
1269 void ICodeGenerator.ValidateIdentifier (string value)
1271 ValidateIdentifier (value);
1274 // The position in the array determines the order in which those
1275 // kind of CodeTypeMembers are generated. Less is more ;-)
1276 static Type [] memberTypes = { typeof (CodeMemberField),
1277 typeof (CodeSnippetTypeMember),
1278 typeof (CodeTypeConstructor),
1279 typeof (CodeConstructor),
1280 typeof (CodeMemberProperty),
1281 typeof (CodeMemberEvent),
1282 typeof (CodeMemberMethod),
1283 typeof (CodeTypeDeclaration),
1284 typeof (CodeEntryPointMethod)
1289 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)