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);
442 GenerateNamespaceEnd (ns);
445 protected abstract void GenerateNamespaceStart (CodeNamespace ns);
446 protected abstract void GenerateNamespaceEnd (CodeNamespace ns);
447 protected abstract void GenerateNamespaceImport (CodeNamespaceImport i);
448 protected void GenerateNamespaceImports (CodeNamespace e)
450 foreach (CodeNamespaceImport import in e.Imports) {
451 if (import.LinePragma != null)
452 GenerateLinePragmaStart (import.LinePragma);
454 GenerateNamespaceImport (import);
456 if (import.LinePragma != null)
457 GenerateLinePragmaEnd (import.LinePragma);
461 protected void GenerateNamespaces (CodeCompileUnit e)
463 foreach (CodeNamespace ns in e.Namespaces)
464 GenerateNamespace (ns);
467 protected abstract void GenerateObjectCreateExpression (CodeObjectCreateExpression e);
469 protected virtual void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
471 if (e.CustomAttributes != null && e.CustomAttributes.Count > 0)
472 OutputAttributeDeclarations (e.CustomAttributes);
473 OutputDirection (e.Direction);
476 output.Write (e.Name);
479 protected virtual void GeneratePrimitiveExpression (CodePrimitiveExpression e)
481 if (e.Value == null) {
482 output.Write (NullToken);
486 Type type = e.Value.GetType ();
487 if (type == typeof (bool)) {
488 output.Write (e.Value.ToString ().ToLower (CultureInfo.InvariantCulture));
489 } else if (type == typeof (char)) {
490 output.Write ("'" + e.Value.ToString () + "'");
491 } else if (type == typeof (string)) {
492 output.Write (QuoteSnippetString ((string) e.Value));
493 } else if (type == typeof (float)) {
494 GenerateSingleFloatValue((float) e.Value);
495 } else if (type == typeof (double)) {
496 GenerateDoubleValue((double) e.Value);
497 } else if (type == typeof (decimal)) {
498 this.GenerateDecimalValue((decimal) e.Value);
499 } else if (type == typeof (byte) || type == typeof (short) ||
500 type == typeof (int) || type == typeof (long)) {
501 // All of these should be IFormatable, I am just being safe/slow
502 IFormattable formattable = e.Value as IFormattable;
503 if (formattable != null) {
504 output.Write (formattable.ToString (null, CultureInfo.InvariantCulture));
506 output.Write (e.Value.ToString ());
509 throw new ArgumentException (string.Format(CultureInfo.InvariantCulture,
510 "Invalid Primitive Type: {0}. Only CLS compliant primitive " +
511 "types can be used. Consider using CodeObjectCreateExpression.",
516 protected abstract void GenerateProperty (CodeMemberProperty p, CodeTypeDeclaration d);
517 protected abstract void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression e);
518 protected abstract void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression e);
519 protected abstract void GenerateRemoveEventStatement (CodeRemoveEventStatement statement);
521 protected virtual void GenerateSingleFloatValue (Single s)
523 output.Write (s.ToString(CultureInfo.InvariantCulture));
526 protected virtual void GenerateSnippetCompileUnit (CodeSnippetCompileUnit e)
528 if (e.LinePragma != null)
529 GenerateLinePragmaStart (e.LinePragma);
531 output.WriteLine (e.Value);
533 if (e.LinePragma != null)
534 GenerateLinePragmaEnd (e.LinePragma);
538 protected abstract void GenerateSnippetExpression (CodeSnippetExpression e);
539 protected abstract void GenerateSnippetMember (CodeSnippetTypeMember m);
540 protected virtual void GenerateSnippetStatement (CodeSnippetStatement s)
542 output.WriteLine (s.Value);
545 protected void GenerateStatement (CodeStatement s)
547 bool handled = false;
550 if (s.StartDirectives.Count > 0)
551 GenerateDirectives (s.StartDirectives);
553 if (s.LinePragma != null)
554 GenerateLinePragmaStart (s.LinePragma);
556 CodeAssignStatement assign = s as CodeAssignStatement;
557 if (assign != null) {
558 GenerateAssignStatement (assign);
561 CodeAttachEventStatement attach = s as CodeAttachEventStatement;
562 if (attach != null) {
563 GenerateAttachEventStatement (attach);
566 CodeCommentStatement comment = s as CodeCommentStatement;
567 if (comment != null) {
568 GenerateCommentStatement (comment);
571 CodeConditionStatement condition = s as CodeConditionStatement;
572 if (condition != null) {
573 GenerateConditionStatement (condition);
576 CodeExpressionStatement expression = s as CodeExpressionStatement;
577 if (expression != null) {
578 GenerateExpressionStatement (expression);
581 CodeGotoStatement gotostmt = s as CodeGotoStatement;
582 if (gotostmt != null) {
583 GenerateGotoStatement (gotostmt);
586 CodeIterationStatement iteration = s as CodeIterationStatement;
587 if (iteration != null) {
588 GenerateIterationStatement (iteration);
591 CodeLabeledStatement label = s as CodeLabeledStatement;
593 GenerateLabeledStatement (label);
596 CodeMethodReturnStatement returnstmt = s as CodeMethodReturnStatement;
597 if (returnstmt != null) {
598 GenerateMethodReturnStatement (returnstmt);
601 CodeRemoveEventStatement remove = s as CodeRemoveEventStatement;
602 if (remove != null) {
603 GenerateRemoveEventStatement (remove);
606 CodeSnippetStatement snippet = s as CodeSnippetStatement;
607 if (snippet != null) {
612 GenerateSnippetStatement (snippet);
617 GenerateSnippetStatement (snippet);
621 CodeThrowExceptionStatement exception = s as CodeThrowExceptionStatement;
622 if (exception != null) {
623 GenerateThrowExceptionStatement (exception);
626 CodeTryCatchFinallyStatement trycatch = s as CodeTryCatchFinallyStatement;
627 if (trycatch != null) {
628 GenerateTryCatchFinallyStatement (trycatch);
631 CodeVariableDeclarationStatement declaration = s as CodeVariableDeclarationStatement;
632 if (declaration != null) {
633 GenerateVariableDeclarationStatement (declaration);
638 throw new ArgumentException ("Element type " + s + " is not supported.");
640 if (s.LinePragma != null)
641 GenerateLinePragmaEnd (s.LinePragma);
644 if (s.EndDirectives.Count > 0)
645 GenerateDirectives (s.EndDirectives);
649 protected void GenerateStatements (CodeStatementCollection c)
651 foreach (CodeStatement statement in c)
652 GenerateStatement (statement);
655 protected abstract void GenerateThisReferenceExpression (CodeThisReferenceExpression e);
656 protected abstract void GenerateThrowExceptionStatement (CodeThrowExceptionStatement s);
657 protected abstract void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement s);
658 protected abstract void GenerateTypeEnd (CodeTypeDeclaration declaration);
659 protected abstract void GenerateTypeConstructor (CodeTypeConstructor constructor);
661 protected virtual void GenerateTypeOfExpression (CodeTypeOfExpression e)
663 output.Write ("typeof(");
668 protected virtual void GenerateTypeReferenceExpression (CodeTypeReferenceExpression e)
673 protected void GenerateTypes (CodeNamespace e)
675 foreach (CodeTypeDeclaration type in e.Types) {
676 if (options.BlankLinesBetweenMembers)
683 protected abstract void GenerateTypeStart (CodeTypeDeclaration declaration);
684 protected abstract void GenerateVariableDeclarationStatement (CodeVariableDeclarationStatement e);
685 protected abstract void GenerateVariableReferenceExpression (CodeVariableReferenceExpression e);
694 protected virtual void OutputAttributeArgument (CodeAttributeArgument argument)
696 string name = argument.Name;
697 if ((name != null) && (name.Length > 0)) {
701 GenerateExpression (argument.Value);
704 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
706 output.Write (attribute.Name.Replace ('+', '.'));
708 IEnumerator enumerator = attribute.Arguments.GetEnumerator();
709 if (enumerator.MoveNext()) {
710 CodeAttributeArgument argument = (CodeAttributeArgument)enumerator.Current;
711 OutputAttributeArgument (argument);
713 while (enumerator.MoveNext()) {
715 argument = (CodeAttributeArgument)enumerator.Current;
716 OutputAttributeArgument (argument);
722 protected virtual void OutputAttributeDeclarations (CodeAttributeDeclarationCollection attributes)
724 GenerateAttributeDeclarationsStart (attributes);
726 IEnumerator enumerator = attributes.GetEnumerator();
727 if (enumerator.MoveNext()) {
728 CodeAttributeDeclaration attribute = (CodeAttributeDeclaration)enumerator.Current;
730 OutputAttributeDeclaration (attribute);
732 while (enumerator.MoveNext()) {
733 attribute = (CodeAttributeDeclaration)enumerator.Current;
735 output.WriteLine (',');
736 OutputAttributeDeclaration (attribute);
740 GenerateAttributeDeclarationsEnd (attributes);
743 protected virtual void OutputDirection (FieldDirection direction)
746 case FieldDirection.In:
747 //output.Write ("in ");
749 case FieldDirection.Out:
750 output.Write ("out ");
752 case FieldDirection.Ref:
753 output.Write ("ref ");
758 protected virtual void OutputExpressionList (CodeExpressionCollection expressions)
760 OutputExpressionList (expressions, false);
763 protected virtual void OutputExpressionList (CodeExpressionCollection expressions,
764 bool newLineBetweenItems)
766 IEnumerator enumerator = expressions.GetEnumerator();
767 if (enumerator.MoveNext()) {
768 CodeExpression expression = (CodeExpression)enumerator.Current;
770 GenerateExpression (expression);
772 while (enumerator.MoveNext()) {
773 expression = (CodeExpression)enumerator.Current;
776 if (newLineBetweenItems)
781 GenerateExpression (expression);
786 protected virtual void OutputFieldScopeModifier (MemberAttributes attributes)
788 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
789 output.Write ("new ");
791 switch (attributes & MemberAttributes.ScopeMask) {
792 case MemberAttributes.Static:
793 output.Write ("static ");
795 case MemberAttributes.Const:
796 output.Write ("const ");
801 protected virtual void OutputIdentifier (string ident)
803 output.Write (ident);
806 protected virtual void OutputMemberAccessModifier (MemberAttributes attributes)
808 switch (attributes & MemberAttributes.AccessMask) {
809 case MemberAttributes.Assembly:
810 output.Write ("internal ");
812 case MemberAttributes.FamilyAndAssembly:
814 output.Write ("internal ");
816 output.Write ("/*FamANDAssem*/ internal ");
819 case MemberAttributes.Family:
820 output.Write ("protected ");
822 case MemberAttributes.FamilyOrAssembly:
823 output.Write ("protected internal ");
825 case MemberAttributes.Private:
826 output.Write ("private ");
828 case MemberAttributes.Public:
829 output.Write ("public ");
834 protected virtual void OutputMemberScopeModifier (MemberAttributes attributes)
837 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
838 output.Write( "new " );
841 switch (attributes & MemberAttributes.ScopeMask) {
842 case MemberAttributes.Abstract:
843 output.Write ("abstract ");
845 case MemberAttributes.Final:
848 case MemberAttributes.Static:
849 output.Write ("static ");
851 case MemberAttributes.Override:
852 output.Write ("override ");
856 // FUNNY! if the scope value is
857 // rubbish (0 or >Const), and access
858 // is public or protected, make it
861 // i'm not sure whether this is 100%
862 // correct, but it seems to be MS
865 // On .NET 2.0, internal members
866 // are also marked "virtual".
868 MemberAttributes access = attributes & MemberAttributes.AccessMask;
869 if (access == MemberAttributes.Public || access == MemberAttributes.Family)
870 output.Write ("virtual ");
875 protected virtual void OutputOperator (CodeBinaryOperatorType op)
878 case CodeBinaryOperatorType.Add:
881 case CodeBinaryOperatorType.Subtract:
884 case CodeBinaryOperatorType.Multiply:
887 case CodeBinaryOperatorType.Divide:
890 case CodeBinaryOperatorType.Modulus:
893 case CodeBinaryOperatorType.Assign:
896 case CodeBinaryOperatorType.IdentityInequality:
899 case CodeBinaryOperatorType.IdentityEquality:
902 case CodeBinaryOperatorType.ValueEquality:
905 case CodeBinaryOperatorType.BitwiseOr:
908 case CodeBinaryOperatorType.BitwiseAnd:
911 case CodeBinaryOperatorType.BooleanOr:
914 case CodeBinaryOperatorType.BooleanAnd:
917 case CodeBinaryOperatorType.LessThan:
920 case CodeBinaryOperatorType.LessThanOrEqual:
923 case CodeBinaryOperatorType.GreaterThan:
926 case CodeBinaryOperatorType.GreaterThanOrEqual:
932 protected virtual void OutputParameters (CodeParameterDeclarationExpressionCollection parameters)
935 foreach (CodeParameterDeclarationExpression expr in parameters) {
940 GenerateExpression (expr);
944 protected abstract void OutputType (CodeTypeReference t);
946 protected virtual void OutputTypeAttributes (TypeAttributes attributes,
950 switch (attributes & TypeAttributes.VisibilityMask) {
951 case TypeAttributes.NotPublic:
952 // private by default
955 case TypeAttributes.Public:
956 case TypeAttributes.NestedPublic:
957 output.Write ("public ");
960 case TypeAttributes.NestedPrivate:
961 output.Write ("private ");
966 output.Write ("struct ");
969 output.Write ("enum ");
971 if ((attributes & TypeAttributes.Interface) != 0)
972 output.Write ("interface ");
973 else if (currentType is CodeTypeDelegate)
974 output.Write ("delegate ");
976 if ((attributes & TypeAttributes.Sealed) != 0)
977 output.Write ("sealed ");
978 if ((attributes & TypeAttributes.Abstract) != 0)
979 output.Write ("abstract ");
981 output.Write ("class ");
986 protected virtual void OutputTypeNamePair (CodeTypeReference type,
994 protected abstract string QuoteSnippetString (string value);
999 protected abstract string CreateEscapedIdentifier (string value);
1000 string ICodeGenerator.CreateEscapedIdentifier (string value)
1002 return CreateEscapedIdentifier (value);
1005 protected abstract string CreateValidIdentifier (string value);
1006 string ICodeGenerator.CreateValidIdentifier (string value)
1008 return CreateValidIdentifier (value);
1011 private void InitOutput (TextWriter output, CodeGeneratorOptions options)
1013 if (options == null)
1014 options = new CodeGeneratorOptions ();
1016 this.output = new IndentedTextWriter (output, options.IndentString);
1017 this.options = options;
1020 void ICodeGenerator.GenerateCodeFromCompileUnit (CodeCompileUnit compileUnit,
1022 CodeGeneratorOptions options)
1024 InitOutput (output, options);
1026 if (compileUnit is CodeSnippetCompileUnit) {
1027 GenerateSnippetCompileUnit ((CodeSnippetCompileUnit) compileUnit);
1029 GenerateCompileUnit (compileUnit);
1033 void ICodeGenerator.GenerateCodeFromExpression (CodeExpression expression,
1035 CodeGeneratorOptions options)
1037 InitOutput (output, options);
1038 GenerateExpression (expression);
1041 void ICodeGenerator.GenerateCodeFromNamespace (CodeNamespace ns,
1043 CodeGeneratorOptions options)
1045 InitOutput (output, options);
1046 GenerateNamespace (ns);
1049 void ICodeGenerator.GenerateCodeFromStatement (CodeStatement statement,
1051 CodeGeneratorOptions options)
1053 InitOutput (output, options);
1054 GenerateStatement (statement);
1057 void ICodeGenerator.GenerateCodeFromType (CodeTypeDeclaration type,
1059 CodeGeneratorOptions options)
1061 InitOutput (output, options);
1062 GenerateType (type);
1065 private void GenerateType (CodeTypeDeclaration type)
1067 this.currentType = type;
1070 if (type.StartDirectives.Count > 0)
1071 GenerateDirectives (type.StartDirectives);
1073 foreach (CodeCommentStatement statement in type.Comments)
1074 GenerateCommentStatement (statement);
1076 if (type.LinePragma != null)
1077 GenerateLinePragmaStart (type.LinePragma);
1079 GenerateTypeStart (type);
1081 CodeTypeMember[] members = new CodeTypeMember[type.Members.Count];
1082 type.Members.CopyTo (members, 0);
1085 if (!Options.VerbatimOrder)
1088 int[] order = new int[members.Length];
1089 for (int n = 0; n < members.Length; n++)
1090 order[n] = Array.IndexOf (memberTypes, members[n].GetType ()) * members.Length + n;
1092 Array.Sort (order, members);
1095 // WARNING: if anything is missing in the foreach loop and you add it, add the type in
1096 // its corresponding place in CodeTypeMemberComparer class (below)
1098 CodeTypeDeclaration subtype = null;
1099 foreach (CodeTypeMember member in members) {
1100 CodeTypeMember prevMember = this.currentMember;
1101 this.currentMember = member;
1103 if (prevMember != null && subtype == null) {
1104 if (prevMember.LinePragma != null)
1105 GenerateLinePragmaEnd (prevMember.LinePragma);
1107 if (prevMember.EndDirectives.Count > 0)
1108 GenerateDirectives (prevMember.EndDirectives);
1112 if (options.BlankLinesBetweenMembers)
1113 output.WriteLine ();
1115 subtype = member as CodeTypeDeclaration;
1116 if (subtype != null) {
1117 GenerateType (subtype);
1118 this.currentType = type;
1123 if (currentMember.StartDirectives.Count > 0)
1124 GenerateDirectives (currentMember.StartDirectives);
1126 foreach (CodeCommentStatement statement in member.Comments)
1127 GenerateCommentStatement (statement);
1129 if (member.LinePragma != null)
1130 GenerateLinePragmaStart (member.LinePragma);
1132 CodeMemberEvent eventm = member as CodeMemberEvent;
1133 if (eventm != null) {
1134 GenerateEvent (eventm, type);
1137 CodeMemberField field = member as CodeMemberField;
1138 if (field != null) {
1139 GenerateField (field);
1142 CodeEntryPointMethod epmethod = member as CodeEntryPointMethod;
1143 if (epmethod != null) {
1144 GenerateEntryPointMethod (epmethod, type);
1147 CodeTypeConstructor typeCtor = member as CodeTypeConstructor;
1148 if (typeCtor != null) {
1149 GenerateTypeConstructor (typeCtor);
1152 CodeConstructor ctor = member as CodeConstructor;
1154 GenerateConstructor (ctor, type);
1157 CodeMemberMethod method = member as CodeMemberMethod;
1158 if (method != null) {
1159 GenerateMethod (method, type);
1162 CodeMemberProperty property = member as CodeMemberProperty;
1163 if (property != null) {
1164 GenerateProperty (property, type);
1167 CodeSnippetTypeMember snippet = member as CodeSnippetTypeMember;
1168 if (snippet != null) {
1169 GenerateSnippetMember (snippet);
1173 this.currentMember = prevMember;
1176 // Hack because of previous continue usage
1177 if (currentMember != null && !(currentMember is CodeTypeDeclaration)) {
1178 if (currentMember.LinePragma != null)
1179 GenerateLinePragmaEnd (currentMember.LinePragma);
1181 if (currentMember.EndDirectives.Count > 0)
1182 GenerateDirectives (currentMember.EndDirectives);
1186 this.currentType = type;
1187 GenerateTypeEnd (type);
1189 if (type.LinePragma != null)
1190 GenerateLinePragmaEnd (type.LinePragma);
1193 if (type.EndDirectives.Count > 0)
1194 GenerateDirectives (type.EndDirectives);
1198 protected abstract string GetTypeOutput (CodeTypeReference type);
1200 string ICodeGenerator.GetTypeOutput (CodeTypeReference type)
1202 return GetTypeOutput (type);
1205 protected abstract bool IsValidIdentifier (string value);
1207 bool ICodeGenerator.IsValidIdentifier (string value)
1209 return IsValidIdentifier (value);
1212 public static bool IsValidLanguageIndependentIdentifier (string value)
1216 if (value.Equals (string.Empty))
1218 switch (char.GetUnicodeCategory (value[0]))
1220 case UnicodeCategory.LetterNumber:
1221 case UnicodeCategory.LowercaseLetter:
1222 case UnicodeCategory.TitlecaseLetter:
1223 case UnicodeCategory.UppercaseLetter:
1224 case UnicodeCategory.OtherLetter:
1225 case UnicodeCategory.ModifierLetter:
1226 case UnicodeCategory.ConnectorPunctuation:
1227 if (value.Length > 1)
1229 for (int x = 0; x < value.Length; x++)
1231 switch (char.GetUnicodeCategory (value[x]))
1233 case UnicodeCategory.LetterNumber:
1234 case UnicodeCategory.LowercaseLetter:
1235 case UnicodeCategory.TitlecaseLetter:
1236 case UnicodeCategory.UppercaseLetter:
1237 case UnicodeCategory.OtherLetter:
1238 case UnicodeCategory.ModifierLetter:
1239 case UnicodeCategory.ConnectorPunctuation:
1240 case UnicodeCategory.DecimalDigitNumber:
1241 case UnicodeCategory.NonSpacingMark:
1242 case UnicodeCategory.SpacingCombiningMark:
1243 case UnicodeCategory.Format:
1256 protected abstract bool Supports (GeneratorSupport supports);
1258 bool ICodeGenerator.Supports (GeneratorSupport value)
1260 return Supports (value);
1263 protected virtual void ValidateIdentifier (string value)
1265 if (!(IsValidIdentifier (value)))
1266 throw new ArgumentException ("Identifier is invalid", "value");
1270 public static void ValidateIdentifiers (CodeObject e)
1272 throw new NotImplementedException();
1275 void ICodeGenerator.ValidateIdentifier (string value)
1277 ValidateIdentifier (value);
1280 // The position in the array determines the order in which those
1281 // kind of CodeTypeMembers are generated. Less is more ;-)
1282 static Type [] memberTypes = { typeof (CodeMemberField),
1283 typeof (CodeSnippetTypeMember),
1284 typeof (CodeTypeConstructor),
1285 typeof (CodeConstructor),
1286 typeof (CodeMemberProperty),
1287 typeof (CodeMemberEvent),
1288 typeof (CodeMemberMethod),
1289 typeof (CodeTypeDeclaration),
1290 typeof (CodeEntryPointMethod)
1294 protected virtual void GenerateDirectives (CodeDirectiveCollection directives)