2 // Microsoft.VisualBasic.VBCodeGenerator.cs
5 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
6 // (partially based on CSharpCodeGenerator)
7 // Jochen Wezel (jwezel@compumaster.de)
8 // Frederik Carlier (frederik.carlier@carlier-online.be)
9 // Rolf Bjarne Kvinge (RKvinge@novell.com)
11 // (C) 2003 Andreas Nahr
12 // (C) 2003 Jochen Wezel (http://www.compumaster.de)
15 // 2003-11-06 JW: some corrections regarding missing spaces in generated code (e. g. "Property ")
16 // 2003-11-06 JW: QuoteSnippetString implemented
17 // 2003-11-08 JW: automatically add Microsoft.VisualBasic
18 // 2003-11-12 JW: some corrections to allow correct compilation
19 // 2003-11-28 JW: implementing code differences into current build of this file
20 // 2003-12-10 JW: added "String." for the ChrW method because mbas doesn't support it without the String currently / TODO: remove it ASAP!
21 // 2007-04-13 FC: Added support for the IdentityInequality operator when comparing against Nothing
24 // Permission is hereby granted, free of charge, to any person obtaining
25 // a copy of this software and associated documentation files (the
26 // "Software"), to deal in the Software without restriction, including
27 // without limitation the rights to use, copy, modify, merge, publish,
28 // distribute, sublicense, and/or sell copies of the Software, and to
29 // permit persons to whom the Software is furnished to do so, subject to
30 // the following conditions:
32 // The above copyright notice and this permission notice shall be
33 // included in all copies or substantial portions of the Software.
35 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
38 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
39 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
40 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
41 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46 using System.Globalization;
48 using System.Text.RegularExpressions;
50 using System.CodeDom.Compiler;
52 using System.Reflection;
53 using System.Collections;
55 namespace Microsoft.VisualBasic
57 internal class VBCodeGenerator : CodeGenerator
59 private string [] Keywords = new string [] {
60 "AddHandler", "AddressOf", "Alias", "And",
61 "AndAlso", "Ansi", "As", "Assembly",
62 "Auto", "Boolean", "ByRef", "Byte",
63 "ByVal", "Call", "Case", "Catch",
64 "CBool", "CByte", "CChar", "CDate",
65 "CDec", "CDbl", "Char", "CInt",
66 "Class", "CLng", "CObj", "Const",
67 "CShort", "CSng", "CStr", "CType",
68 "Date", "Decimal", "Declare", "Default",
69 "Delegate", "Dim", "DirectCast", "Do",
70 "Double", "Each", "Else", "ElseIf",
71 "End", "Enum", "Erase", "Error",
72 "Event", "Exit", "False", "Finally",
73 "For", "Friend", "Function", "Get",
74 "GetType", "Global", "GoSub", "GoTo", "Handles",
75 "If", "Implements", "Imports", "In",
76 "Inherits", "Integer", "Interface", "Is",
77 "Let", "Lib", "Like", "Long",
78 "Loop", "Me", "Mod", "Module",
79 "MustInherit", "MustOverride", "MyBase", "MyClass",
80 "Namespace", "New", "Next", "Not",
81 "Nothing", "NotInheritable", "NotOverridable", "Object",
82 "On", "Option", "Optional", "Or",
83 "OrElse", "Overloads", "Overridable", "Overrides",
84 "ParamArray", "Partial", "Preserve", "Private", "Property",
85 "Protected", "Public", "RaiseEvent", "ReadOnly",
86 "ReDim", "REM", "RemoveHandler", "Resume",
87 "Return", "Select", "Set", "Shadows",
88 "Shared", "Short", "Single", "Static",
89 "Step", "Stop", "String", "Structure",
90 "Sub", "SyncLock", "Then", "Throw",
91 "To", "True", "Try", "TypeOf",
92 "Unicode", "Until", "Variant", "When",
93 "While", "With", "WithEvents", "WriteOnly",
96 public VBCodeGenerator()
100 protected override string NullToken {
106 protected override void ContinueOnNewLine (string st)
109 Output.WriteLine (" _");
112 protected override void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
114 // We need to special case for comparisons against null;
115 // in Visual Basic the "Not (Expr) Is Nothing" construct is used
117 bool null_comparison = false;
118 bool reverse = false;
119 if (e.Operator == CodeBinaryOperatorType.IdentityInequality) {
120 CodePrimitiveExpression nothing;
121 nothing = e.Left as CodePrimitiveExpression;
122 if (nothing == null) {
123 nothing = e.Right as CodePrimitiveExpression;
127 null_comparison = nothing != null && nothing.Value == null;
130 if (null_comparison) {
131 TextWriter output = Output;
133 output.Write ("(Not (");
134 GenerateExpression (reverse ? e.Right : e.Left);
135 output.Write (") Is ");
136 GenerateExpression (reverse ? e.Left : e.Right);
139 base.GenerateBinaryOperatorExpression (e);
143 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
145 TextWriter output = Output;
147 output.Write ("New ");
149 CodeExpressionCollection initializers = expression.Initializers;
150 CodeTypeReference createType = expression.CreateType;
152 if (initializers.Count > 0) {
154 OutputType (createType);
156 output.Write ("() {");
158 OutputExpressionList (initializers);
162 CodeTypeReference arrayType = createType.ArrayElementType;
163 while (arrayType != null) {
164 createType = arrayType;
165 arrayType = arrayType.ArrayElementType;
168 OutputType (createType);
172 CodeExpression size = expression.SizeExpression;
174 GenerateExpression (size);
176 output.Write (expression.Size);
178 output.Write (") - 1) {}");
182 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
184 Output.Write ("MyBase");
187 protected override void GenerateCastExpression (CodeCastExpression expression)
189 TextWriter output = Output;
190 // ENHANCE: Use a DirectCast if it is known that expression.Expression is no Value-Type
191 output.Write ("CType(");
192 GenerateExpression (expression.Expression);
194 OutputType (expression.TargetType);
198 private bool AsBool (object datavalue)
200 return datavalue != null && datavalue is bool && (bool) datavalue;
203 private string OnOff (bool datavalue)
205 return datavalue ? "On" : "Off";
208 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
210 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
211 GenerateComment (new CodeComment (" <autogenerated>"));
212 GenerateComment (new CodeComment (" This code was generated by a tool."));
213 GenerateComment (new CodeComment (" Mono Runtime Version: " + System.Environment.Version));
214 GenerateComment (new CodeComment (""));
215 GenerateComment (new CodeComment (" Changes to this file may cause incorrect behavior and will be lost if "));
216 GenerateComment (new CodeComment (" the code is regenerated."));
217 GenerateComment (new CodeComment (" </autogenerated>"));
218 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
220 if (AsBool (compileUnit.UserData ["AllowLateBound"])) {
221 Output.WriteLine("Option Explicit {0}", OnOff (AsBool (compileUnit.UserData ["RequireVariableDeclaration"])));
222 Output.WriteLine("Option Strict Off");
224 Output.WriteLine("Option Explicit On"); // Strict On implies Explicit On
225 Output.WriteLine("Option Strict On");
230 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
232 GenerateCompileUnitStart (compileUnit);
234 OutputAttributes (compileUnit.AssemblyCustomAttributes,
235 "Assembly: ", LineHandling.NewLine);
237 GenerateNamespaces (compileUnit);
239 GenerateCompileUnitEnd (compileUnit);
242 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
244 TextWriter output = Output;
246 output.Write ("AddressOf ");
248 CodeExpression targetObject = expression.TargetObject;
249 if (targetObject != null) {
250 GenerateExpression (targetObject);
253 output.Write (expression.MethodName);
256 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
258 CodeExpression targetObject = expression.TargetObject;
259 if (targetObject != null) {
260 GenerateExpression (targetObject);
263 Output.Write (CreateEscapedIdentifier (expression.FieldName));
266 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
268 Output.Write (CreateEscapedIdentifier (expression.ParameterName));
271 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
273 Output.Write (CreateEscapedIdentifier (expression.VariableName));
276 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
278 TextWriter output = Output;
280 GenerateExpression (expression.TargetObject);
282 OutputExpressionList (expression.Indices);
286 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
288 TextWriter output = Output;
290 GenerateExpression (expression.TargetObject);
292 OutputExpressionList (expression.Indices);
296 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
298 Output.Write (expression.Value);
301 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
303 TextWriter output = Output;
305 GenerateMethodReferenceExpression (expression.Method);
308 OutputExpressionList (expression.Parameters);
312 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
314 if (expression.TargetObject != null) {
315 GenerateExpression (expression.TargetObject);
318 Output.Write (CreateEscapedIdentifier (expression.MethodName));
321 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
323 if (expression.TargetObject != null) {
324 GenerateExpression (expression.TargetObject);
326 if (expression.TargetObject is CodeThisReferenceExpression) {
327 // We're actually creating a reference to a compiler-generated field here...
328 Output.Write (expression.EventName + "Event");
330 Output.Write (CreateEscapedIdentifier (expression.EventName));
333 Output.Write (CreateEscapedIdentifier (expression.EventName + "Event"));
337 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
339 CodeEventReferenceExpression ev = expression.TargetObject as CodeEventReferenceExpression;
342 Output.Write ("RaiseEvent ");
346 Output.Write ("RaiseEvent ");
348 if (ev.TargetObject != null && !(ev.TargetObject is CodeThisReferenceExpression)) {
349 GenerateExpression (ev.TargetObject);
352 Output.Write (ev.EventName);
353 } else if (expression.TargetObject != null) {
354 GenerateExpression (expression.TargetObject);
357 OutputExpressionList (expression.Parameters);
361 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
363 Output.Write( "New " );
364 OutputType (expression.CreateType);
366 OutputExpressionList (expression.Parameters);
370 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
372 OutputAttributes (e.CustomAttributes, null, LineHandling.InLine);
373 OutputDirection (e.Direction);
374 OutputTypeNamePair (e.Type, e.Name);
377 protected override void GeneratePrimitiveExpression (CodePrimitiveExpression e)
379 if (e.Value is char) {
380 char c = (char) e.Value;
382 Output.Write("Global.Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
383 } else if (e.Value is ushort) {
384 ushort uc = (ushort) e.Value;
385 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
387 } else if (e.Value is uint) {
388 uint ui = (uint) e.Value;
389 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
391 } else if (e.Value is ulong) {
392 ulong ul = (ulong) e.Value;
393 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
395 } else if (e.Value is sbyte) {
396 sbyte sb = (sbyte) e.Value;
397 Output.Write ("CSByte(");
398 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
401 base.GeneratePrimitiveExpression(e);
405 protected override void GenerateSingleFloatValue (float s)
407 base.GenerateSingleFloatValue (s);
408 base.Output.Write ('!');
411 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
413 if (expression.TargetObject != null) {
414 GenerateMemberReferenceExpression (expression.TargetObject, expression.PropertyName);
416 Output.Write (CreateEscapedIdentifier (expression.PropertyName));
420 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
422 Output.Write ("Value");
425 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
430 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
432 GenerateExpression (statement.Expression);
433 Output.WriteLine (); //start new line
436 protected override void GenerateIterationStatement (CodeIterationStatement statement)
438 TextWriter output = Output;
440 GenerateStatement (statement.InitStatement);
441 output.Write ("Do While ");
442 GenerateExpression (statement.TestExpression);
445 GenerateStatements (statement.Statements);
446 GenerateStatement (statement.IncrementStatement);
448 output.WriteLine ("Loop");
451 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
453 Output.Write ("Throw");
454 if (statement.ToThrow != null) {
456 GenerateExpression (statement.ToThrow);
461 protected override void GenerateComment (CodeComment comment)
463 TextWriter output = Output;
464 string commentChars = null;
466 if (comment.DocComment) {
467 commentChars = "'''";
472 output.Write (commentChars);
473 string text = comment.Text;
475 for (int i = 0; i < text.Length; i++) {
476 output.Write (text [i]);
477 if (text[i] == '\r') {
478 if (i < (text.Length - 1) && text [i + 1] == '\n') {
481 output.Write (commentChars);
482 } else if (text [i] == '\n') {
483 output.Write (commentChars);
490 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
492 TextWriter output = Output;
494 if (statement.Expression != null) {
495 output.Write ("Return ");
496 GenerateExpression (statement.Expression);
499 output.WriteLine ("Return");
503 protected override void GenerateConditionStatement (CodeConditionStatement statement)
505 TextWriter output = Output;
506 output.Write ("If ");
508 GenerateExpression (statement.Condition);
510 output.WriteLine (" Then");
512 GenerateStatements (statement.TrueStatements);
515 CodeStatementCollection falses = statement.FalseStatements;
516 if (falses.Count > 0) {
517 output.WriteLine ("Else");
519 GenerateStatements (falses);
523 if (Options.ElseOnClosing)
524 output.WriteLine ("Else");
526 output.WriteLine ("End If");
529 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
531 TextWriter output = Output;
533 output.WriteLine ("Try ");
535 GenerateStatements (statement.TryStatements);
538 foreach (CodeCatchClause clause in statement.CatchClauses) {
539 output.Write ("Catch ");
540 OutputTypeNamePair (clause.CatchExceptionType, clause.LocalName);
543 GenerateStatements (clause.Statements);
547 CodeStatementCollection finallies = statement.FinallyStatements;
548 if (finallies.Count > 0) {
549 output.WriteLine ("Finally");
551 GenerateStatements (finallies);
555 output.WriteLine("End Try");
558 protected override void GenerateAssignStatement (CodeAssignStatement statement)
560 TextWriter output = Output;
561 GenerateExpression (statement.Left);
562 output.Write (" = ");
563 GenerateExpression (statement.Right);
567 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
569 TextWriter output = Output;
571 Output.Write ("AddHandler ");
572 if (statement.Event.TargetObject != null) {
573 GenerateEventReferenceExpression (statement.Event);
575 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
577 Output.Write ( ", ");
578 GenerateExpression (statement.Listener);
582 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
584 TextWriter output = Output;
586 Output.Write ("RemoveHandler ");
587 if (statement.Event.TargetObject != null) {
588 GenerateEventReferenceExpression (statement.Event);
590 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
592 Output.Write ( ", ");
593 GenerateExpression (statement.Listener);
597 protected override void GenerateGotoStatement (CodeGotoStatement statement)
599 TextWriter output = Output;
601 output.Write ("goto ");
602 output.Write (statement.Label);
606 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
608 TextWriter output = Output;
611 output.WriteLine (statement.Label + ":");
613 if (statement.Statement != null) {
614 GenerateStatement (statement.Statement);
618 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
620 TextWriter output = Output;
622 output.Write ("GetType(");
627 protected override void GenerateVariableDeclarationStatement( CodeVariableDeclarationStatement statement )
629 TextWriter output = Output;
631 output.Write ("Dim ");
632 OutputTypeNamePair (statement.Type, statement.Name);
634 CodeExpression initExpression = statement.InitExpression;
635 if (initExpression != null) {
636 output.Write (" = ");
637 GenerateExpression (initExpression);
643 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
646 Output.Write ("#ExternalSource(\"");
647 Output.Write (linePragma.FileName);
648 Output.Write ("\",");
649 Output.Write (linePragma.LineNumber);
650 Output.WriteLine (")");
651 Output.WriteLine ("");
654 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
656 Output.WriteLine ("#End ExternalSource");
659 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
661 if (IsCurrentDelegate || IsCurrentEnum)
664 TextWriter output = Output;
666 OutputAttributes (eventRef.CustomAttributes, null,
667 LineHandling.ContinueLine);
669 OutputMemberAccessModifier (eventRef.Attributes);
671 output.Write ("Event ");
672 OutputTypeNamePair (eventRef.Type, GetEventName(eventRef));
674 if (eventRef.ImplementationTypes.Count > 0) {
675 OutputImplementationTypes (eventRef.ImplementationTypes, eventRef.Name);
676 } else if (eventRef.PrivateImplementationType != null) {
677 output.Write (" Implements ");
678 OutputType (eventRef.PrivateImplementationType);
680 output.Write (eventRef.Name);
686 protected override void GenerateField (CodeMemberField field)
688 if (IsCurrentDelegate || IsCurrentInterface)
691 TextWriter output = Output;
693 OutputAttributes (field.CustomAttributes, null,
694 LineHandling.ContinueLine);
697 output.Write (field.Name);
699 MemberAttributes attributes = field.Attributes;
700 OutputMemberAccessModifier (attributes);
701 OutputVTableModifier (attributes);
702 OutputFieldScopeModifier (attributes);
703 OutputTypeNamePair (field.Type, field.Name);
706 CodeExpression initExpression = field.InitExpression;
707 if (initExpression != null) {
708 output.Write (" = ");
709 GenerateExpression (initExpression);
715 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
717 Output.Write (member.Text);
720 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, CodeTypeDeclaration declaration)
722 OutputAttributes (method.CustomAttributes, null,
723 LineHandling.ContinueLine);
725 Output.WriteLine ("Public Shared Sub Main()");
727 GenerateStatements (method.Statements);
729 Output.WriteLine ("End Sub");
732 [MonoTODO ("partially implemented")]
733 protected override void GenerateMethod (CodeMemberMethod method, CodeTypeDeclaration declaration)
735 if (IsCurrentDelegate || IsCurrentEnum)
738 bool isSub = method.ReturnType.BaseType == typeof(void).FullName;
740 TextWriter output = Output;
742 OutputAttributes (method.CustomAttributes, null,
743 LineHandling.ContinueLine);
745 MemberAttributes attributes = method.Attributes;
747 if (!IsCurrentInterface) {
748 if (method.PrivateImplementationType == null) {
749 OutputMemberAccessModifier (attributes);
750 if (IsOverloaded (method, declaration)) {
751 output.Write ("Overloads ");
754 OutputVTableModifier (attributes);
755 OutputMemberScopeModifier (attributes);
757 OutputVTableModifier (attributes);
761 output.Write ("Sub ");
763 output.Write ("Function ");
765 output.Write (GetMethodName(method));
766 OutputTypeParameters (method.TypeParameters);
768 OutputParameters (method.Parameters);
772 output.Write (" As ");
773 OutputAttributes (method.ReturnTypeCustomAttributes, null,
774 LineHandling.InLine);
775 OutputType (method.ReturnType);
778 if (method.ImplementationTypes.Count > 0) {
779 OutputImplementationTypes (method.ImplementationTypes, method.Name);
780 } else if (method.PrivateImplementationType != null) {
781 output.Write (" Implements ");
782 OutputType (method.PrivateImplementationType);
784 output.Write (method.Name);
788 if (!IsCurrentInterface) {
789 if ((attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
791 GenerateStatements (method.Statements);
794 output.WriteLine ("End Sub");
796 output.WriteLine ("End Function");
801 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
803 if (IsCurrentDelegate || IsCurrentEnum)
806 TextWriter output = Output;
808 OutputAttributes (property.CustomAttributes, null,
809 LineHandling.ContinueLine);
811 MemberAttributes attributes = property.Attributes;
813 if (!IsCurrentInterface) {
814 if (property.PrivateImplementationType == null) {
815 OutputMemberAccessModifier (attributes);
816 if (IsOverloaded (property, declaration)) {
817 output.Write ("Overloads ");
820 OutputVTableModifier (attributes);
821 OutputMemberScopeModifier (attributes);
823 OutputVTableModifier (attributes);
826 // mark property as default property if we're dealing with an indexer
827 if (string.Compare (GetPropertyName(property), "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
828 output.Write ("Default ");
831 if (property.HasGet && (!property.HasSet))
832 output.Write ("ReadOnly " );
834 if (property.HasSet && (!property.HasGet))
835 output.Write ("WriteOnly " );
837 output.Write ("Property ");
838 Output.Write (GetPropertyName (property));
839 // in .NET 2.0, always output parantheses (whether or not there
840 // are any parameters to output
842 OutputParameters (property.Parameters);
844 Output.Write (" As ");
845 Output.Write (GetTypeOutput(property.Type));
847 if (property.ImplementationTypes.Count > 0) {
848 OutputImplementationTypes (property.ImplementationTypes, property.Name);
849 } else if (property.PrivateImplementationType != null) {
850 output.Write (" Implements ");
851 OutputType (property.PrivateImplementationType);
853 output.Write (property.Name);
858 if (!IsCurrentInterface) {
860 if (property.HasGet) {
861 output.WriteLine ("Get");
862 if (!IsAbstract (property.Attributes)) {
864 GenerateStatements (property.GetStatements);
866 output.WriteLine ("End Get");
870 if (property.HasSet) {
871 output.WriteLine ("Set");
872 if (!IsAbstract (property.Attributes)) {
874 GenerateStatements (property.SetStatements);
876 output.WriteLine ("End Set");
881 output.WriteLine ("End Property");
885 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
887 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
890 OutputAttributes (constructor.CustomAttributes, null,
891 LineHandling.ContinueLine);
892 OutputMemberAccessModifier (constructor.Attributes);
893 Output.Write ("Sub New(");
894 OutputParameters (constructor.Parameters);
895 Output.WriteLine (")");
897 // check if ctor passes args on to other ctor in class
898 CodeExpressionCollection ctorArgs = constructor.ChainedConstructorArgs;
899 if (ctorArgs.Count > 0) {
900 Output.Write ("Me.New(");
901 OutputExpressionList (ctorArgs);
902 Output.WriteLine (")");
904 // check if ctor passes args on to ctor in base class
905 ctorArgs = constructor.BaseConstructorArgs;
906 if (ctorArgs.Count > 0) {
907 Output.Write ("MyBase.New(");
908 OutputExpressionList (ctorArgs);
909 Output.WriteLine (")");
910 } else if (IsCurrentClass) {
911 // call default base ctor
912 Output.WriteLine ("MyBase.New");
915 GenerateStatements (constructor.Statements);
917 Output.WriteLine ("End Sub");
920 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
922 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
925 OutputAttributes (constructor.CustomAttributes, null,
926 LineHandling.ContinueLine);
928 Output.WriteLine ("Shared Sub New()");
930 GenerateStatements (constructor.Statements);
932 Output.WriteLine ("End Sub");
935 [MonoTODO ("partially implemented")]
936 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
938 TextWriter output = Output;
940 OutputAttributes (declaration.CustomAttributes, null,
941 LineHandling.ContinueLine);
943 TypeAttributes attributes = declaration.TypeAttributes;
945 if (IsCurrentDelegate) {
946 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
948 if ((attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
949 output.Write ("Public ");
952 bool isSub = delegateDecl.ReturnType.BaseType == typeof (void).FullName;
954 output.Write ("Delegate Sub ");
956 output.Write ("Delegate Function ");
959 output.Write (CreateEscapedIdentifier (delegateDecl.Name));
960 OutputTypeParameters (delegateDecl.TypeParameters);
962 OutputParameters (delegateDecl.Parameters);
965 Output.Write (" As ");
966 OutputType (delegateDecl.ReturnType);
968 Output.WriteLine ("");
970 OutputTypeAttributes (declaration);
971 output.Write (CreateEscapedIdentifier (declaration.Name));
972 OutputTypeParameters (declaration.TypeParameters);
975 if (declaration.BaseTypes.Count > 0) {
976 output.Write (" As ");
977 OutputType (declaration.BaseTypes[0]);
984 bool firstInherits = true;
985 bool firstImplements = true;
987 for (int i = 0; i < declaration.BaseTypes.Count; i++) {
988 // a struct can only implement interfaces
989 // an interface can only inherit from other interface
991 CodeTypeReference typeRef = declaration.BaseTypes[i];
993 if (firstInherits && !declaration.IsStruct && !typeRef.IsInterface) {
995 output.Write ("Inherits ");
996 firstInherits = false;
997 } else if (!declaration.IsInterface && firstImplements) {
999 output.Write ("Implements ");
1000 firstImplements = false;
1002 output.Write (", ");
1004 OutputType (typeRef);
1006 output.WriteLine ();
1011 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
1013 if (IsCurrentDelegate) {
1016 string output = string.Empty;
1019 if (declaration.IsStruct)
1020 output = "End Structure";
1021 if (declaration.IsInterface)
1022 output = "End Interface";
1023 if (declaration.IsEnum)
1024 output = "End Enum";
1025 if (declaration.IsClass)
1026 output = "End Class";
1028 Output.WriteLine (output);
1031 protected override void GenerateNamespace(CodeNamespace ns)
1033 GenerateNamespaceImports (ns);
1034 Output.WriteLine ();
1035 GenerateCommentStatements (ns.Comments);
1036 GenerateNamespaceStart (ns);
1038 GenerateNamespaceEnd (ns);
1042 protected override void GenerateNamespaceStart (CodeNamespace ns)
1044 TextWriter output = Output;
1046 string name = ns.Name;
1047 if (name != null && name != string.Empty) {
1048 output.Write ("Namespace ");
1049 output.WriteLine (name);
1054 protected override void GenerateNamespaceEnd (CodeNamespace ns)
1056 string name = ns.Name;
1057 if (name != null && name != string.Empty) {
1059 Output.WriteLine ("End Namespace");
1063 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
1065 TextWriter output = Output;
1067 output.Write ("Imports ");
1068 output.Write (import.Namespace);
1069 output.WriteLine ();
1072 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
1077 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
1082 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, LineHandling lineHandling) {
1083 if (attributes.Count == 0) {
1087 GenerateAttributeDeclarationsStart (attributes);
1089 IEnumerator enumerator = attributes.GetEnumerator ();
1090 if (enumerator.MoveNext ()) {
1091 CodeAttributeDeclaration att = (CodeAttributeDeclaration) enumerator.Current;
1092 if (prefix != null) {
1093 Output.Write (prefix);
1095 OutputAttributeDeclaration (att);
1097 while (enumerator.MoveNext ()) {
1098 Output.Write (", ");
1099 if (lineHandling != LineHandling.InLine) {
1100 ContinueOnNewLine ("");
1103 att = (CodeAttributeDeclaration) enumerator.Current;
1104 if (prefix != null) {
1105 Output.Write (prefix);
1107 OutputAttributeDeclaration (att);
1110 GenerateAttributeDeclarationsEnd (attributes);
1113 switch (lineHandling) {
1114 case LineHandling.ContinueLine:
1115 ContinueOnNewLine ("");
1117 case LineHandling.NewLine:
1118 Output.WriteLine ();
1123 protected override void OutputAttributeArgument (CodeAttributeArgument argument)
1125 string name = argument.Name;
1126 if (name != null && name.Length > 0) {
1127 Output.Write (name);
1128 Output.Write (":=");
1130 GenerateExpression (argument.Value);
1133 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
1135 Output.Write (attribute.Name.Replace ('+', '.'));
1137 IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
1138 if (enumerator.MoveNext ()) {
1139 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
1140 OutputAttributeArgument (argument);
1142 while (enumerator.MoveNext ()) {
1143 Output.Write (", ");
1144 argument = (CodeAttributeArgument) enumerator.Current;
1145 OutputAttributeArgument (argument);
1151 protected override void OutputDirection (FieldDirection direction)
1153 switch (direction) {
1154 case FieldDirection.In:
1155 Output.Write ("ByVal ");
1157 case FieldDirection.Out:
1158 case FieldDirection.Ref:
1159 Output.Write ("ByRef ");
1164 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1166 switch (attributes & MemberAttributes.ScopeMask) {
1167 case MemberAttributes.Static:
1168 Output.Write ("Shared ");
1170 case MemberAttributes.Const:
1171 Output.Write ("Const ");
1176 private void OutputImplementationTypes (CodeTypeReferenceCollection implementationTypes, string member)
1178 IEnumerator enumerator = implementationTypes.GetEnumerator ();
1179 if (enumerator.MoveNext ()) {
1180 Output.Write (" Implements ");
1182 CodeTypeReference typeReference = (CodeTypeReference) enumerator.Current;
1183 OutputType (typeReference);
1185 OutputIdentifier (member);
1187 while (enumerator.MoveNext ()) {
1188 Output.Write (" , ");
1189 typeReference = (CodeTypeReference) enumerator.Current;
1190 OutputType (typeReference);
1192 OutputIdentifier (member);
1197 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1199 switch (attributes & MemberAttributes.AccessMask) {
1200 case MemberAttributes.Assembly:
1201 case MemberAttributes.FamilyAndAssembly:
1202 Output.Write ("Friend ");
1204 case MemberAttributes.Family:
1205 Output.Write ("Protected ");
1207 case MemberAttributes.FamilyOrAssembly:
1208 Output.Write ("Protected Friend ");
1210 case MemberAttributes.Private:
1211 Output.Write ("Private ");
1213 case MemberAttributes.Public:
1214 Output.Write ("Public ");
1219 private void OutputVTableModifier (MemberAttributes attributes)
1221 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
1222 Output.Write ("Shadows ");
1225 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1227 switch (attributes & MemberAttributes.ScopeMask) {
1228 case MemberAttributes.Abstract:
1229 Output.Write ("MustOverride ");
1231 case MemberAttributes.Final:
1234 case MemberAttributes.Static:
1235 Output.Write ("Shared ");
1237 case MemberAttributes.Override:
1238 Output.Write ("Overrides ");
1240 case MemberAttributes.Overloaded:
1241 // based on http://gendotnet.com/Code%20Gen%20Articles/codedom.htm
1242 Output.Write ("Overloads ");
1244 MemberAttributes access_ovl = attributes & MemberAttributes.AccessMask;
1245 if (access_ovl == MemberAttributes.Public || access_ovl == MemberAttributes.Family)
1246 Output.Write ("Overridable ");
1250 // FUNNY! if the scope value is
1251 // rubbish (0 or >Const), and access
1252 // is public, protected make it
1255 // i'm not sure whether this is 100%
1256 // correct, but it seems to be MS
1259 // On MS.NET 2.0, internal properties
1260 // are also marked "virtual".
1262 MemberAttributes access = attributes & MemberAttributes.AccessMask;
1263 if (access == MemberAttributes.Public ||
1264 access == MemberAttributes.Family || access == MemberAttributes.Assembly)
1265 Output.Write ("Overridable ");
1270 protected override void OutputOperator (CodeBinaryOperatorType op)
1273 case CodeBinaryOperatorType.Add:
1276 case CodeBinaryOperatorType.Subtract:
1279 case CodeBinaryOperatorType.Multiply:
1282 case CodeBinaryOperatorType.Divide:
1285 case CodeBinaryOperatorType.Modulus:
1286 Output.Write ("Mod");
1288 case CodeBinaryOperatorType.Assign:
1291 case CodeBinaryOperatorType.IdentityInequality:
1292 Output.Write ("<>");
1294 case CodeBinaryOperatorType.IdentityEquality:
1295 Output.Write ("Is");
1297 case CodeBinaryOperatorType.ValueEquality:
1300 case CodeBinaryOperatorType.BitwiseOr:
1301 Output.Write ("Or");
1303 case CodeBinaryOperatorType.BitwiseAnd:
1304 Output.Write ("And");
1306 case CodeBinaryOperatorType.BooleanOr:
1307 Output.Write ("OrElse");
1309 case CodeBinaryOperatorType.BooleanAnd:
1310 Output.Write ("AndAlso");
1312 case CodeBinaryOperatorType.LessThan:
1315 case CodeBinaryOperatorType.LessThanOrEqual:
1316 Output.Write ("<=");
1318 case CodeBinaryOperatorType.GreaterThan:
1321 case CodeBinaryOperatorType.GreaterThanOrEqual:
1322 Output.Write (">=");
1327 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1329 TextWriter output = Output;
1330 TypeAttributes attributes = declaration.TypeAttributes;
1332 if (declaration.IsPartial)
1333 output.Write ("Partial ");
1335 switch (attributes & TypeAttributes.VisibilityMask) {
1336 case TypeAttributes.Public:
1337 case TypeAttributes.NestedPublic:
1338 output.Write ("Public ");
1340 case TypeAttributes.NestedPrivate:
1341 output.Write ("Private ");
1343 case TypeAttributes.NotPublic:
1344 case TypeAttributes.NestedFamANDAssem:
1345 case TypeAttributes.NestedAssembly:
1346 output.Write ("Friend ");
1348 case TypeAttributes.NestedFamily:
1349 output.Write ("Protected ");
1351 case TypeAttributes.NestedFamORAssem:
1352 output.Write ("Protected Friend ");
1356 if (declaration.IsStruct) {
1357 output.Write ("Structure ");
1358 } else if (declaration.IsEnum) {
1359 output.Write ("Enum ");
1361 if ((attributes & TypeAttributes.Interface) != 0) {
1362 output.Write ("Interface ");
1364 if ((attributes & TypeAttributes.Sealed) != 0)
1365 output.Write ("NotInheritable ");
1367 if ((attributes & TypeAttributes.Abstract) != 0)
1368 output.Write ("MustInherit ");
1370 output.Write ("Class ");
1375 void OutputTypeParameters (CodeTypeParameterCollection parameters)
1377 int count = parameters.Count;
1381 Output.Write ("(Of ");
1382 for (int i = 0; i < count; ++i) {
1384 Output.Write (", ");
1385 CodeTypeParameter p = parameters [i];
1386 Output.Write (p.Name);
1387 OutputTypeParameterConstraints (p);
1392 void OutputTypeParameterConstraints (CodeTypeParameter parameter)
1394 int constraint_count = parameter.Constraints.Count +
1395 (parameter.HasConstructorConstraint ? 1 : 0);
1397 if (constraint_count == 0)
1400 Output.Write (" As ");
1402 if (constraint_count > 1)
1403 Output.Write (" {");
1405 for (int i = 0; i < parameter.Constraints.Count; i++) {
1407 Output.Write (", ");
1408 OutputType (parameter.Constraints [i]);
1411 if (parameter.HasConstructorConstraint) {
1412 if (constraint_count > 1)
1413 Output.Write (", ");
1414 Output.Write ("New");
1417 if (constraint_count > 1)
1421 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
1423 if (name.Length == 0)
1424 name = "__exception";
1425 Output.Write (CreateEscapedIdentifier(name) + " As " + GetTypeOutput (typeRef));
1428 protected override void OutputType (CodeTypeReference type)
1430 Output.Write (GetTypeOutput (type));
1433 protected override string QuoteSnippetString (string value)
1435 StringBuilder mySBuilder = new StringBuilder(value.Length);
1436 mySBuilder.Append ("\"");
1437 bool inQuotes = true;
1438 for (int MyCounter = 0; MyCounter < value.Length; MyCounter++) {
1439 if (value[MyCounter] == 34) //quotation mark
1442 mySBuilder.Append ("&\"");
1445 mySBuilder.Append (value[MyCounter]);
1446 mySBuilder.Append (value[MyCounter]);
1448 else if (value[MyCounter] >= 32) //standard ansi/unicode characters
1451 mySBuilder.Append ("&\"");
1454 mySBuilder.Append (value[MyCounter]);
1456 else //special chars, e.g. line break
1459 mySBuilder.Append ("\"");
1462 mySBuilder.Append ("&Microsoft.VisualBasic.ChrW(");
1463 mySBuilder.Append ((int)value[MyCounter]);
1464 mySBuilder.Append (")");
1468 mySBuilder.Append ("\"");
1469 return mySBuilder.ToString();
1472 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1474 GenerateExpression (targetObject);
1476 Output.Write (memberName);
1483 protected override string CreateEscapedIdentifier (string value)
1485 for (int x = 0; x < Keywords.Length; x++)
1486 if (value.ToLower().Equals (Keywords[x].ToLower()))
1487 return "[" + value + "]";
1491 protected override string CreateValidIdentifier (string value)
1493 for (int x = 0; x < Keywords.Length; x++)
1494 if (value.ToLower().Equals (Keywords[x].ToLower()))
1499 protected override string GetTypeOutput (CodeTypeReference type)
1502 CodeTypeReference arrayType;
1504 arrayType = type.ArrayElementType;
1505 if (arrayType != null)
1506 output = GetTypeOutput (arrayType);
1508 switch (type.BaseType) {
1509 case "System.DateTime":
1512 case "System.Decimal":
1515 case "System.Double":
1518 case "System.Single":
1524 case "System.Int32":
1527 case "System.Int64":
1530 case "System.Int16":
1533 case "System.Boolean":
1539 case "System.String":
1542 case "System.Object":
1545 case "System.SByte":
1548 case "System.UInt16":
1551 case "System.UInt32":
1552 output = "UInteger";
1554 case "System.UInt64":
1558 output = type.BaseType.Replace('+', '.');
1559 output = CreateEscapedIdentifier (output);
1564 int rank = type.ArrayRank;
1567 for (--rank; rank > 0; --rank)
1575 protected override bool IsValidIdentifier (string identifier)
1577 for (int x = 0; x < Keywords.Length; x++)
1578 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1583 protected override bool Supports (GeneratorSupport supports)
1588 private bool IsOverloaded (CodeMemberProperty property, CodeTypeDeclaration type)
1590 if ((property.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1594 foreach (CodeTypeMember member in type.Members) {
1595 CodeMemberProperty p = member as CodeMemberProperty;
1597 // member is not a property
1601 if (p != property && p.Name == property.Name && p.PrivateImplementationType == null)
1607 private bool IsOverloaded (CodeMemberMethod method, CodeTypeDeclaration type)
1609 if ((method.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1613 foreach (CodeTypeMember member in type.Members) {
1614 CodeMemberMethod m = member as CodeMemberMethod;
1616 // member is not a method
1620 if (!(m is CodeTypeConstructor) && !(m is CodeConstructor) && m != method && m.Name == method.Name && m.PrivateImplementationType == null)
1626 private string GetEventName (CodeMemberEvent evt)
1628 if (evt.PrivateImplementationType == null)
1631 string baseType = evt.PrivateImplementationType.BaseType.Replace ('.', '_');
1632 return baseType + "_" + evt.Name;
1635 private string GetMethodName (CodeMemberMethod method)
1637 if (method.PrivateImplementationType == null)
1640 string baseType = method.PrivateImplementationType.BaseType.Replace ('.', '_');
1641 return baseType + "_" + method.Name;
1644 private string GetPropertyName (CodeMemberProperty property)
1646 if (property.PrivateImplementationType == null)
1647 return property.Name;
1649 string baseType = property.PrivateImplementationType.BaseType.Replace ('.', '_');
1650 return baseType + "_" + property.Name;
1653 static bool IsAbstract (MemberAttributes attributes)
1655 return (attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract;
1658 private enum LineHandling