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);
67 CodeTypeDeclaration CurrentClass {
73 protected CodeTypeMember CurrentMember {
79 protected string CurrentMemberName {
81 if (currentMember == null)
82 return "<% unknown %>";
83 return currentMember.Name;
87 protected string CurrentTypeName {
89 if (currentType == null)
90 return "<% unknown %>";
91 return currentType.Name;
95 protected int Indent {
100 output.Indent = value;
104 protected bool IsCurrentClass {
106 if (currentType == null)
108 return currentType.IsClass && !(currentType is CodeTypeDelegate);
112 protected bool IsCurrentDelegate {
114 return currentType is CodeTypeDelegate;
118 protected bool IsCurrentEnum {
120 if (currentType == null)
122 return currentType.IsEnum;
126 protected bool IsCurrentInterface {
128 if (currentType == null)
130 return currentType.IsInterface;
134 protected bool IsCurrentStruct {
136 if (currentType == null)
138 return currentType.IsStruct;
142 protected abstract string NullToken {
147 protected CodeGeneratorOptions Options {
153 protected TextWriter Output {
162 protected virtual void ContinueOnNewLine (string st)
164 output.WriteLine (st);
168 * Code Generation methods
170 protected abstract void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression e);
171 protected abstract void GenerateArrayCreateExpression (CodeArrayCreateExpression e);
172 protected abstract void GenerateArrayIndexerExpression (CodeArrayIndexerExpression e);
173 protected abstract void GenerateAssignStatement (CodeAssignStatement s);
174 protected abstract void GenerateAttachEventStatement (CodeAttachEventStatement s);
175 protected abstract void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes);
176 protected abstract void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes);
177 protected abstract void GenerateBaseReferenceExpression (CodeBaseReferenceExpression e);
179 protected virtual void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
182 GenerateExpression (e.Left);
184 OutputOperator (e.Operator);
186 GenerateExpression (e.Right);
190 protected abstract void GenerateCastExpression (CodeCastExpression e);
193 public virtual void GenerateCodeFromMember (CodeTypeMember member, TextWriter writer, CodeGeneratorOptions options)
195 throw new NotImplementedException ();
198 protected abstract void GenerateComment (CodeComment comment);
200 protected virtual void GenerateCommentStatement (CodeCommentStatement statement)
202 GenerateComment (statement.Comment);
205 protected virtual void GenerateCommentStatements (CodeCommentStatementCollection statements)
207 foreach (CodeCommentStatement comment in statements)
208 GenerateCommentStatement (comment);
211 protected virtual void GenerateCompileUnit (CodeCompileUnit compileUnit)
213 GenerateCompileUnitStart (compileUnit);
215 CodeAttributeDeclarationCollection attributes = compileUnit.AssemblyCustomAttributes;
216 if (attributes.Count != 0) {
217 foreach (CodeAttributeDeclaration att in attributes) {
218 GenerateAttributeDeclarationsStart (attributes);
219 output.Write ("assembly: ");
220 OutputAttributeDeclaration (att);
221 GenerateAttributeDeclarationsEnd (attributes);
226 foreach (CodeNamespace ns in compileUnit.Namespaces)
227 GenerateNamespace (ns);
229 GenerateCompileUnitEnd (compileUnit);
232 protected virtual void GenerateCompileUnitEnd (CodeCompileUnit compileUnit)
235 if (compileUnit.EndDirectives.Count > 0)
236 GenerateDirectives (compileUnit.EndDirectives);
240 protected virtual void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
243 if (compileUnit.StartDirectives.Count > 0) {
244 GenerateDirectives (compileUnit.StartDirectives);
250 protected abstract void GenerateConditionStatement (CodeConditionStatement s);
251 protected abstract void GenerateConstructor (CodeConstructor x, CodeTypeDeclaration d);
253 protected virtual void GenerateDecimalValue (Decimal d)
255 Output.Write (d.ToString (CultureInfo.InvariantCulture));
259 protected virtual void GenerateDefaultValueExpression (CodeDefaultValueExpression e)
261 throw new NotImplementedException ();
264 protected abstract void GenerateDelegateCreateExpression (CodeDelegateCreateExpression e);
265 protected abstract void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression e);
267 protected virtual void GenerateDirectionExpression (CodeDirectionExpression e)
269 OutputDirection (e.Direction);
271 GenerateExpression (e.Expression);
274 protected virtual void GenerateDoubleValue (Double d)
276 Output.Write (d.ToString (CultureInfo.InvariantCulture));
279 protected abstract void GenerateEntryPointMethod (CodeEntryPointMethod m, CodeTypeDeclaration d);
280 protected abstract void GenerateEvent (CodeMemberEvent ev, CodeTypeDeclaration d);
281 protected abstract void GenerateEventReferenceExpression (CodeEventReferenceExpression e);
283 protected void GenerateExpression (CodeExpression e)
286 throw new ArgumentNullException ("e");
290 } catch (NotImplementedException) {
291 throw new ArgumentException ("Element type " + e.GetType () + " is not supported.", "e");
295 protected abstract void GenerateExpressionStatement (CodeExpressionStatement statement);
296 protected abstract void GenerateField (CodeMemberField f);
297 protected abstract void GenerateFieldReferenceExpression (CodeFieldReferenceExpression e);
298 protected abstract void GenerateGotoStatement (CodeGotoStatement statement);
299 protected abstract void GenerateIndexerExpression (CodeIndexerExpression e);
300 protected abstract void GenerateIterationStatement (CodeIterationStatement s);
301 protected abstract void GenerateLabeledStatement (CodeLabeledStatement statement);
302 protected abstract void GenerateLinePragmaStart (CodeLinePragma p);
303 protected abstract void GenerateLinePragmaEnd (CodeLinePragma p);
304 protected abstract void GenerateMethod (CodeMemberMethod m, CodeTypeDeclaration d);
305 protected abstract void GenerateMethodInvokeExpression (CodeMethodInvokeExpression e);
306 protected abstract void GenerateMethodReferenceExpression (CodeMethodReferenceExpression e);
307 protected abstract void GenerateMethodReturnStatement (CodeMethodReturnStatement e);
309 protected virtual void GenerateNamespace (CodeNamespace ns)
311 foreach (CodeCommentStatement statement in ns.Comments)
312 GenerateCommentStatement (statement);
314 GenerateNamespaceStart (ns);
316 foreach (CodeNamespaceImport import in ns.Imports) {
317 if (import.LinePragma != null)
318 GenerateLinePragmaStart (import.LinePragma);
320 GenerateNamespaceImport (import);
322 if (import.LinePragma != null)
323 GenerateLinePragmaEnd (import.LinePragma);
330 GenerateNamespaceEnd (ns);
333 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
334 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
335 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
336 protected void GenerateNamespaceImports (CodeNamespace e)
338 foreach (CodeNamespaceImport import in e.Imports) {
339 if (import.LinePragma != null)
340 GenerateLinePragmaStart (import.LinePragma);
342 GenerateNamespaceImport (import);
344 if (import.LinePragma != null)
345 GenerateLinePragmaEnd (import.LinePragma);
349 protected void GenerateNamespaces (CodeCompileUnit e)
351 foreach (CodeNamespace ns in e.Namespaces)
352 GenerateNamespace (ns);
355 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
357 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
359 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
360 OutputAttributeDeclarations (e.CustomAttributes);
361 OutputDirection (e.Direction);
364 output.Write (e.Name);
367 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
369 object value = e.Value;
371 output.Write (NullToken);
375 Type type = value.GetType ();
376 TypeCode typeCode = Type.GetTypeCode (type);
378 case TypeCode.Boolean:
379 output.Write (value.ToString ().ToLower (CultureInfo.InvariantCulture));
382 output.Write ("'" + value.ToString () + "'");
384 case TypeCode.String:
385 output.Write (QuoteSnippetString ((string) value));
387 case TypeCode.Single:
388 GenerateSingleFloatValue ((float) value);
390 case TypeCode.Double:
391 GenerateDoubleValue ((double) value);
393 case TypeCode.Decimal:
394 GenerateDecimalValue ((decimal) value);
400 output.Write (((IFormattable)value).ToString (null, CultureInfo.InvariantCulture));
403 throw new ArgumentException (string.Format(CultureInfo.InvariantCulture,
404 "Invalid Primitive Type: {0}. Only CLS compliant primitive " +
405 "types can be used. Consider using CodeObjectCreateExpression.",
410 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
411 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
412 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
413 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
415 protected virtual void GenerateSingleFloatValue (Single s)
417 output.Write (s.ToString(CultureInfo.InvariantCulture));
420 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
422 if (e.LinePragma != null)
423 GenerateLinePragmaStart (e.LinePragma);
425 output.WriteLine (e.Value);
427 if (e.LinePragma != null)
428 GenerateLinePragmaEnd (e.LinePragma);
432 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
433 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
434 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
436 output.WriteLine (s.Value);
439 protected void GenerateStatement (CodeStatement s)
442 if (s.StartDirectives.Count > 0)
443 GenerateDirectives (s.StartDirectives);
445 if (s.LinePragma != null)
446 GenerateLinePragmaStart (s.LinePragma);
448 CodeSnippetStatement snippet = s as CodeSnippetStatement;
449 if (snippet != null) {
454 GenerateSnippetStatement (snippet);
459 GenerateSnippetStatement (snippet);
464 } catch (NotImplementedException) {
465 throw new ArgumentException ("Element type " + s.GetType () + " is not supported.", "s");
469 if (s.LinePragma != null)
470 GenerateLinePragmaEnd (s.LinePragma);
473 if (s.EndDirectives.Count > 0)
474 GenerateDirectives (s.EndDirectives);
478 protected void GenerateStatements (CodeStatementCollection c)
480 foreach (CodeStatement statement in c)
481 GenerateStatement (statement);
484 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
485 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
486 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
487 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
488 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
490 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
492 output.Write ("typeof(");
497 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
502 protected void GenerateTypes (CodeNamespace e)
504 foreach (CodeTypeDeclaration type in e.Types) {
505 if (options.BlankLinesBetweenMembers)
512 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
513 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
514 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
523 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
525 string name = argument.Name;
526 if ((name != null) && (name.Length > 0)) {
530 GenerateExpression (argument.Value);
533 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
535 output.Write (attribute.Name.Replace ('+', '.'));
537 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
538 if (enumerator.MoveNext()) {
539 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
540 OutputAttributeArgument (argument);
542 while (enumerator.MoveNext()) {
544 argument = (CodeAttributeArgument)enumerator.Current;
545 OutputAttributeArgument (argument);
551 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
553 GenerateAttributeDeclarationsStart (attributes);
555 IEnumerator enumerator = attributes.GetEnumerator();
556 if (enumerator.MoveNext()) {
557 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
559 OutputAttributeDeclaration (attribute);
561 while (enumerator.MoveNext()) {
562 attribute = (CodeAttributeDeclaration)enumerator.Current;
564 output.WriteLine (',');
565 OutputAttributeDeclaration (attribute);
569 GenerateAttributeDeclarationsEnd (attributes);
572 protected virtual void OutputDirection (FieldDirection direction)
575 case FieldDirection.In:
576 //output.Write ("in ");
578 case FieldDirection.Out:
579 output.Write ("out ");
581 case FieldDirection.Ref:
582 output.Write ("ref ");
587 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
589 OutputExpressionList (expressions, false);
592 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
593 bool newLineBetweenItems)
596 IEnumerator enumerator = expressions.GetEnumerator();
597 if (enumerator.MoveNext()) {
598 CodeExpression expression = (CodeExpression)enumerator.Current;
600 GenerateExpression (expression);
602 while (enumerator.MoveNext()) {
603 expression = (CodeExpression)enumerator.Current;
606 if (newLineBetweenItems)
611 GenerateExpression (expression);
617 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
619 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
620 output.Write ("new ");
622 switch (attributes & MemberAttributes.ScopeMask) {
623 case MemberAttributes.Static:
624 output.Write ("static ");
626 case MemberAttributes.Const:
627 output.Write ("const ");
632 protected virtual void OutputIdentifier (string ident)
634 output.Write (ident);
637 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
639 switch (attributes & MemberAttributes.AccessMask) {
640 case MemberAttributes.Assembly:
641 output.Write ("internal ");
643 case MemberAttributes.FamilyAndAssembly:
645 output.Write ("internal ");
647 output.Write ("/*FamANDAssem*/ internal ");
650 case MemberAttributes.Family:
651 output.Write ("protected ");
653 case MemberAttributes.FamilyOrAssembly:
654 output.Write ("protected internal ");
656 case MemberAttributes.Private:
657 output.Write ("private ");
659 case MemberAttributes.Public:
660 output.Write ("public ");
665 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
668 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
669 output.Write( "new " );
672 switch (attributes & MemberAttributes.ScopeMask) {
673 case MemberAttributes.Abstract:
674 output.Write ("abstract ");
676 case MemberAttributes.Final:
679 case MemberAttributes.Static:
680 output.Write ("static ");
682 case MemberAttributes.Override:
683 output.Write ("override ");
687 // FUNNY! if the scope value is
688 // rubbish (0 or >Const), and access
689 // is public or protected, make it
692 // i'm not sure whether this is 100%
693 // correct, but it seems to be MS
696 // On .NET 2.0, internal members
697 // are also marked "virtual".
699 MemberAttributes access = attributes & MemberAttributes.AccessMask;
700 if (access == MemberAttributes.Public || access == MemberAttributes.Family)
701 output.Write ("virtual ");
706 protected virtual void OutputOperator (CodeBinaryOperatorType op)
709 case CodeBinaryOperatorType.Add:
712 case CodeBinaryOperatorType.Subtract:
715 case CodeBinaryOperatorType.Multiply:
718 case CodeBinaryOperatorType.Divide:
721 case CodeBinaryOperatorType.Modulus:
724 case CodeBinaryOperatorType.Assign:
727 case CodeBinaryOperatorType.IdentityInequality:
730 case CodeBinaryOperatorType.IdentityEquality:
733 case CodeBinaryOperatorType.ValueEquality:
736 case CodeBinaryOperatorType.BitwiseOr:
739 case CodeBinaryOperatorType.BitwiseAnd:
742 case CodeBinaryOperatorType.BooleanOr:
745 case CodeBinaryOperatorType.BooleanAnd:
748 case CodeBinaryOperatorType.LessThan:
751 case CodeBinaryOperatorType.LessThanOrEqual:
754 case CodeBinaryOperatorType.GreaterThan:
757 case CodeBinaryOperatorType.GreaterThanOrEqual:
763 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
766 foreach (CodeParameterDeclarationExpression expr in parameters) {
771 GenerateExpression (expr);
775 protected abstract void OutputType (CodeTypeReference t);
777 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
781 switch (attributes & TypeAttributes.VisibilityMask) {
782 case TypeAttributes.NotPublic:
783 // private by default
786 case TypeAttributes.Public:
787 case TypeAttributes.NestedPublic:
788 output.Write ("public ");
791 case TypeAttributes.NestedPrivate:
792 output.Write ("private ");
797 output.Write ("struct ");
800 output.Write ("enum ");
802 if ((attributes & TypeAttributes.Interface) != 0)
803 output.Write ("interface ");
804 else if (currentType is CodeTypeDelegate)
805 output.Write ("delegate ");
807 if ((attributes & TypeAttributes.Sealed) != 0)
808 output.Write ("sealed ");
809 if ((attributes & TypeAttributes.Abstract) != 0)
810 output.Write ("abstract ");
812 output.Write ("class ");
817 protected virtual void OutputTypeNamePair (CodeTypeReference type,
825 protected abstract string QuoteSnippetString (string value);
830 protected abstract string CreateEscapedIdentifier (string value);
831 string ICodeGenerator.CreateEscapedIdentifier (string value)
833 return CreateEscapedIdentifier (value);
836 protected abstract string CreateValidIdentifier (string value);
837 string ICodeGenerator.CreateValidIdentifier (string value)
839 return CreateValidIdentifier (value);
842 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
845 options = new CodeGeneratorOptions ();
847 this.output = new IndentedTextWriter (output, options.IndentString);
848 this.options = options;
851 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
853 CodeGeneratorOptions options)
855 InitOutput (output, options);
857 if (compileUnit is CodeSnippetCompileUnit) {
858 GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
860 GenerateCompileUnit (compileUnit);
864 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
866 CodeGeneratorOptions options)
868 InitOutput (output, options);
869 GenerateExpression (expression);
872 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
874 CodeGeneratorOptions options)
876 InitOutput (output, options);
877 GenerateNamespace (ns);
880 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
882 CodeGeneratorOptions options)
884 InitOutput (output, options);
885 GenerateStatement (statement);
888 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
890 CodeGeneratorOptions options)
892 InitOutput (output, options);
896 private void GenerateType (CodeTypeDeclaration type)
898 this.currentType = type;
899 this.currentMember = null;
902 if (type.StartDirectives.Count > 0)
903 GenerateDirectives (type.StartDirectives);
905 foreach (CodeCommentStatement statement in type.Comments)
906 GenerateCommentStatement (statement);
908 if (type.LinePragma != null)
909 GenerateLinePragmaStart (type.LinePragma);
911 GenerateTypeStart (type);
913 CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
914 type.Members.CopyTo (members, 0);
917 if (!Options.VerbatimOrder)
920 int[] order = new int[members.Length];
921 for (int n = 0; n < members.Length; n++)
922 order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
924 Array.Sort (order, members);
927 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
928 // its corresponding place in CodeTypeMemberComparer class (below)
930 CodeTypeDeclaration subtype = null;
931 foreach (CodeTypeMember member in members) {
932 CodeTypeMember prevMember = this.currentMember;
933 this.currentMember = member;
935 if (prevMember != null && subtype == null) {
936 if (prevMember.LinePragma != null)
937 GenerateLinePragmaEnd (prevMember.LinePragma);
939 if (prevMember.EndDirectives.Count > 0)
940 GenerateDirectives (prevMember.EndDirectives);
944 if (options.BlankLinesBetweenMembers)
947 subtype = member as CodeTypeDeclaration;
948 if (subtype != null) {
949 GenerateType (subtype);
950 this.currentType = type;
955 if (currentMember.StartDirectives.Count > 0)
956 GenerateDirectives (currentMember.StartDirectives);
958 foreach (CodeCommentStatement statement in member.Comments)
959 GenerateCommentStatement (statement);
961 if (member.LinePragma != null)
962 GenerateLinePragmaStart (member.LinePragma);
965 member.Accept (visitor);
966 } catch (NotImplementedException) {
967 throw new ArgumentException ("Element type " + member.GetType () + " is not supported.");
971 // Hack because of previous continue usage
972 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
973 if (currentMember.LinePragma != null)
974 GenerateLinePragmaEnd (currentMember.LinePragma);
976 if (currentMember.EndDirectives.Count > 0)
977 GenerateDirectives (currentMember.EndDirectives);
981 this.currentType = type;
982 GenerateTypeEnd (type);
984 if (type.LinePragma != null)
985 GenerateLinePragmaEnd (type.LinePragma);
988 if (type.EndDirectives.Count > 0)
989 GenerateDirectives (type.EndDirectives);
993 protected abstract string GetTypeOutput (CodeTypeReference type);
995 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
997 return GetTypeOutput (type);
1000 protected abstract bool IsValidIdentifier (string value);
1002 bool ICodeGenerator.IsValidIdentifier (string value)
1004 return IsValidIdentifier (value);
1007 public static bool IsValidLanguageIndependentIdentifier (string value)
1011 if (value.Equals (string.Empty))
1014 switch (char.GetUnicodeCategory (value[0])) {
1015 case UnicodeCategory.LetterNumber:
1016 case UnicodeCategory.LowercaseLetter:
1017 case UnicodeCategory.TitlecaseLetter:
1018 case UnicodeCategory.UppercaseLetter:
1019 case UnicodeCategory.OtherLetter:
1020 case UnicodeCategory.ModifierLetter:
1021 case UnicodeCategory.ConnectorPunctuation:
1027 for (int x = 1; x < value.Length; ++x) {
1028 switch (char.GetUnicodeCategory (value[x])) {
1029 case UnicodeCategory.LetterNumber:
1030 case UnicodeCategory.LowercaseLetter:
1031 case UnicodeCategory.TitlecaseLetter:
1032 case UnicodeCategory.UppercaseLetter:
1033 case UnicodeCategory.OtherLetter:
1034 case UnicodeCategory.ModifierLetter:
1035 case UnicodeCategory.ConnectorPunctuation:
1036 case UnicodeCategory.DecimalDigitNumber:
1037 case UnicodeCategory.NonSpacingMark:
1038 case UnicodeCategory.SpacingCombiningMark:
1039 case UnicodeCategory.Format:
1049 protected abstract bool Supports (GeneratorSupport supports);
1051 bool ICodeGenerator.Supports (GeneratorSupport value)
1053 return Supports (value);
1056 protected virtual void ValidateIdentifier (string value)
1058 if (!(IsValidIdentifier (value)))
1059 throw new ArgumentException ("Identifier is invalid", "value");
1063 public static void ValidateIdentifiers (CodeObject e)
1065 throw new NotImplementedException();
1068 void ICodeGenerator.ValidateIdentifier (string value)
1070 ValidateIdentifier (value);
1073 // The position in the array determines the order in which those
1074 // kind of CodeTypeMembers are generated. Less is more ;-)
1075 static Type [] memberTypes = { typeof (CodeMemberField),
1076 typeof (CodeSnippetTypeMember),
1077 typeof (CodeTypeConstructor),
1078 typeof (CodeConstructor),
1079 typeof (CodeMemberProperty),
1080 typeof (CodeMemberEvent),
1081 typeof (CodeMemberMethod),
1082 typeof (CodeTypeDeclaration),
1083 typeof (CodeEntryPointMethod)
1087 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
1092 internal class Visitor : ICodeDomVisitor {
1095 public Visitor (CodeGenerator generator)
1102 public void Visit (CodeArgumentReferenceExpression o)
1104 g.GenerateArgumentReferenceExpression (o);
1107 public void Visit (CodeArrayCreateExpression o)
1109 g.GenerateArrayCreateExpression (o);
1112 public void Visit (CodeArrayIndexerExpression o)
1114 g.GenerateArrayIndexerExpression (o);
1117 public void Visit (CodeBaseReferenceExpression o)
1119 g.GenerateBaseReferenceExpression (o);
1122 public void Visit (CodeBinaryOperatorExpression o)
1124 g.GenerateBinaryOperatorExpression (o);
1127 public void Visit (CodeCastExpression o)
1129 g.GenerateCastExpression (o);
1133 public void Visit (CodeDefaultValueExpression o)
1135 g.GenerateDefaultValueExpression (o);
1139 public void Visit (CodeDelegateCreateExpression o)
1141 g.GenerateDelegateCreateExpression (o);
1144 public void Visit (CodeDelegateInvokeExpression o)
1146 g.GenerateDelegateInvokeExpression (o);
1149 public void Visit (CodeDirectionExpression o)
1151 g.GenerateDirectionExpression (o);
1154 public void Visit (CodeEventReferenceExpression o)
1156 g.GenerateEventReferenceExpression (o);
1159 public void Visit (CodeFieldReferenceExpression o)
1161 g.GenerateFieldReferenceExpression (o);
1164 public void Visit (CodeIndexerExpression o)
1166 g.GenerateIndexerExpression (o);
1169 public void Visit (CodeMethodInvokeExpression o)
1171 g.GenerateMethodInvokeExpression (o);
1174 public void Visit (CodeMethodReferenceExpression o)
1176 g.GenerateMethodReferenceExpression (o);
1179 public void Visit (CodeObjectCreateExpression o)
1181 g.GenerateObjectCreateExpression (o);
1184 public void Visit (CodeParameterDeclarationExpression o)
1186 g.GenerateParameterDeclarationExpression (o);
1189 public void Visit (CodePrimitiveExpression o)
1191 g.GeneratePrimitiveExpression (o);
1194 public void Visit (CodePropertyReferenceExpression o)
1196 g.GeneratePropertyReferenceExpression (o);
1199 public void Visit (CodePropertySetValueReferenceExpression o)
1201 g.GeneratePropertySetValueReferenceExpression (o);
1204 public void Visit (CodeSnippetExpression o)
1206 g.GenerateSnippetExpression (o);
1209 public void Visit (CodeThisReferenceExpression o)
1211 g.GenerateThisReferenceExpression (o);
1214 public void Visit (CodeTypeOfExpression o)
1216 g.GenerateTypeOfExpression (o);
1219 public void Visit (CodeTypeReferenceExpression o)
1221 g.GenerateTypeReferenceExpression (o);
1224 public void Visit (CodeVariableReferenceExpression o)
1226 g.GenerateVariableReferenceExpression (o);
1231 public void Visit (CodeAssignStatement o)
1233 g.GenerateAssignStatement (o);
1236 public void Visit (CodeAttachEventStatement o)
1238 g.GenerateAttachEventStatement (o);
1241 public void Visit (CodeCommentStatement o)
1243 g.GenerateCommentStatement (o);
1246 public void Visit (CodeConditionStatement o)
1248 g.GenerateConditionStatement (o);
1251 public void Visit (CodeExpressionStatement o)
1253 g.GenerateExpressionStatement (o);
1256 public void Visit (CodeGotoStatement o)
1258 g.GenerateGotoStatement (o);
1261 public void Visit (CodeIterationStatement o)
1263 g.GenerateIterationStatement (o);
1266 public void Visit (CodeLabeledStatement o)
1268 g.GenerateLabeledStatement (o);
1271 public void Visit (CodeMethodReturnStatement o)
1273 g.GenerateMethodReturnStatement (o);
1276 public void Visit (CodeRemoveEventStatement o)
1278 g.GenerateRemoveEventStatement (o);
1281 public void Visit (CodeThrowExceptionStatement o)
1283 g.GenerateThrowExceptionStatement (o);
1286 public void Visit (CodeTryCatchFinallyStatement o)
1288 g.GenerateTryCatchFinallyStatement (o);
1291 public void Visit (CodeVariableDeclarationStatement o)
1293 g.GenerateVariableDeclarationStatement (o);
1298 public void Visit (CodeConstructor o)
1300 g.GenerateConstructor (o, g.CurrentClass);
1303 public void Visit (CodeEntryPointMethod o)
1305 g.GenerateEntryPointMethod (o, g.CurrentClass);
1308 public void Visit (CodeMemberEvent o)
1310 g.GenerateEvent (o, g.CurrentClass);
1313 public void Visit (CodeMemberField o)
1315 g.GenerateField (o);
1318 public void Visit (CodeMemberMethod o)
1320 g.GenerateMethod (o, g.CurrentClass);
1323 public void Visit (CodeMemberProperty o)
1325 g.GenerateProperty (o, g.CurrentClass);
1328 public void Visit (CodeSnippetTypeMember o)
1330 g.GenerateSnippetMember (o);
1333 public void Visit (CodeTypeConstructor o)
1335 g.GenerateTypeConstructor (o);