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()
61 protected CodeTypeDeclaration CurrentClass {
68 protected CodeTypeMember CurrentMember {
74 protected string CurrentMemberName {
76 if (currentMember == null)
77 return "<% unknown %>";
78 return currentMember.Name;
82 protected string CurrentTypeName {
84 if (currentType == null)
85 return "<% unknown %>";
86 return currentType.Name;
90 protected int Indent {
95 output.Indent = value;
99 protected bool IsCurrentClass {
101 if (currentType == null)
103 return currentType.IsClass && !(currentType is CodeTypeDelegate);
107 protected bool IsCurrentDelegate {
109 return currentType is CodeTypeDelegate;
113 protected bool IsCurrentEnum {
115 if (currentType == null)
117 return currentType.IsEnum;
121 protected bool IsCurrentInterface {
123 if (currentType == null)
125 return currentType.IsInterface;
129 protected bool IsCurrentStruct {
131 if (currentType == null)
133 return currentType.IsStruct;
137 protected abstract string NullToken {
142 protected CodeGeneratorOptions Options {
148 protected TextWriter Output {
157 protected virtual void ContinueOnNewLine (string st)
159 output.WriteLine (st);
163 * Code Generation methods
165 protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
166 protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
167 protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
168 protected abstract void GenerateAssignStatement (CodeAssignStatement s);
169 protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
170 protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
171 protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
172 protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
174 protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
177 GenerateExpression (e.Left);
179 OutputOperator (e.Operator);
181 GenerateExpression (e.Right);
185 protected abstract void GenerateCastExpression (CodeCastExpression e);
188 public virtual void GenerateCodeFromMember (CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options)
190 throw new NotImplementedException ();
193 protected abstract void GenerateComment (CodeComment comment);
195 protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
197 GenerateComment (statement.Comment);
200 protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
202 foreach (CodeCommentStatement comment in statements)
203 GenerateCommentStatement (comment);
206 protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
208 GenerateCompileUnitStart (compileUnit);
210 CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
211 if (attributes.Count != 0) {
212 foreach (CodeAttributeDeclaration att in attributes) {
213 GenerateAttributeDeclarationsStart (attributes);
214 output.Write ("assembly: ");
215 OutputAttributeDeclaration (att);
216 GenerateAttributeDeclarationsEnd (attributes);
221 foreach (CodeNamespace ns in compileUnit.Namespaces)
222 GenerateNamespace (ns);
224 GenerateCompileUnitEnd (compileUnit);
227 protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
230 if (compileUnit.EndDirectives.Count > 0)
231 GenerateDirectives (compileUnit.EndDirectives);
235 protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
238 if (compileUnit.StartDirectives.Count > 0) {
239 GenerateDirectives (compileUnit.StartDirectives);
245 protected abstract void GenerateConditionStatement (CodeConditionStatement s);
246 protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
248 protected virtual void GenerateDecimalValue (Decimal d)
250 Output.Write (d.ToString (CultureInfo.InvariantCulture));
254 protected virtual void GenerateDefaultValueExpression (CodeDefaultValueExpression e)
256 throw new NotImplementedException ();
259 protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
260 protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
262 protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
264 OutputDirection (e.Direction);
266 GenerateExpression (e.Expression);
269 protected virtual void GenerateDoubleValue (Double d)
271 Output.Write (d.ToString (CultureInfo.InvariantCulture));
274 protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
275 protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
276 protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
278 protected void GenerateExpression (CodeExpression e)
281 throw new ArgumentNullException ("Value cannot be null.");
283 CodeArgumentReferenceExpression argref = e as CodeArgumentReferenceExpression;
284 if (argref != null) {
285 GenerateArgumentReferenceExpression (argref);
288 CodeArrayCreateExpression mkarray = e as CodeArrayCreateExpression;
289 if (mkarray != null) {
290 GenerateArrayCreateExpression (mkarray);
293 CodeArrayIndexerExpression arrayidx = e as CodeArrayIndexerExpression;
294 if (arrayidx != null) {
295 GenerateArrayIndexerExpression (arrayidx);
298 CodeBaseReferenceExpression baseref = e as CodeBaseReferenceExpression;
299 if (baseref != null) {
300 GenerateBaseReferenceExpression (baseref);
303 CodeBinaryOperatorExpression binary = e as CodeBinaryOperatorExpression;
304 if (binary != null) {
305 GenerateBinaryOperatorExpression (binary);
308 CodeCastExpression cast = e as CodeCastExpression;
310 GenerateCastExpression (cast);
313 CodeDelegateCreateExpression mkdel = e as CodeDelegateCreateExpression;
315 GenerateDelegateCreateExpression (mkdel);
318 CodeDelegateInvokeExpression delinvoke = e as CodeDelegateInvokeExpression;
319 if (delinvoke != null) {
320 GenerateDelegateInvokeExpression (delinvoke);
323 CodeDirectionExpression direction = e as CodeDirectionExpression;
324 if (direction != null) {
325 GenerateDirectionExpression (direction);
328 CodeEventReferenceExpression eventref = e as CodeEventReferenceExpression;
329 if ( eventref != null ) {
330 GenerateEventReferenceExpression( eventref );
333 CodeFieldReferenceExpression fieldref = e as CodeFieldReferenceExpression;
334 if (fieldref != null) {
335 GenerateFieldReferenceExpression (fieldref);
338 CodeIndexerExpression idx = e as CodeIndexerExpression;
340 GenerateIndexerExpression (idx);
343 CodeMethodInvokeExpression methodinv = e as CodeMethodInvokeExpression;
344 if (methodinv != null) {
345 GenerateMethodInvokeExpression (methodinv);
348 CodeMethodReferenceExpression methodref = e as CodeMethodReferenceExpression;
349 if (methodref != null) {
350 GenerateMethodReferenceExpression (methodref);
353 CodeObjectCreateExpression objref = e as CodeObjectCreateExpression;
354 if (objref != null) {
355 GenerateObjectCreateExpression (objref);
358 CodeParameterDeclarationExpression param = e as CodeParameterDeclarationExpression;
360 GenerateParameterDeclarationExpression (param);
363 CodePrimitiveExpression primitive = e as CodePrimitiveExpression;
364 if (primitive != null) {
365 GeneratePrimitiveExpression (primitive);
368 CodePropertyReferenceExpression propref = e as CodePropertyReferenceExpression;
369 if (propref != null) {
370 GeneratePropertyReferenceExpression (propref);
373 CodePropertySetValueReferenceExpression propset = e as CodePropertySetValueReferenceExpression;
374 if (propset != null) {
375 GeneratePropertySetValueReferenceExpression (propset);
378 CodeSnippetExpression snippet = e as CodeSnippetExpression;
379 if (snippet != null) {
380 GenerateSnippetExpression (snippet);
383 CodeThisReferenceExpression thisref = e as CodeThisReferenceExpression;
384 if (thisref != null) {
385 GenerateThisReferenceExpression (thisref);
388 CodeTypeOfExpression typeOf = e as CodeTypeOfExpression;
389 if (typeOf != null) {
390 GenerateTypeOfExpression (typeOf);
393 CodeTypeReferenceExpression typeref = e as CodeTypeReferenceExpression;
394 if (typeref != null) {
395 GenerateTypeReferenceExpression (typeref);
398 CodeVariableReferenceExpression varref = e as CodeVariableReferenceExpression;
399 if (varref != null) {
400 GenerateVariableReferenceExpression (varref);
404 throw new ArgumentException ("Element type " + e + " is not supported.");
407 protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
408 protected abstract void GenerateField (CodeMemberField f);
409 protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
410 protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
411 protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
412 protected abstract void GenerateIterationStatement (CodeIterationStatement s);
413 protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
414 protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
415 protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
416 protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
417 protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
418 protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
419 protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
421 protected virtual void GenerateNamespace (CodeNamespace ns)
423 foreach (CodeCommentStatement statement in ns.Comments)
424 GenerateCommentStatement (statement);
426 GenerateNamespaceStart (ns);
428 foreach (CodeNamespaceImport import in ns.Imports) {
429 if (import.LinePragma != null)
430 GenerateLinePragmaStart (import.LinePragma);
432 GenerateNamespaceImport (import);
434 if (import.LinePragma != null)
435 GenerateLinePragmaEnd (import.LinePragma);
440 foreach (CodeTypeDeclaration type in ns.Types) {
445 GenerateNamespaceEnd (ns);
448 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
449 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
450 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
451 protected void GenerateNamespaceImports (CodeNamespace e)
453 foreach (CodeNamespaceImport import in e.Imports) {
454 if (import.LinePragma != null)
455 GenerateLinePragmaStart (import.LinePragma);
457 GenerateNamespaceImport (import);
459 if (import.LinePragma != null)
460 GenerateLinePragmaEnd (import.LinePragma);
464 protected void GenerateNamespaces (CodeCompileUnit e)
466 foreach (CodeNamespace ns in e.Namespaces)
467 GenerateNamespace (ns);
470 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
472 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
474 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
475 OutputAttributeDeclarations (e.CustomAttributes);
476 OutputDirection (e.Direction);
479 output.Write (e.Name);
482 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
484 if (e.Value == null) {
485 output.Write (NullToken);
489 Type type = e.Value.GetType ();
490 if (type == typeof (bool)) {
491 output.Write (e.Value.ToString ().ToLower (CultureInfo.InvariantCulture));
492 } else if (type == typeof (char)) {
493 output.Write ("'" + e.Value.ToString () + "'");
494 } else if (type == typeof (string)) {
495 output.Write (QuoteSnippetString ((string) e.Value));
496 } else if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) ||
497 type == typeof (int) || type == typeof (long) || type == typeof (float) ||
498 type == typeof (double) || type == typeof (decimal)) {
499 // All of these should be IFormatable, I am just being safe/slow
500 IFormattable formattable = e.Value as IFormattable;
501 if (formattable != null)
502 output.Write (formattable.ToString (null, CultureInfo.InvariantCulture));
504 output.Write (e.Value.ToString ());
506 if (type == typeof (float))
509 throw new ArgumentException ("Value type (" + type + ") is not a primitive type");
513 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
514 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
515 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
516 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
518 protected virtual void GenerateSingleFloatValue (Single s)
520 output.Write (s.ToString(CultureInfo.InvariantCulture));
523 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
525 if (e.LinePragma != null)
526 GenerateLinePragmaStart (e.LinePragma);
528 output.WriteLine (e.Value);
530 if (e.LinePragma != null)
531 GenerateLinePragmaEnd (e.LinePragma);
535 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
536 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
537 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
539 output.WriteLine (s.Value);
542 protected void GenerateStatement (CodeStatement s)
544 bool handled = false;
547 if (s.StartDirectives.Count > 0)
548 GenerateDirectives (s.StartDirectives);
550 if (s.LinePragma != null)
551 GenerateLinePragmaStart (s.LinePragma);
553 CodeAssignStatement assign = s as CodeAssignStatement;
554 if (assign != null) {
555 GenerateAssignStatement (assign);
558 CodeAttachEventStatement attach = s as CodeAttachEventStatement;
559 if (attach != null) {
560 GenerateAttachEventStatement (attach);
563 CodeCommentStatement comment = s as CodeCommentStatement;
564 if (comment != null) {
565 GenerateCommentStatement (comment);
568 CodeConditionStatement condition = s as CodeConditionStatement;
569 if (condition != null) {
570 GenerateConditionStatement (condition);
573 CodeExpressionStatement expression = s as CodeExpressionStatement;
574 if (expression != null) {
575 GenerateExpressionStatement (expression);
578 CodeGotoStatement gotostmt = s as CodeGotoStatement;
579 if (gotostmt != null) {
580 GenerateGotoStatement (gotostmt);
583 CodeIterationStatement iteration = s as CodeIterationStatement;
584 if (iteration != null) {
585 GenerateIterationStatement (iteration);
588 CodeLabeledStatement label = s as CodeLabeledStatement;
590 GenerateLabeledStatement (label);
593 CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
594 if (returnstmt != null) {
595 GenerateMethodReturnStatement (returnstmt);
598 CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
599 if (remove != null) {
600 GenerateRemoveEventStatement (remove);
603 CodeSnippetStatement snippet = s as CodeSnippetStatement;
604 if (snippet != null) {
605 GenerateSnippetStatement (snippet);
608 CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
609 if (exception != null) {
610 GenerateThrowExceptionStatement (exception);
613 CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
614 if (trycatch != null) {
615 GenerateTryCatchFinallyStatement (trycatch);
618 CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
619 if (declaration != null) {
620 GenerateVariableDeclarationStatement (declaration);
625 throw new ArgumentException ("Element type " + s + " is not supported.");
627 if (s.LinePragma != null)
628 GenerateLinePragmaEnd (s.LinePragma);
631 if (s.EndDirectives.Count > 0)
632 GenerateDirectives (s.EndDirectives);
636 protected void GenerateStatements (CodeStatementCollection c)
638 foreach (CodeStatement statement in c)
639 GenerateStatement (statement);
642 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
643 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
644 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
645 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
646 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
648 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
650 output.Write ("typeof(");
655 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
660 protected void GenerateTypes (CodeNamespace e)
662 foreach (CodeTypeDeclaration type in e.Types)
666 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
667 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
668 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
677 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
679 string name = argument.Name;
680 if ((name != null) && (name.Length > 0)) {
684 GenerateExpression (argument.Value);
687 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
689 output.Write (attribute.Name.Replace ('+', '.'));
691 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
692 if (enumerator.MoveNext()) {
693 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
694 OutputAttributeArgument (argument);
696 while (enumerator.MoveNext()) {
698 argument = (CodeAttributeArgument)enumerator.Current;
699 OutputAttributeArgument (argument);
705 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
707 GenerateAttributeDeclarationsStart (attributes);
709 IEnumerator enumerator = attributes.GetEnumerator();
710 if (enumerator.MoveNext()) {
711 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
713 OutputAttributeDeclaration (attribute);
715 while (enumerator.MoveNext()) {
716 attribute = (CodeAttributeDeclaration)enumerator.Current;
718 output.WriteLine (',');
719 OutputAttributeDeclaration (attribute);
723 GenerateAttributeDeclarationsEnd (attributes);
726 protected virtual void OutputDirection (FieldDirection direction)
729 case FieldDirection.In:
730 //output.Write ("in ");
732 case FieldDirection.Out:
733 output.Write ("out ");
735 case FieldDirection.Ref:
736 output.Write ("ref ");
741 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
743 OutputExpressionList (expressions, false);
746 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
747 bool newLineBetweenItems)
749 IEnumerator enumerator = expressions.GetEnumerator();
750 if (enumerator.MoveNext()) {
751 CodeExpression expression = (CodeExpression)enumerator.Current;
753 GenerateExpression (expression);
755 while (enumerator.MoveNext()) {
756 expression = (CodeExpression)enumerator.Current;
759 if (newLineBetweenItems)
764 GenerateExpression (expression);
769 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
771 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
772 output.Write ("new ");
774 switch (attributes & MemberAttributes.ScopeMask) {
775 case MemberAttributes.Static:
776 output.Write ("static ");
778 case MemberAttributes.Const:
779 output.Write ("const ");
784 protected virtual void OutputIdentifier (string ident)
786 output.Write (ident);
789 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
791 switch (attributes & MemberAttributes.AccessMask) {
792 case MemberAttributes.Assembly:
793 output.Write ("internal ");
795 case MemberAttributes.FamilyAndAssembly:
797 output.Write ("internal ");
799 output.Write ("/*FamANDAssem*/ internal ");
802 case MemberAttributes.Family:
803 output.Write ("protected ");
805 case MemberAttributes.FamilyOrAssembly:
806 output.Write ("protected internal ");
808 case MemberAttributes.Private:
809 output.Write ("private ");
811 case MemberAttributes.Public:
812 output.Write ("public ");
817 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
820 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
821 output.Write( "new " );
824 switch (attributes & MemberAttributes.ScopeMask) {
825 case MemberAttributes.Abstract:
826 output.Write ("abstract ");
828 case MemberAttributes.Final:
831 case MemberAttributes.Static:
832 output.Write ("static ");
834 case MemberAttributes.Override:
835 output.Write ("override ");
839 // FUNNY! if the scope value is
840 // rubbish (0 or >Const), and access
841 // is public or protected, make it
844 // i'm not sure whether this is 100%
845 // correct, but it seems to be MS
848 // On .NET 2.0, internal members
849 // are also marked "virtual".
851 MemberAttributes access = attributes & MemberAttributes.AccessMask;
852 if (access == MemberAttributes.Public || access == MemberAttributes.Family)
853 output.Write ("virtual ");
858 protected virtual void OutputOperator (CodeBinaryOperatorType op)
861 case CodeBinaryOperatorType.Add:
864 case CodeBinaryOperatorType.Subtract:
867 case CodeBinaryOperatorType.Multiply:
870 case CodeBinaryOperatorType.Divide:
873 case CodeBinaryOperatorType.Modulus:
876 case CodeBinaryOperatorType.Assign:
879 case CodeBinaryOperatorType.IdentityInequality:
882 case CodeBinaryOperatorType.IdentityEquality:
885 case CodeBinaryOperatorType.ValueEquality:
888 case CodeBinaryOperatorType.BitwiseOr:
891 case CodeBinaryOperatorType.BitwiseAnd:
894 case CodeBinaryOperatorType.BooleanOr:
897 case CodeBinaryOperatorType.BooleanAnd:
900 case CodeBinaryOperatorType.LessThan:
903 case CodeBinaryOperatorType.LessThanOrEqual:
906 case CodeBinaryOperatorType.GreaterThan:
909 case CodeBinaryOperatorType.GreaterThanOrEqual:
915 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
918 foreach (CodeParameterDeclarationExpression expr in parameters) {
923 GenerateExpression (expr);
927 protected abstract void OutputType (CodeTypeReference t);
929 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
933 switch (attributes & TypeAttributes.VisibilityMask) {
934 case TypeAttributes.NotPublic:
935 // private by default
938 case TypeAttributes.Public:
939 case TypeAttributes.NestedPublic:
940 output.Write ("public ");
943 case TypeAttributes.NestedPrivate:
944 output.Write ("private ");
949 output.Write ("struct ");
952 output.Write ("enum ");
954 if ((attributes & TypeAttributes.Interface) != 0)
955 output.Write ("interface ");
956 else if (currentType is CodeTypeDelegate)
957 output.Write ("delegate ");
959 if ((attributes & TypeAttributes.Sealed) != 0)
960 output.Write ("sealed ");
961 if ((attributes & TypeAttributes.Abstract) != 0)
962 output.Write ("abstract ");
964 output.Write ("class ");
969 protected virtual void OutputTypeNamePair (CodeTypeReference type,
977 protected abstract string QuoteSnippetString (string value);
982 protected abstract string CreateEscapedIdentifier (string value);
983 string ICodeGenerator.CreateEscapedIdentifier (string value)
985 return CreateEscapedIdentifier (value);
988 protected abstract string CreateValidIdentifier (string value);
989 string ICodeGenerator.CreateValidIdentifier (string value)
991 return CreateValidIdentifier (value);
994 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
997 options = new CodeGeneratorOptions ();
999 this.output = new IndentedTextWriter (output, options.IndentString);
1000 this.options = options;
1003 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
1005 CodeGeneratorOptions options)
1007 InitOutput (output, options);
1009 if (compileUnit is CodeSnippetCompileUnit) {
1010 GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
1012 GenerateCompileUnit (compileUnit);
1016 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
1018 CodeGeneratorOptions options)
1020 InitOutput (output, options);
1021 GenerateExpression (expression);
1024 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
1026 CodeGeneratorOptions options)
1028 InitOutput (output, options);
1029 GenerateNamespace (ns);
1032 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
1034 CodeGeneratorOptions options)
1036 InitOutput (output, options);
1037 GenerateStatement (statement);
1040 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
1042 CodeGeneratorOptions options)
1044 InitOutput (output, options);
1045 GenerateType (type);
1048 private void GenerateType (CodeTypeDeclaration type)
1050 this.currentType = type;
1053 if (type.StartDirectives.Count > 0)
1054 GenerateDirectives (type.StartDirectives);
1056 foreach (CodeCommentStatement statement in type.Comments)
1057 GenerateCommentStatement (statement);
1059 if (type.LinePragma != null)
1060 GenerateLinePragmaStart (type.LinePragma);
1062 GenerateTypeStart (type);
1064 CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
1065 type.Members.CopyTo (members, 0);
1068 if (!Options.VerbatimOrder)
1071 int[] order = new int[members.Length];
1072 for (int n = 0; n < members.Length; n++)
1073 order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
1075 Array.Sort (order, members);
1078 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
1079 // its corresponding place in CodeTypeMemberComparer class (below)
1081 CodeTypeDeclaration subtype = null;
1082 foreach (CodeTypeMember member in members) {
1083 CodeTypeMember prevMember = this.currentMember;
1084 this.currentMember = member;
1086 if (prevMember != null && subtype == null) {
1087 if (prevMember.LinePragma != null)
1088 GenerateLinePragmaEnd (prevMember.LinePragma);
1090 if (prevMember.EndDirectives.Count > 0)
1091 GenerateDirectives (prevMember.EndDirectives);
1095 if (options.BlankLinesBetweenMembers)
1096 output.WriteLine ();
1098 subtype = member as CodeTypeDeclaration;
1099 if (subtype != null) {
1100 GenerateType (subtype);
1101 this.currentType = type;
1106 if (currentMember.StartDirectives.Count > 0)
1107 GenerateDirectives (currentMember.StartDirectives);
1109 foreach (CodeCommentStatement statement in member.Comments)
1110 GenerateCommentStatement (statement);
1112 if (member.LinePragma != null)
1113 GenerateLinePragmaStart (member.LinePragma);
1115 CodeMemberEvent eventm = member as CodeMemberEvent;
1116 if (eventm != null) {
1117 GenerateEvent (eventm, type);
1120 CodeMemberField field = member as CodeMemberField;
1121 if (field != null) {
1122 GenerateField (field);
1125 CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
1126 if (epmethod != null) {
1127 GenerateEntryPointMethod (epmethod, type);
1130 CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
1131 if (typeCtor != null) {
1132 GenerateTypeConstructor (typeCtor);
1135 CodeConstructor ctor = member as CodeConstructor;
1137 GenerateConstructor (ctor, type);
1140 CodeMemberMethod method = member as CodeMemberMethod;
1141 if (method != null) {
1142 GenerateMethod (method, type);
1145 CodeMemberProperty property = member as CodeMemberProperty;
1146 if (property != null) {
1147 GenerateProperty (property, type);
1150 CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
1151 if (snippet != null) {
1152 GenerateSnippetMember (snippet);
1156 this.currentMember = prevMember;
1159 // Hack because of previous continue usage
1160 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
1161 if (currentMember.LinePragma != null)
1162 GenerateLinePragmaEnd (currentMember.LinePragma);
1164 if (currentMember.EndDirectives.Count > 0)
1165 GenerateDirectives (currentMember.EndDirectives);
1169 this.currentType = type;
1170 GenerateTypeEnd (type);
1172 if (type.LinePragma != null)
1173 GenerateLinePragmaEnd (type.LinePragma);
1176 if (type.EndDirectives.Count > 0)
1177 GenerateDirectives (type.EndDirectives);
1181 protected abstract string GetTypeOutput (CodeTypeReference type);
1183 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
1185 return GetTypeOutput (type);
1188 protected abstract bool IsValidIdentifier (string value);
1190 bool ICodeGenerator.IsValidIdentifier (string value)
1192 return IsValidIdentifier (value);
1195 public static bool IsValidLanguageIndependentIdentifier (string value)
1199 if (value.Equals (string.Empty))
1201 switch (char.GetUnicodeCategory (value[0]))
1203 case UnicodeCategory.LetterNumber:
1204 case UnicodeCategory.LowercaseLetter:
1205 case UnicodeCategory.TitlecaseLetter:
1206 case UnicodeCategory.UppercaseLetter:
1207 case UnicodeCategory.OtherLetter:
1208 case UnicodeCategory.ModifierLetter:
1209 case UnicodeCategory.ConnectorPunctuation:
1210 if (value.Length > 1)
1212 for (int x = 0; x < value.Length; x++)
1214 switch (char.GetUnicodeCategory (value[x]))
1216 case UnicodeCategory.LetterNumber:
1217 case UnicodeCategory.LowercaseLetter:
1218 case UnicodeCategory.TitlecaseLetter:
1219 case UnicodeCategory.UppercaseLetter:
1220 case UnicodeCategory.OtherLetter:
1221 case UnicodeCategory.ModifierLetter:
1222 case UnicodeCategory.ConnectorPunctuation:
1223 case UnicodeCategory.DecimalDigitNumber:
1224 case UnicodeCategory.NonSpacingMark:
1225 case UnicodeCategory.SpacingCombiningMark:
1226 case UnicodeCategory.Format:
1239 protected abstract bool Supports (GeneratorSupport supports);
1241 bool ICodeGenerator.Supports (GeneratorSupport value)
1243 return Supports (value);
1246 protected virtual void ValidateIdentifier (string value)
1248 if (!(IsValidIdentifier (value)))
1249 throw new ArgumentException ("Identifier is invalid", "value");
1253 public static void ValidateIdentifiers (CodeObject e)
1255 throw new NotImplementedException();
1258 void ICodeGenerator.ValidateIdentifier (string value)
1260 ValidateIdentifier (value);
1263 // The position in the array determines the order in which those
1264 // kind of CodeTypeMembers are generated. Less is more ;-)
1265 static Type [] memberTypes = { typeof (CodeMemberField),
1266 typeof (CodeSnippetTypeMember),
1267 typeof (CodeTypeConstructor),
1268 typeof (CodeConstructor),
1269 typeof (CodeMemberProperty),
1270 typeof (CodeMemberEvent),
1271 typeof (CodeMemberMethod),
1272 typeof (CodeTypeDeclaration),
1273 typeof (CodeEntryPointMethod)
1277 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)