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;
901 if (type.StartDirectives.Count > 0)
902 GenerateDirectives (type.StartDirectives);
904 foreach (CodeCommentStatement statement in type.Comments)
905 GenerateCommentStatement (statement);
907 if (type.LinePragma != null)
908 GenerateLinePragmaStart (type.LinePragma);
910 GenerateTypeStart (type);
912 CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
913 type.Members.CopyTo (members, 0);
916 if (!Options.VerbatimOrder)
919 int[] order = new int[members.Length];
920 for (int n = 0; n < members.Length; n++)
921 order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
923 Array.Sort (order, members);
926 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
927 // its corresponding place in CodeTypeMemberComparer class (below)
929 CodeTypeDeclaration subtype = null;
930 foreach (CodeTypeMember member in members) {
931 CodeTypeMember prevMember = this.currentMember;
932 this.currentMember = member;
934 if (prevMember != null && subtype == null) {
935 if (prevMember.LinePragma != null)
936 GenerateLinePragmaEnd (prevMember.LinePragma);
938 if (prevMember.EndDirectives.Count > 0)
939 GenerateDirectives (prevMember.EndDirectives);
943 if (options.BlankLinesBetweenMembers)
946 subtype = member as CodeTypeDeclaration;
947 if (subtype != null) {
948 GenerateType (subtype);
949 this.currentType = type;
954 if (currentMember.StartDirectives.Count > 0)
955 GenerateDirectives (currentMember.StartDirectives);
957 foreach (CodeCommentStatement statement in member.Comments)
958 GenerateCommentStatement (statement);
960 if (member.LinePragma != null)
961 GenerateLinePragmaStart (member.LinePragma);
964 member.Accept (visitor);
965 } catch (NotImplementedException) {
966 throw new ArgumentException ("Element type " + member.GetType () + " is not supported.");
970 // Hack because of previous continue usage
971 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
972 if (currentMember.LinePragma != null)
973 GenerateLinePragmaEnd (currentMember.LinePragma);
975 if (currentMember.EndDirectives.Count > 0)
976 GenerateDirectives (currentMember.EndDirectives);
980 this.currentType = type;
981 GenerateTypeEnd (type);
983 if (type.LinePragma != null)
984 GenerateLinePragmaEnd (type.LinePragma);
987 if (type.EndDirectives.Count > 0)
988 GenerateDirectives (type.EndDirectives);
992 protected abstract string GetTypeOutput (CodeTypeReference type);
994 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
996 return GetTypeOutput (type);
999 protected abstract bool IsValidIdentifier (string value);
1001 bool ICodeGenerator.IsValidIdentifier (string value)
1003 return IsValidIdentifier (value);
1006 public static bool IsValidLanguageIndependentIdentifier (string value)
1010 if (value.Equals (string.Empty))
1013 switch (char.GetUnicodeCategory (value[0])) {
1014 case UnicodeCategory.LetterNumber:
1015 case UnicodeCategory.LowercaseLetter:
1016 case UnicodeCategory.TitlecaseLetter:
1017 case UnicodeCategory.UppercaseLetter:
1018 case UnicodeCategory.OtherLetter:
1019 case UnicodeCategory.ModifierLetter:
1020 case UnicodeCategory.ConnectorPunctuation:
1026 for (int x = 1; x < value.Length; ++x) {
1027 switch (char.GetUnicodeCategory (value[x])) {
1028 case UnicodeCategory.LetterNumber:
1029 case UnicodeCategory.LowercaseLetter:
1030 case UnicodeCategory.TitlecaseLetter:
1031 case UnicodeCategory.UppercaseLetter:
1032 case UnicodeCategory.OtherLetter:
1033 case UnicodeCategory.ModifierLetter:
1034 case UnicodeCategory.ConnectorPunctuation:
1035 case UnicodeCategory.DecimalDigitNumber:
1036 case UnicodeCategory.NonSpacingMark:
1037 case UnicodeCategory.SpacingCombiningMark:
1038 case UnicodeCategory.Format:
1048 protected abstract bool Supports (GeneratorSupport supports);
1050 bool ICodeGenerator.Supports (GeneratorSupport value)
1052 return Supports (value);
1055 protected virtual void ValidateIdentifier (string value)
1057 if (!(IsValidIdentifier (value)))
1058 throw new ArgumentException ("Identifier is invalid", "value");
1062 public static void ValidateIdentifiers (CodeObject e)
1064 throw new NotImplementedException();
1067 void ICodeGenerator.ValidateIdentifier (string value)
1069 ValidateIdentifier (value);
1072 // The position in the array determines the order in which those
1073 // kind of CodeTypeMembers are generated. Less is more ;-)
1074 static Type [] memberTypes = { typeof (CodeMemberField),
1075 typeof (CodeSnippetTypeMember),
1076 typeof (CodeTypeConstructor),
1077 typeof (CodeConstructor),
1078 typeof (CodeMemberProperty),
1079 typeof (CodeMemberEvent),
1080 typeof (CodeMemberMethod),
1081 typeof (CodeTypeDeclaration),
1082 typeof (CodeEntryPointMethod)
1086 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)
1091 internal class Visitor : ICodeDomVisitor {
1094 public Visitor (CodeGenerator generator)
1101 public void Visit (CodeArgumentReferenceExpression o)
1103 g.GenerateArgumentReferenceExpression (o);
1106 public void Visit (CodeArrayCreateExpression o)
1108 g.GenerateArrayCreateExpression (o);
1111 public void Visit (CodeArrayIndexerExpression o)
1113 g.GenerateArrayIndexerExpression (o);
1116 public void Visit (CodeBaseReferenceExpression o)
1118 g.GenerateBaseReferenceExpression (o);
1121 public void Visit (CodeBinaryOperatorExpression o)
1123 g.GenerateBinaryOperatorExpression (o);
1126 public void Visit (CodeCastExpression o)
1128 g.GenerateCastExpression (o);
1132 public void Visit (CodeDefaultValueExpression o)
1134 g.GenerateDefaultValueExpression (o);
1138 public void Visit (CodeDelegateCreateExpression o)
1140 g.GenerateDelegateCreateExpression (o);
1143 public void Visit (CodeDelegateInvokeExpression o)
1145 g.GenerateDelegateInvokeExpression (o);
1148 public void Visit (CodeDirectionExpression o)
1150 g.GenerateDirectionExpression (o);
1153 public void Visit (CodeEventReferenceExpression o)
1155 g.GenerateEventReferenceExpression (o);
1158 public void Visit (CodeFieldReferenceExpression o)
1160 g.GenerateFieldReferenceExpression (o);
1163 public void Visit (CodeIndexerExpression o)
1165 g.GenerateIndexerExpression (o);
1168 public void Visit (CodeMethodInvokeExpression o)
1170 g.GenerateMethodInvokeExpression (o);
1173 public void Visit (CodeMethodReferenceExpression o)
1175 g.GenerateMethodReferenceExpression (o);
1178 public void Visit (CodeObjectCreateExpression o)
1180 g.GenerateObjectCreateExpression (o);
1183 public void Visit (CodeParameterDeclarationExpression o)
1185 g.GenerateParameterDeclarationExpression (o);
1188 public void Visit (CodePrimitiveExpression o)
1190 g.GeneratePrimitiveExpression (o);
1193 public void Visit (CodePropertyReferenceExpression o)
1195 g.GeneratePropertyReferenceExpression (o);
1198 public void Visit (CodePropertySetValueReferenceExpression o)
1200 g.GeneratePropertySetValueReferenceExpression (o);
1203 public void Visit (CodeSnippetExpression o)
1205 g.GenerateSnippetExpression (o);
1208 public void Visit (CodeThisReferenceExpression o)
1210 g.GenerateThisReferenceExpression (o);
1213 public void Visit (CodeTypeOfExpression o)
1215 g.GenerateTypeOfExpression (o);
1218 public void Visit (CodeTypeReferenceExpression o)
1220 g.GenerateTypeReferenceExpression (o);
1223 public void Visit (CodeVariableReferenceExpression o)
1225 g.GenerateVariableReferenceExpression (o);
1230 public void Visit (CodeAssignStatement o)
1232 g.GenerateAssignStatement (o);
1235 public void Visit (CodeAttachEventStatement o)
1237 g.GenerateAttachEventStatement (o);
1240 public void Visit (CodeCommentStatement o)
1242 g.GenerateCommentStatement (o);
1245 public void Visit (CodeConditionStatement o)
1247 g.GenerateConditionStatement (o);
1250 public void Visit (CodeExpressionStatement o)
1252 g.GenerateExpressionStatement (o);
1255 public void Visit (CodeGotoStatement o)
1257 g.GenerateGotoStatement (o);
1260 public void Visit (CodeIterationStatement o)
1262 g.GenerateIterationStatement (o);
1265 public void Visit (CodeLabeledStatement o)
1267 g.GenerateLabeledStatement (o);
1270 public void Visit (CodeMethodReturnStatement o)
1272 g.GenerateMethodReturnStatement (o);
1275 public void Visit (CodeRemoveEventStatement o)
1277 g.GenerateRemoveEventStatement (o);
1280 public void Visit (CodeThrowExceptionStatement o)
1282 g.GenerateThrowExceptionStatement (o);
1285 public void Visit (CodeTryCatchFinallyStatement o)
1287 g.GenerateTryCatchFinallyStatement (o);
1290 public void Visit (CodeVariableDeclarationStatement o)
1292 g.GenerateVariableDeclarationStatement (o);
1297 public void Visit (CodeConstructor o)
1299 g.GenerateConstructor (o, g.CurrentClass);
1302 public void Visit (CodeEntryPointMethod o)
1304 g.GenerateEntryPointMethod (o, g.CurrentClass);
1307 public void Visit (CodeMemberEvent o)
1309 g.GenerateEvent (o, g.CurrentClass);
1312 public void Visit (CodeMemberField o)
1314 g.GenerateField (o);
1317 public void Visit (CodeMemberMethod o)
1319 g.GenerateMethod (o, g.CurrentClass);
1322 public void Visit (CodeMemberProperty o)
1324 g.GenerateProperty (o, g.CurrentClass);
1327 public void Visit (CodeSnippetTypeMember o)
1329 g.GenerateSnippetMember (o);
1332 public void Visit (CodeTypeConstructor o)
1334 g.GenerateTypeConstructor (o);