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;
49 private Visitor visitor;
54 protected CodeGenerator()
56 visitor = new Visitor (this);
63 CodeTypeDeclaration CurrentClass {
69 protected CodeTypeMember CurrentMember {
75 protected string CurrentMemberName {
77 if (currentMember == null)
78 return "<% unknown %>";
79 return currentMember.Name;
83 protected string CurrentTypeName {
85 if (currentType == null)
86 return "<% unknown %>";
87 return currentType.Name;
91 protected int Indent {
96 output.Indent = value;
100 protected bool IsCurrentClass {
102 if (currentType == null)
104 return currentType.IsClass && !(currentType is CodeTypeDelegate);
108 protected bool IsCurrentDelegate {
110 return currentType is CodeTypeDelegate;
114 protected bool IsCurrentEnum {
116 if (currentType == null)
118 return currentType.IsEnum;
122 protected bool IsCurrentInterface {
124 if (currentType == null)
126 return currentType.IsInterface;
130 protected bool IsCurrentStruct {
132 if (currentType == null)
134 return currentType.IsStruct;
138 protected abstract string NullToken {
143 protected CodeGeneratorOptions Options {
149 protected TextWriter Output {
158 protected virtual void ContinueOnNewLine (string st)
160 output.WriteLine (st);
164 * Code Generation methods
166 protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
167 protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
168 protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
169 protected abstract void GenerateAssignStatement (CodeAssignStatement s);
170 protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
171 protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
172 protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
173 protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
175 protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
178 GenerateExpression (e.Left);
180 OutputOperator (e.Operator);
182 GenerateExpression (e.Right);
186 protected abstract void GenerateCastExpression (CodeCastExpression e);
189 public virtual void GenerateCodeFromMember (CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options)
191 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 foreach (CodeNamespace ns in compileUnit.Namespaces)
211 if (string.IsNullOrEmpty(ns.Name))
212 GenerateNamespace (ns);
214 CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
215 if (attributes.Count != 0) {
216 foreach (CodeAttributeDeclaration att in attributes) {
217 GenerateAttributeDeclarationsStart (attributes);
218 output.Write ("assembly: ");
219 OutputAttributeDeclaration (att);
220 GenerateAttributeDeclarationsEnd (attributes);
225 foreach (CodeNamespace ns in compileUnit.Namespaces)
226 if (!string.IsNullOrEmpty(ns.Name))
227 GenerateNamespace (ns);
229 GenerateCompileUnitEnd (compileUnit);
232 protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
234 if (compileUnit.EndDirectives.Count > 0)
235 GenerateDirectives (compileUnit.EndDirectives);
238 protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
240 if (compileUnit.StartDirectives.Count > 0) {
241 GenerateDirectives (compileUnit.StartDirectives);
246 protected abstract void GenerateConditionStatement (CodeConditionStatement s);
247 protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
249 protected virtual void GenerateDecimalValue (Decimal d)
251 Output.Write (d.ToString (CultureInfo.InvariantCulture));
255 protected virtual void GenerateDefaultValueExpression (CodeDefaultValueExpression e)
257 throw new NotImplementedException ();
260 protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
261 protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
263 protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
265 OutputDirection (e.Direction);
267 GenerateExpression (e.Expression);
270 protected virtual void GenerateDoubleValue (Double d)
272 Output.Write (d.ToString (CultureInfo.InvariantCulture));
275 protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
276 protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
277 protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
279 protected void GenerateExpression (CodeExpression e)
282 throw new ArgumentNullException ("e");
286 } catch (NotImplementedException) {
287 throw new ArgumentException ("Element type " + e.GetType () + " is not supported.", "e");
291 protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
292 protected abstract void GenerateField (CodeMemberField f);
293 protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
294 protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
295 protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
296 protected abstract void GenerateIterationStatement (CodeIterationStatement s);
297 protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
298 protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
299 protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
300 protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
301 protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
302 protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
303 protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
305 protected virtual void GenerateNamespace (CodeNamespace ns)
307 foreach (CodeCommentStatement statement in ns.Comments)
308 GenerateCommentStatement (statement);
310 GenerateNamespaceStart (ns);
312 foreach (CodeNamespaceImport import in ns.Imports) {
313 if (import.LinePragma != null)
314 GenerateLinePragmaStart (import.LinePragma);
316 GenerateNamespaceImport (import);
318 if (import.LinePragma != null)
319 GenerateLinePragmaEnd (import.LinePragma);
326 GenerateNamespaceEnd (ns);
329 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
330 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
331 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
332 protected void GenerateNamespaceImports (CodeNamespace e)
334 foreach (CodeNamespaceImport import in e.Imports) {
335 if (import.LinePragma != null)
336 GenerateLinePragmaStart (import.LinePragma);
338 GenerateNamespaceImport (import);
340 if (import.LinePragma != null)
341 GenerateLinePragmaEnd (import.LinePragma);
345 protected void GenerateNamespaces (CodeCompileUnit e)
347 foreach (CodeNamespace ns in e.Namespaces)
348 GenerateNamespace (ns);
351 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
353 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
355 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
356 OutputAttributeDeclarations (e.CustomAttributes);
357 OutputDirection (e.Direction);
360 output.Write (e.Name);
363 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
365 object value = e.Value;
367 output.Write (NullToken);
371 Type type = value.GetType ();
372 TypeCode typeCode = Type.GetTypeCode (type);
374 case TypeCode.Boolean:
375 output.Write (value.ToString ().ToLower (CultureInfo.InvariantCulture));
378 output.Write ("'" + value.ToString () + "'");
380 case TypeCode.String:
381 output.Write (QuoteSnippetString ((string) value));
383 case TypeCode.Single:
384 GenerateSingleFloatValue ((float) value);
386 case TypeCode.Double:
387 GenerateDoubleValue ((double) value);
389 case TypeCode.Decimal:
390 GenerateDecimalValue ((decimal) value);
396 output.Write (((IFormattable)value).ToString (null, CultureInfo.InvariantCulture));
399 throw new ArgumentException (string.Format(CultureInfo.InvariantCulture,
400 "Invalid Primitive Type: {0}. Only CLS compliant primitive " +
401 "types can be used. Consider using CodeObjectCreateExpression.",
406 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
407 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
408 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
409 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
411 protected virtual void GenerateSingleFloatValue (Single s)
413 output.Write (s.ToString(CultureInfo.InvariantCulture));
416 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
418 if (e.LinePragma != null)
419 GenerateLinePragmaStart (e.LinePragma);
421 output.WriteLine (e.Value);
423 if (e.LinePragma != null)
424 GenerateLinePragmaEnd (e.LinePragma);
428 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
429 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
430 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
432 output.WriteLine (s.Value);
435 protected void GenerateStatement (CodeStatement s)
437 if (s.StartDirectives.Count > 0)
438 GenerateDirectives (s.StartDirectives);
439 if (s.LinePragma != null)
440 GenerateLinePragmaStart (s.LinePragma);
442 CodeSnippetStatement snippet = s as CodeSnippetStatement;
443 if (snippet != null) {
447 GenerateSnippetStatement (snippet);
454 } catch (NotImplementedException) {
455 throw new ArgumentException ("Element type " + s.GetType () + " is not supported.", "s");
459 if (s.LinePragma != null)
460 GenerateLinePragmaEnd (s.LinePragma);
462 if (s.EndDirectives.Count > 0)
463 GenerateDirectives (s.EndDirectives);
466 protected void GenerateStatements (CodeStatementCollection c)
468 foreach (CodeStatement statement in c)
469 GenerateStatement (statement);
472 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
473 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
474 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
475 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
476 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
478 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
480 output.Write ("typeof(");
485 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
490 protected void GenerateTypes (CodeNamespace e)
492 foreach (CodeTypeDeclaration type in e.Types) {
493 if (options.BlankLinesBetweenMembers)
500 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
501 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
502 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
511 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
513 string name = argument.Name;
514 if ((name != null) && (name.Length > 0)) {
518 GenerateExpression (argument.Value);
521 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
523 output.Write (attribute.Name.Replace ('+', '.'));
525 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
526 if (enumerator.MoveNext()) {
527 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
528 OutputAttributeArgument (argument);
530 while (enumerator.MoveNext()) {
532 argument = (CodeAttributeArgument)enumerator.Current;
533 OutputAttributeArgument (argument);
539 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
541 GenerateAttributeDeclarationsStart (attributes);
543 IEnumerator enumerator = attributes.GetEnumerator();
544 if (enumerator.MoveNext()) {
545 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
547 OutputAttributeDeclaration (attribute);
549 while (enumerator.MoveNext()) {
550 attribute = (CodeAttributeDeclaration)enumerator.Current;
552 output.WriteLine (',');
553 OutputAttributeDeclaration (attribute);
557 GenerateAttributeDeclarationsEnd (attributes);
560 protected virtual void OutputDirection (FieldDirection direction)
563 case FieldDirection.In:
564 //output.Write ("in ");
566 case FieldDirection.Out:
567 output.Write ("out ");
569 case FieldDirection.Ref:
570 output.Write ("ref ");
575 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
577 OutputExpressionList (expressions, false);
580 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
581 bool newLineBetweenItems)
584 IEnumerator enumerator = expressions.GetEnumerator();
585 if (enumerator.MoveNext()) {
586 CodeExpression expression = (CodeExpression)enumerator.Current;
588 GenerateExpression (expression);
590 while (enumerator.MoveNext()) {
591 expression = (CodeExpression)enumerator.Current;
594 if (newLineBetweenItems)
599 GenerateExpression (expression);
605 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
607 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
608 output.Write ("new ");
610 switch (attributes & MemberAttributes.ScopeMask) {
611 case MemberAttributes.Static:
612 output.Write ("static ");
614 case MemberAttributes.Const:
615 output.Write ("const ");
620 protected virtual void OutputIdentifier (string ident)
622 output.Write (ident);
625 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
627 switch (attributes & MemberAttributes.AccessMask) {
628 case MemberAttributes.Assembly:
629 output.Write ("internal ");
631 case MemberAttributes.FamilyAndAssembly:
632 output.Write ("internal ");
634 case MemberAttributes.Family:
635 output.Write ("protected ");
637 case MemberAttributes.FamilyOrAssembly:
638 output.Write ("protected internal ");
640 case MemberAttributes.Private:
641 output.Write ("private ");
643 case MemberAttributes.Public:
644 output.Write ("public ");
649 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
651 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
652 output.Write( "new " );
654 switch (attributes & MemberAttributes.ScopeMask) {
655 case MemberAttributes.Abstract:
656 output.Write ("abstract ");
658 case MemberAttributes.Final:
661 case MemberAttributes.Static:
662 output.Write ("static ");
664 case MemberAttributes.Override:
665 output.Write ("override ");
669 // FUNNY! if the scope value is
670 // rubbish (0 or >Const), and access
671 // is public or protected, make it
674 // i'm not sure whether this is 100%
675 // correct, but it seems to be MS
678 // On .NET 2.0, internal members
679 // are also marked "virtual".
681 MemberAttributes access = attributes & MemberAttributes.AccessMask;
682 if (access == MemberAttributes.Public || access == MemberAttributes.Family)
683 output.Write ("virtual ");
688 protected virtual void OutputOperator (CodeBinaryOperatorType op)
691 case CodeBinaryOperatorType.Add:
694 case CodeBinaryOperatorType.Subtract:
697 case CodeBinaryOperatorType.Multiply:
700 case CodeBinaryOperatorType.Divide:
703 case CodeBinaryOperatorType.Modulus:
706 case CodeBinaryOperatorType.Assign:
709 case CodeBinaryOperatorType.IdentityInequality:
712 case CodeBinaryOperatorType.IdentityEquality:
715 case CodeBinaryOperatorType.ValueEquality:
718 case CodeBinaryOperatorType.BitwiseOr:
721 case CodeBinaryOperatorType.BitwiseAnd:
724 case CodeBinaryOperatorType.BooleanOr:
727 case CodeBinaryOperatorType.BooleanAnd:
730 case CodeBinaryOperatorType.LessThan:
733 case CodeBinaryOperatorType.LessThanOrEqual:
736 case CodeBinaryOperatorType.GreaterThan:
739 case CodeBinaryOperatorType.GreaterThanOrEqual:
745 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
748 foreach (CodeParameterDeclarationExpression expr in parameters) {
753 GenerateExpression (expr);
757 protected abstract void OutputType (CodeTypeReference t);
759 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
763 switch (attributes & TypeAttributes.VisibilityMask) {
764 case TypeAttributes.NotPublic:
765 // private by default
768 case TypeAttributes.Public:
769 case TypeAttributes.NestedPublic:
770 output.Write ("public ");
773 case TypeAttributes.NestedPrivate:
774 output.Write ("private ");
779 output.Write ("struct ");
782 output.Write ("enum ");
784 if ((attributes & TypeAttributes.Interface) != 0)
785 output.Write ("interface ");
786 else if (currentType is CodeTypeDelegate)
787 output.Write ("delegate ");
789 if ((attributes & TypeAttributes.Sealed) != 0)
790 output.Write ("sealed ");
791 if ((attributes & TypeAttributes.Abstract) != 0)
792 output.Write ("abstract ");
794 output.Write ("class ");
799 protected virtual void OutputTypeNamePair (CodeTypeReference type,
807 protected abstract string QuoteSnippetString (string value);
812 protected abstract string CreateEscapedIdentifier (string value);
813 string ICodeGenerator.CreateEscapedIdentifier (string value)
815 return CreateEscapedIdentifier (value);
818 protected abstract string CreateValidIdentifier (string value);
819 string ICodeGenerator.CreateValidIdentifier (string value)
821 return CreateValidIdentifier (value);
824 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
827 options = new CodeGeneratorOptions ();
829 this.output = new IndentedTextWriter (output, options.IndentString);
830 this.options = options;
833 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
835 CodeGeneratorOptions options)
837 InitOutput (output, options);
839 if (compileUnit is CodeSnippetCompileUnit) {
840 GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
842 GenerateCompileUnit (compileUnit);
846 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
848 CodeGeneratorOptions options)
850 InitOutput (output, options);
851 GenerateExpression (expression);
854 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
856 CodeGeneratorOptions options)
858 InitOutput (output, options);
859 GenerateNamespace (ns);
862 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
864 CodeGeneratorOptions options)
866 InitOutput (output, options);
867 GenerateStatement (statement);
870 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
872 CodeGeneratorOptions options)
874 InitOutput (output, options);
878 private void GenerateType (CodeTypeDeclaration type)
880 this.currentType = type;
881 this.currentMember = null;
883 if (type.StartDirectives.Count > 0)
884 GenerateDirectives (type.StartDirectives);
885 foreach (CodeCommentStatement statement in type.Comments)
886 GenerateCommentStatement (statement);
888 if (type.LinePragma != null)
889 GenerateLinePragmaStart (type.LinePragma);
891 GenerateTypeStart (type);
893 CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
894 type.Members.CopyTo (members, 0);
896 if (!Options.VerbatimOrder)
898 int[] order = new int[members.Length];
899 for (int n = 0; n < members.Length; n++)
900 order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
902 Array.Sort (order, members);
905 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
906 // its corresponding place in CodeTypeMemberComparer class (below)
908 CodeTypeDeclaration subtype = null;
909 foreach (CodeTypeMember member in members) {
910 CodeTypeMember prevMember = this.currentMember;
911 this.currentMember = member;
913 if (prevMember != null && subtype == null) {
914 if (prevMember.LinePragma != null)
915 GenerateLinePragmaEnd (prevMember.LinePragma);
916 if (prevMember.EndDirectives.Count > 0)
917 GenerateDirectives (prevMember.EndDirectives);
920 if (options.BlankLinesBetweenMembers)
923 subtype = member as CodeTypeDeclaration;
924 if (subtype != null) {
925 GenerateType (subtype);
926 this.currentType = type;
930 if (currentMember.StartDirectives.Count > 0)
931 GenerateDirectives (currentMember.StartDirectives);
932 foreach (CodeCommentStatement statement in member.Comments)
933 GenerateCommentStatement (statement);
935 if (member.LinePragma != null)
936 GenerateLinePragmaStart (member.LinePragma);
939 member.Accept (visitor);
940 } catch (NotImplementedException) {
941 throw new ArgumentException ("Element type " + member.GetType () + " is not supported.");
945 // Hack because of previous continue usage
946 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
947 if (currentMember.LinePragma != null)
948 GenerateLinePragmaEnd (currentMember.LinePragma);
949 if (currentMember.EndDirectives.Count > 0)
950 GenerateDirectives (currentMember.EndDirectives);
953 this.currentType = type;
954 GenerateTypeEnd (type);
956 if (type.LinePragma != null)
957 GenerateLinePragmaEnd (type.LinePragma);
959 if (type.EndDirectives.Count > 0)
960 GenerateDirectives (type.EndDirectives);
963 protected abstract string GetTypeOutput (CodeTypeReference type);
965 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
967 return GetTypeOutput (type);
970 protected abstract bool IsValidIdentifier (string value);
972 bool ICodeGenerator.IsValidIdentifier (string value)
974 return IsValidIdentifier (value);
977 public static bool IsValidLanguageIndependentIdentifier (string value)
981 if (value.Equals (string.Empty))
984 switch (char.GetUnicodeCategory (value[0])) {
985 case UnicodeCategory.LetterNumber:
986 case UnicodeCategory.LowercaseLetter:
987 case UnicodeCategory.TitlecaseLetter:
988 case UnicodeCategory.UppercaseLetter:
989 case UnicodeCategory.OtherLetter:
990 case UnicodeCategory.ModifierLetter:
991 case UnicodeCategory.ConnectorPunctuation:
997 for (int x = 1; x < value.Length; ++x) {
998 switch (char.GetUnicodeCategory (value[x])) {
999 case UnicodeCategory.LetterNumber:
1000 case UnicodeCategory.LowercaseLetter:
1001 case UnicodeCategory.TitlecaseLetter:
1002 case UnicodeCategory.UppercaseLetter:
1003 case UnicodeCategory.OtherLetter:
1004 case UnicodeCategory.ModifierLetter:
1005 case UnicodeCategory.ConnectorPunctuation:
1006 case UnicodeCategory.DecimalDigitNumber:
1007 case UnicodeCategory.NonSpacingMark:
1008 case UnicodeCategory.SpacingCombiningMark:
1009 case UnicodeCategory.Format:
1019 protected abstract bool Supports (GeneratorSupport supports);
1021 bool ICodeGenerator.Supports (GeneratorSupport value)
1023 return Supports (value);
1026 protected virtual void ValidateIdentifier (string value)
1028 if (!(IsValidIdentifier (value)))
1029 throw new ArgumentException ("Identifier is invalid", "value");
1033 public static void ValidateIdentifiers (CodeObject e)
1035 throw new NotImplementedException();
1038 void ICodeGenerator.ValidateIdentifier (string value)
1040 ValidateIdentifier (value);
1043 // The position in the array determines the order in which those
1044 // kind of CodeTypeMembers are generated. Less is more ;-)
1045 static Type [] memberTypes = { typeof (CodeMemberField),
1046 typeof (CodeSnippetTypeMember),
1047 typeof (CodeTypeConstructor),
1048 typeof (CodeConstructor),
1049 typeof (CodeMemberProperty),
1050 typeof (CodeMemberEvent),
1051 typeof (CodeMemberMethod),
1052 typeof (CodeTypeDeclaration),
1053 typeof (CodeEntryPointMethod)
1056 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
1060 internal class Visitor : ICodeDomVisitor {
1063 public Visitor (CodeGenerator generator)
1070 public void Visit (CodeArgumentReferenceExpression o)
1072 g.GenerateArgumentReferenceExpression (o);
1075 public void Visit (CodeArrayCreateExpression o)
1077 g.GenerateArrayCreateExpression (o);
1080 public void Visit (CodeArrayIndexerExpression o)
1082 g.GenerateArrayIndexerExpression (o);
1085 public void Visit (CodeBaseReferenceExpression o)
1087 g.GenerateBaseReferenceExpression (o);
1090 public void Visit (CodeBinaryOperatorExpression o)
1092 g.GenerateBinaryOperatorExpression (o);
1095 public void Visit (CodeCastExpression o)
1097 g.GenerateCastExpression (o);
1100 public void Visit (CodeDefaultValueExpression o)
1102 g.GenerateDefaultValueExpression (o);
1105 public void Visit (CodeDelegateCreateExpression o)
1107 g.GenerateDelegateCreateExpression (o);
1110 public void Visit (CodeDelegateInvokeExpression o)
1112 g.GenerateDelegateInvokeExpression (o);
1115 public void Visit (CodeDirectionExpression o)
1117 g.GenerateDirectionExpression (o);
1120 public void Visit (CodeEventReferenceExpression o)
1122 g.GenerateEventReferenceExpression (o);
1125 public void Visit (CodeFieldReferenceExpression o)
1127 g.GenerateFieldReferenceExpression (o);
1130 public void Visit (CodeIndexerExpression o)
1132 g.GenerateIndexerExpression (o);
1135 public void Visit (CodeMethodInvokeExpression o)
1137 g.GenerateMethodInvokeExpression (o);
1140 public void Visit (CodeMethodReferenceExpression o)
1142 g.GenerateMethodReferenceExpression (o);
1145 public void Visit (CodeObjectCreateExpression o)
1147 g.GenerateObjectCreateExpression (o);
1150 public void Visit (CodeParameterDeclarationExpression o)
1152 g.GenerateParameterDeclarationExpression (o);
1155 public void Visit (CodePrimitiveExpression o)
1157 g.GeneratePrimitiveExpression (o);
1160 public void Visit (CodePropertyReferenceExpression o)
1162 g.GeneratePropertyReferenceExpression (o);
1165 public void Visit (CodePropertySetValueReferenceExpression o)
1167 g.GeneratePropertySetValueReferenceExpression (o);
1170 public void Visit (CodeSnippetExpression o)
1172 g.GenerateSnippetExpression (o);
1175 public void Visit (CodeThisReferenceExpression o)
1177 g.GenerateThisReferenceExpression (o);
1180 public void Visit (CodeTypeOfExpression o)
1182 g.GenerateTypeOfExpression (o);
1185 public void Visit (CodeTypeReferenceExpression o)
1187 g.GenerateTypeReferenceExpression (o);
1190 public void Visit (CodeVariableReferenceExpression o)
1192 g.GenerateVariableReferenceExpression (o);
1197 public void Visit (CodeAssignStatement o)
1199 g.GenerateAssignStatement (o);
1202 public void Visit (CodeAttachEventStatement o)
1204 g.GenerateAttachEventStatement (o);
1207 public void Visit (CodeCommentStatement o)
1209 g.GenerateCommentStatement (o);
1212 public void Visit (CodeConditionStatement o)
1214 g.GenerateConditionStatement (o);
1217 public void Visit (CodeExpressionStatement o)
1219 g.GenerateExpressionStatement (o);
1222 public void Visit (CodeGotoStatement o)
1224 g.GenerateGotoStatement (o);
1227 public void Visit (CodeIterationStatement o)
1229 g.GenerateIterationStatement (o);
1232 public void Visit (CodeLabeledStatement o)
1234 g.GenerateLabeledStatement (o);
1237 public void Visit (CodeMethodReturnStatement o)
1239 g.GenerateMethodReturnStatement (o);
1242 public void Visit (CodeRemoveEventStatement o)
1244 g.GenerateRemoveEventStatement (o);
1247 public void Visit (CodeThrowExceptionStatement o)
1249 g.GenerateThrowExceptionStatement (o);
1252 public void Visit (CodeTryCatchFinallyStatement o)
1254 g.GenerateTryCatchFinallyStatement (o);
1257 public void Visit (CodeVariableDeclarationStatement o)
1259 g.GenerateVariableDeclarationStatement (o);
1264 public void Visit (CodeConstructor o)
1266 g.GenerateConstructor (o, g.CurrentClass);
1269 public void Visit (CodeEntryPointMethod o)
1271 g.GenerateEntryPointMethod (o, g.CurrentClass);
1274 public void Visit (CodeMemberEvent o)
1276 g.GenerateEvent (o, g.CurrentClass);
1279 public void Visit (CodeMemberField o)
1281 g.GenerateField (o);
1284 public void Visit (CodeMemberMethod o)
1286 g.GenerateMethod (o, g.CurrentClass);
1289 public void Visit (CodeMemberProperty o)
1291 g.GenerateProperty (o, g.CurrentClass);
1294 public void Visit (CodeSnippetTypeMember o)
1296 g.GenerateSnippetMember (o);
1299 public void Visit (CodeTypeConstructor o)
1301 g.GenerateTypeConstructor (o);