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",
97 private CodeAttributeDeclarationCollection assemblyCustomAttributes;
99 public VBCodeGenerator()
103 protected override string NullToken {
109 protected override void ContinueOnNewLine (string st)
112 Output.WriteLine (" _");
115 protected override void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
117 // We need to special case for comparisons against null;
118 // in Visual Basic the "Not (Expr) Is Nothing" construct is used
120 bool null_comparison = false;
121 bool reverse = false;
122 if (e.Operator == CodeBinaryOperatorType.IdentityInequality) {
123 CodePrimitiveExpression nothing;
124 nothing = e.Left as CodePrimitiveExpression;
125 if (nothing == null) {
126 nothing = e.Right as CodePrimitiveExpression;
130 null_comparison = nothing != null && nothing.Value == null;
133 if (null_comparison) {
134 TextWriter output = Output;
136 output.Write ("(Not (");
137 GenerateExpression (reverse ? e.Right : e.Left);
138 output.Write (") Is ");
139 GenerateExpression (reverse ? e.Left : e.Right);
142 base.GenerateBinaryOperatorExpression (e);
146 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
148 TextWriter output = Output;
150 output.Write ("New ");
152 CodeExpressionCollection initializers = expression.Initializers;
153 CodeTypeReference createType = expression.CreateType;
155 if (initializers.Count > 0) {
157 OutputType (createType);
159 output.Write ("() {");
161 OutputExpressionList (initializers);
165 CodeTypeReference arrayType = createType.ArrayElementType;
166 while (arrayType != null) {
167 createType = arrayType;
168 arrayType = arrayType.ArrayElementType;
171 OutputType (createType);
175 CodeExpression size = expression.SizeExpression;
177 GenerateExpression (size);
179 output.Write (expression.Size);
181 output.Write (") - 1) {}");
185 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
187 Output.Write ("MyBase");
190 protected override void GenerateCastExpression (CodeCastExpression expression)
192 TextWriter output = Output;
193 // ENHANCE: Use a DirectCast if it is known that expression.Expression is no Value-Type
194 output.Write ("CType(");
195 GenerateExpression (expression.Expression);
197 OutputType (expression.TargetType);
201 private bool AsBool (object datavalue)
203 return datavalue != null && datavalue is bool && (bool) datavalue;
206 private string OnOff (bool datavalue)
208 return datavalue ? "On" : "Off";
211 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
213 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
214 GenerateComment (new CodeComment (" <autogenerated>"));
215 GenerateComment (new CodeComment (" This code was generated by a tool."));
216 GenerateComment (new CodeComment (" Mono Runtime Version: " + System.Environment.Version));
217 GenerateComment (new CodeComment (""));
218 GenerateComment (new CodeComment (" Changes to this file may cause incorrect behavior and will be lost if "));
219 GenerateComment (new CodeComment (" the code is regenerated."));
220 GenerateComment (new CodeComment (" </autogenerated>"));
221 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
223 if (AsBool (compileUnit.UserData ["AllowLateBound"])) {
224 Output.WriteLine("Option Explicit {0}", OnOff (AsBool (compileUnit.UserData ["RequireVariableDeclaration"])));
225 Output.WriteLine("Option Strict Off");
227 Output.WriteLine("Option Explicit On"); // Strict On implies Explicit On
228 Output.WriteLine("Option Strict On");
233 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
235 assemblyCustomAttributes = compileUnit.AssemblyCustomAttributes;
237 GenerateCompileUnitStart (compileUnit);
239 GenerateNamespaces (compileUnit);
241 // In the case there are no namespaces, and hence no Import statements, now
242 // is the time to emit assembly level attributes.
243 if (assemblyCustomAttributes != null)
244 GenerateAssemblyAttributes ();
246 GenerateCompileUnitEnd (compileUnit);
249 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
251 TextWriter output = Output;
253 output.Write ("AddressOf ");
255 CodeExpression targetObject = expression.TargetObject;
256 if (targetObject != null) {
257 GenerateExpression (targetObject);
260 output.Write (expression.MethodName);
263 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
265 CodeExpression targetObject = expression.TargetObject;
266 if (targetObject != null) {
267 GenerateExpression (targetObject);
270 Output.Write (CreateEscapedIdentifier (expression.FieldName));
273 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
275 Output.Write (CreateEscapedIdentifier (expression.ParameterName));
278 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
280 Output.Write (CreateEscapedIdentifier (expression.VariableName));
283 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
285 TextWriter output = Output;
287 GenerateExpression (expression.TargetObject);
289 OutputExpressionList (expression.Indices);
293 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
295 TextWriter output = Output;
297 GenerateExpression (expression.TargetObject);
299 OutputExpressionList (expression.Indices);
303 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
305 Output.Write (expression.Value);
308 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
310 TextWriter output = Output;
312 GenerateMethodReferenceExpression (expression.Method);
315 OutputExpressionList (expression.Parameters);
319 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
321 if (expression.TargetObject != null) {
322 GenerateExpression (expression.TargetObject);
325 Output.Write (CreateEscapedIdentifier (expression.MethodName));
328 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
330 if (expression.TargetObject != null) {
331 GenerateExpression (expression.TargetObject);
333 if (expression.TargetObject is CodeThisReferenceExpression) {
334 // We're actually creating a reference to a compiler-generated field here...
335 Output.Write (expression.EventName + "Event");
337 Output.Write (CreateEscapedIdentifier (expression.EventName));
340 Output.Write (CreateEscapedIdentifier (expression.EventName + "Event"));
344 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
346 CodeEventReferenceExpression ev = expression.TargetObject as CodeEventReferenceExpression;
349 Output.Write ("RaiseEvent ");
350 if (ev.TargetObject != null && !(ev.TargetObject is CodeThisReferenceExpression)) {
351 GenerateExpression (ev.TargetObject);
354 Output.Write (ev.EventName);
355 } else if (expression.TargetObject != null) {
356 GenerateExpression (expression.TargetObject);
359 OutputExpressionList (expression.Parameters);
363 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
365 Output.Write( "New " );
366 OutputType (expression.CreateType);
368 OutputExpressionList (expression.Parameters);
372 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
374 OutputAttributes (e.CustomAttributes, null, LineHandling.InLine);
375 OutputDirection (e.Direction);
376 OutputTypeNamePair (e.Type, e.Name);
379 protected override void GeneratePrimitiveExpression (CodePrimitiveExpression e)
381 if (e.Value is char) {
382 char c = (char) e.Value;
384 Output.Write("Global.Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
385 } else if (e.Value is ushort) {
386 ushort uc = (ushort) e.Value;
387 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
389 } else if (e.Value is uint) {
390 uint ui = (uint) e.Value;
391 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
393 } else if (e.Value is ulong) {
394 ulong ul = (ulong) e.Value;
395 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
397 } else if (e.Value is sbyte) {
398 sbyte sb = (sbyte) e.Value;
399 Output.Write ("CSByte(");
400 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
403 base.GeneratePrimitiveExpression(e);
407 protected override void GenerateSingleFloatValue (float s)
409 base.GenerateSingleFloatValue (s);
410 base.Output.Write ('!');
413 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
415 if (expression.TargetObject != null) {
416 GenerateMemberReferenceExpression (expression.TargetObject, expression.PropertyName);
418 Output.Write (CreateEscapedIdentifier (expression.PropertyName));
422 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
424 Output.Write ("Value");
427 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
432 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
434 GenerateExpression (statement.Expression);
435 Output.WriteLine (); //start new line
438 protected override void GenerateIterationStatement (CodeIterationStatement statement)
440 TextWriter output = Output;
442 GenerateStatement (statement.InitStatement);
443 output.Write ("Do While ");
444 GenerateExpression (statement.TestExpression);
447 GenerateStatements (statement.Statements);
448 GenerateStatement (statement.IncrementStatement);
450 output.WriteLine ("Loop");
453 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
455 Output.Write ("Throw");
456 if (statement.ToThrow != null) {
458 GenerateExpression (statement.ToThrow);
463 protected override void GenerateComment (CodeComment comment)
465 TextWriter output = Output;
466 string commentChars = null;
468 if (comment.DocComment) {
469 commentChars = "'''";
474 output.Write (commentChars);
475 string text = comment.Text;
477 for (int i = 0; i < text.Length; i++) {
478 output.Write (text [i]);
479 if (text[i] == '\r') {
480 if (i < (text.Length - 1) && text [i + 1] == '\n') {
483 output.Write (commentChars);
484 } else if (text [i] == '\n') {
485 output.Write (commentChars);
492 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
494 TextWriter output = Output;
496 if (statement.Expression != null) {
497 output.Write ("Return ");
498 GenerateExpression (statement.Expression);
501 output.WriteLine ("Return");
505 protected override void GenerateConditionStatement (CodeConditionStatement statement)
507 TextWriter output = Output;
508 output.Write ("If ");
510 GenerateExpression (statement.Condition);
512 output.WriteLine (" Then");
514 GenerateStatements (statement.TrueStatements);
517 CodeStatementCollection falses = statement.FalseStatements;
518 if (falses.Count > 0) {
519 output.WriteLine ("Else");
521 GenerateStatements (falses);
525 if (Options.ElseOnClosing)
526 output.WriteLine ("Else");
528 output.WriteLine ("End If");
531 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
533 TextWriter output = Output;
535 output.WriteLine ("Try ");
537 GenerateStatements (statement.TryStatements);
540 foreach (CodeCatchClause clause in statement.CatchClauses) {
541 output.Write ("Catch ");
542 OutputTypeNamePair (clause.CatchExceptionType, clause.LocalName);
545 GenerateStatements (clause.Statements);
549 CodeStatementCollection finallies = statement.FinallyStatements;
550 if (finallies.Count > 0) {
551 output.WriteLine ("Finally");
553 GenerateStatements (finallies);
557 output.WriteLine("End Try");
560 protected override void GenerateAssignStatement (CodeAssignStatement statement)
562 TextWriter output = Output;
563 GenerateExpression (statement.Left);
564 output.Write (" = ");
565 GenerateExpression (statement.Right);
569 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
571 TextWriter output = Output;
573 Output.Write ("AddHandler ");
574 if (statement.Event.TargetObject != null) {
575 GenerateEventReferenceExpression (statement.Event);
577 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
579 Output.Write ( ", ");
580 GenerateExpression (statement.Listener);
584 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
586 TextWriter output = Output;
588 Output.Write ("RemoveHandler ");
589 if (statement.Event.TargetObject != null) {
590 GenerateEventReferenceExpression (statement.Event);
592 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
594 Output.Write ( ", ");
595 GenerateExpression (statement.Listener);
599 protected override void GenerateGotoStatement (CodeGotoStatement statement)
601 TextWriter output = Output;
603 output.Write ("goto ");
604 output.Write (statement.Label);
608 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
610 TextWriter output = Output;
613 output.WriteLine (statement.Label + ":");
615 if (statement.Statement != null) {
616 GenerateStatement (statement.Statement);
620 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
622 TextWriter output = Output;
624 output.Write ("GetType(");
629 protected override void GenerateVariableDeclarationStatement( CodeVariableDeclarationStatement statement )
631 TextWriter output = Output;
633 output.Write ("Dim ");
634 OutputTypeNamePair (statement.Type, statement.Name);
636 CodeExpression initExpression = statement.InitExpression;
637 if (initExpression != null) {
638 output.Write (" = ");
639 GenerateExpression (initExpression);
645 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
648 Output.Write ("#ExternalSource(\"");
649 Output.Write (linePragma.FileName);
650 Output.Write ("\",");
651 Output.Write (linePragma.LineNumber);
652 Output.WriteLine (")");
653 Output.WriteLine ("");
656 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
658 Output.WriteLine ("#End ExternalSource");
661 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
663 if (IsCurrentDelegate || IsCurrentEnum)
666 TextWriter output = Output;
668 OutputAttributes (eventRef.CustomAttributes, null,
669 LineHandling.ContinueLine);
671 OutputMemberAccessModifier (eventRef.Attributes);
673 output.Write ("Event ");
674 OutputTypeNamePair (eventRef.Type, GetEventName(eventRef));
676 if (eventRef.ImplementationTypes.Count > 0) {
677 OutputImplementationTypes (eventRef.ImplementationTypes, eventRef.Name);
678 } else if (eventRef.PrivateImplementationType != null) {
679 output.Write (" Implements ");
680 OutputType (eventRef.PrivateImplementationType);
682 output.Write (eventRef.Name);
688 protected override void GenerateField (CodeMemberField field)
690 if (IsCurrentDelegate || IsCurrentInterface)
693 TextWriter output = Output;
695 OutputAttributes (field.CustomAttributes, null,
696 LineHandling.ContinueLine);
699 output.Write (field.Name);
701 MemberAttributes attributes = field.Attributes;
702 OutputMemberAccessModifier (attributes);
703 OutputVTableModifier (attributes);
704 OutputFieldScopeModifier (attributes);
705 OutputTypeNamePair (field.Type, field.Name);
708 CodeExpression initExpression = field.InitExpression;
709 if (initExpression != null) {
710 output.Write (" = ");
711 GenerateExpression (initExpression);
717 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
719 Output.Write (member.Text);
722 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, CodeTypeDeclaration declaration)
724 OutputAttributes (method.CustomAttributes, null,
725 LineHandling.ContinueLine);
727 Output.WriteLine ("Public Shared Sub Main()");
729 GenerateStatements (method.Statements);
731 Output.WriteLine ("End Sub");
734 [MonoTODO ("partially implemented")]
735 protected override void GenerateMethod (CodeMemberMethod method, CodeTypeDeclaration declaration)
737 if (IsCurrentDelegate || IsCurrentEnum)
740 bool isSub = method.ReturnType.BaseType == typeof(void).FullName;
742 TextWriter output = Output;
744 OutputAttributes (method.CustomAttributes, null,
745 LineHandling.ContinueLine);
747 MemberAttributes attributes = method.Attributes;
749 if (!IsCurrentInterface) {
750 if (method.PrivateImplementationType == null) {
751 OutputMemberAccessModifier (attributes);
752 if (IsOverloaded (method, declaration)) {
753 output.Write ("Overloads ");
756 OutputVTableModifier (attributes);
757 OutputMemberScopeModifier (attributes);
759 OutputVTableModifier (attributes);
763 output.Write ("Sub ");
765 output.Write ("Function ");
767 output.Write (GetMethodName(method));
768 OutputTypeParameters (method.TypeParameters);
770 OutputParameters (method.Parameters);
774 output.Write (" As ");
775 OutputAttributes (method.ReturnTypeCustomAttributes, null,
776 LineHandling.InLine);
777 OutputType (method.ReturnType);
780 if (method.ImplementationTypes.Count > 0) {
781 OutputImplementationTypes (method.ImplementationTypes, method.Name);
782 } else if (method.PrivateImplementationType != null) {
783 output.Write (" Implements ");
784 OutputType (method.PrivateImplementationType);
786 output.Write (method.Name);
790 if (!IsCurrentInterface) {
791 if ((attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
793 GenerateStatements (method.Statements);
796 output.WriteLine ("End Sub");
798 output.WriteLine ("End Function");
803 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
805 if (IsCurrentDelegate || IsCurrentEnum)
808 TextWriter output = Output;
810 OutputAttributes (property.CustomAttributes, null,
811 LineHandling.ContinueLine);
813 MemberAttributes attributes = property.Attributes;
815 if (!IsCurrentInterface) {
816 if (property.PrivateImplementationType == null) {
817 OutputMemberAccessModifier (attributes);
818 if (IsOverloaded (property, declaration)) {
819 output.Write ("Overloads ");
822 OutputVTableModifier (attributes);
823 OutputMemberScopeModifier (attributes);
825 OutputVTableModifier (attributes);
828 // mark property as default property if we're dealing with an indexer
829 if (string.Compare (GetPropertyName(property), "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
830 output.Write ("Default ");
833 if (property.HasGet && (!property.HasSet))
834 output.Write ("ReadOnly " );
836 if (property.HasSet && (!property.HasGet))
837 output.Write ("WriteOnly " );
839 output.Write ("Property ");
840 Output.Write (GetPropertyName (property));
841 // in .NET 2.0, always output parantheses (whether or not there
842 // are any parameters to output
844 OutputParameters (property.Parameters);
846 Output.Write (" As ");
847 Output.Write (GetTypeOutput(property.Type));
849 if (property.ImplementationTypes.Count > 0) {
850 OutputImplementationTypes (property.ImplementationTypes, property.Name);
851 } else if (property.PrivateImplementationType != null) {
852 output.Write (" Implements ");
853 OutputType (property.PrivateImplementationType);
855 output.Write (property.Name);
860 if (!IsCurrentInterface) {
862 if (property.HasGet) {
863 output.WriteLine ("Get");
864 if (!IsAbstract (property.Attributes)) {
866 GenerateStatements (property.GetStatements);
868 output.WriteLine ("End Get");
872 if (property.HasSet) {
873 output.WriteLine ("Set");
874 if (!IsAbstract (property.Attributes)) {
876 GenerateStatements (property.SetStatements);
878 output.WriteLine ("End Set");
883 output.WriteLine ("End Property");
887 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
889 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
892 OutputAttributes (constructor.CustomAttributes, null,
893 LineHandling.ContinueLine);
894 OutputMemberAccessModifier (constructor.Attributes);
895 Output.Write ("Sub New(");
896 OutputParameters (constructor.Parameters);
897 Output.WriteLine (")");
899 // check if ctor passes args on to other ctor in class
900 CodeExpressionCollection ctorArgs = constructor.ChainedConstructorArgs;
901 if (ctorArgs.Count > 0) {
902 Output.Write ("Me.New(");
903 OutputExpressionList (ctorArgs);
904 Output.WriteLine (")");
906 // check if ctor passes args on to ctor in base class
907 ctorArgs = constructor.BaseConstructorArgs;
908 if (ctorArgs.Count > 0) {
909 Output.Write ("MyBase.New(");
910 OutputExpressionList (ctorArgs);
911 Output.WriteLine (")");
912 } else if (IsCurrentClass) {
913 // call default base ctor
914 Output.WriteLine ("MyBase.New");
917 GenerateStatements (constructor.Statements);
919 Output.WriteLine ("End Sub");
922 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
924 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
927 OutputAttributes (constructor.CustomAttributes, null,
928 LineHandling.ContinueLine);
930 Output.WriteLine ("Shared Sub New()");
932 GenerateStatements (constructor.Statements);
934 Output.WriteLine ("End Sub");
937 [MonoTODO ("partially implemented")]
938 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
940 TextWriter output = Output;
942 OutputAttributes (declaration.CustomAttributes, null,
943 LineHandling.ContinueLine);
945 TypeAttributes attributes = declaration.TypeAttributes;
947 if (IsCurrentDelegate) {
948 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
950 if ((attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
951 output.Write ("Public ");
954 bool isSub = delegateDecl.ReturnType.BaseType == typeof (void).FullName;
956 output.Write ("Delegate Sub ");
958 output.Write ("Delegate Function ");
961 output.Write (CreateEscapedIdentifier (delegateDecl.Name));
962 OutputTypeParameters (delegateDecl.TypeParameters);
964 OutputParameters (delegateDecl.Parameters);
967 Output.Write (" As ");
968 OutputType (delegateDecl.ReturnType);
970 Output.WriteLine ("");
972 OutputTypeAttributes (declaration);
973 output.Write (CreateEscapedIdentifier (declaration.Name));
974 OutputTypeParameters (declaration.TypeParameters);
977 if (declaration.BaseTypes.Count > 0) {
978 output.Write (" As ");
979 OutputType (declaration.BaseTypes[0]);
986 bool firstInherits = true;
987 bool firstImplements = true;
989 for (int i = 0; i < declaration.BaseTypes.Count; i++) {
990 // a struct can only implement interfaces
991 // an interface can only inherit from other interface
993 CodeTypeReference typeRef = declaration.BaseTypes[i];
995 if (firstInherits && !declaration.IsStruct && !typeRef.IsInterface) {
997 output.Write ("Inherits ");
998 firstInherits = false;
999 } else if (!declaration.IsInterface && firstImplements) {
1000 output.WriteLine ();
1001 output.Write ("Implements ");
1002 firstImplements = false;
1004 output.Write (", ");
1006 OutputType (typeRef);
1008 output.WriteLine ();
1013 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
1015 if (IsCurrentDelegate) {
1018 string output = string.Empty;
1021 if (declaration.IsStruct)
1022 output = "End Structure";
1023 if (declaration.IsInterface)
1024 output = "End Interface";
1025 if (declaration.IsEnum)
1026 output = "End Enum";
1027 if (declaration.IsClass)
1028 output = "End Class";
1030 Output.WriteLine (output);
1033 protected override void GenerateNamespace(CodeNamespace ns)
1035 GenerateNamespaceImports (ns);
1037 // Assembly level attributes can't be emitted before the Import statements
1039 if (assemblyCustomAttributes != null)
1040 GenerateAssemblyAttributes ();
1042 Output.WriteLine ();
1044 GenerateCommentStatements (ns.Comments);
1045 GenerateNamespaceStart (ns);
1047 GenerateNamespaceEnd (ns);
1051 protected override void GenerateNamespaceStart (CodeNamespace ns)
1053 TextWriter output = Output;
1055 string name = ns.Name;
1056 if (name != null && name != string.Empty) {
1057 output.Write ("Namespace ");
1058 output.WriteLine (name);
1063 protected override void GenerateNamespaceEnd (CodeNamespace ns)
1065 string name = ns.Name;
1066 if (name != null && name != string.Empty) {
1068 Output.WriteLine ("End Namespace");
1072 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
1074 TextWriter output = Output;
1076 output.Write ("Imports ");
1077 output.Write (import.Namespace);
1078 output.WriteLine ();
1081 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
1086 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
1091 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, LineHandling lineHandling) {
1092 if (attributes.Count == 0) {
1096 GenerateAttributeDeclarationsStart (attributes);
1098 IEnumerator enumerator = attributes.GetEnumerator ();
1099 if (enumerator.MoveNext ()) {
1100 CodeAttributeDeclaration att = (CodeAttributeDeclaration) enumerator.Current;
1101 if (prefix != null) {
1102 Output.Write (prefix);
1104 OutputAttributeDeclaration (att);
1106 while (enumerator.MoveNext ()) {
1107 Output.Write (", ");
1108 if (lineHandling != LineHandling.InLine) {
1109 ContinueOnNewLine ("");
1112 att = (CodeAttributeDeclaration) enumerator.Current;
1113 if (prefix != null) {
1114 Output.Write (prefix);
1116 OutputAttributeDeclaration (att);
1119 GenerateAttributeDeclarationsEnd (attributes);
1122 switch (lineHandling) {
1123 case LineHandling.ContinueLine:
1124 ContinueOnNewLine ("");
1126 case LineHandling.NewLine:
1127 Output.WriteLine ();
1132 protected override void OutputAttributeArgument (CodeAttributeArgument argument)
1134 string name = argument.Name;
1135 if (name != null && name.Length > 0) {
1136 Output.Write (name);
1137 Output.Write (":=");
1139 GenerateExpression (argument.Value);
1142 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
1144 Output.Write (attribute.Name.Replace ('+', '.'));
1146 IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
1147 if (enumerator.MoveNext ()) {
1148 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
1149 OutputAttributeArgument (argument);
1151 while (enumerator.MoveNext ()) {
1152 Output.Write (", ");
1153 argument = (CodeAttributeArgument) enumerator.Current;
1154 OutputAttributeArgument (argument);
1160 protected override void OutputDirection (FieldDirection direction)
1162 switch (direction) {
1163 case FieldDirection.In:
1164 Output.Write ("ByVal ");
1166 case FieldDirection.Out:
1167 case FieldDirection.Ref:
1168 Output.Write ("ByRef ");
1173 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1175 switch (attributes & MemberAttributes.ScopeMask) {
1176 case MemberAttributes.Static:
1177 Output.Write ("Shared ");
1179 case MemberAttributes.Const:
1180 Output.Write ("Const ");
1185 private void OutputImplementationTypes (CodeTypeReferenceCollection implementationTypes, string member)
1187 IEnumerator enumerator = implementationTypes.GetEnumerator ();
1188 if (enumerator.MoveNext ()) {
1189 Output.Write (" Implements ");
1191 CodeTypeReference typeReference = (CodeTypeReference) enumerator.Current;
1192 OutputType (typeReference);
1194 OutputIdentifier (member);
1196 while (enumerator.MoveNext ()) {
1197 Output.Write (" , ");
1198 typeReference = (CodeTypeReference) enumerator.Current;
1199 OutputType (typeReference);
1201 OutputIdentifier (member);
1206 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1208 switch (attributes & MemberAttributes.AccessMask) {
1209 case MemberAttributes.Assembly:
1210 case MemberAttributes.FamilyAndAssembly:
1211 Output.Write ("Friend ");
1213 case MemberAttributes.Family:
1214 Output.Write ("Protected ");
1216 case MemberAttributes.FamilyOrAssembly:
1217 Output.Write ("Protected Friend ");
1219 case MemberAttributes.Private:
1220 Output.Write ("Private ");
1222 case MemberAttributes.Public:
1223 Output.Write ("Public ");
1228 private void OutputVTableModifier (MemberAttributes attributes)
1230 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
1231 Output.Write ("Shadows ");
1234 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1236 switch (attributes & MemberAttributes.ScopeMask) {
1237 case MemberAttributes.Abstract:
1238 Output.Write ("MustOverride ");
1240 case MemberAttributes.Final:
1243 case MemberAttributes.Static:
1244 Output.Write ("Shared ");
1246 case MemberAttributes.Override:
1247 Output.Write ("Overrides ");
1249 case MemberAttributes.Overloaded:
1250 // based on http://gendotnet.com/Code%20Gen%20Articles/codedom.htm
1251 Output.Write ("Overloads ");
1253 MemberAttributes access_ovl = attributes & MemberAttributes.AccessMask;
1254 if (access_ovl == MemberAttributes.Public || access_ovl == MemberAttributes.Family)
1255 Output.Write ("Overridable ");
1259 // FUNNY! if the scope value is
1260 // rubbish (0 or >Const), and access
1261 // is public, protected make it
1264 // i'm not sure whether this is 100%
1265 // correct, but it seems to be MS
1268 // On MS.NET 2.0, internal properties
1269 // are also marked "virtual".
1271 MemberAttributes access = attributes & MemberAttributes.AccessMask;
1272 if (access == MemberAttributes.Public ||
1273 access == MemberAttributes.Family || access == MemberAttributes.Assembly)
1274 Output.Write ("Overridable ");
1279 protected override void OutputOperator (CodeBinaryOperatorType op)
1282 case CodeBinaryOperatorType.Add:
1285 case CodeBinaryOperatorType.Subtract:
1288 case CodeBinaryOperatorType.Multiply:
1291 case CodeBinaryOperatorType.Divide:
1294 case CodeBinaryOperatorType.Modulus:
1295 Output.Write ("Mod");
1297 case CodeBinaryOperatorType.Assign:
1300 case CodeBinaryOperatorType.IdentityInequality:
1301 Output.Write ("<>");
1303 case CodeBinaryOperatorType.IdentityEquality:
1304 Output.Write ("Is");
1306 case CodeBinaryOperatorType.ValueEquality:
1309 case CodeBinaryOperatorType.BitwiseOr:
1310 Output.Write ("Or");
1312 case CodeBinaryOperatorType.BitwiseAnd:
1313 Output.Write ("And");
1315 case CodeBinaryOperatorType.BooleanOr:
1316 Output.Write ("OrElse");
1318 case CodeBinaryOperatorType.BooleanAnd:
1319 Output.Write ("AndAlso");
1321 case CodeBinaryOperatorType.LessThan:
1324 case CodeBinaryOperatorType.LessThanOrEqual:
1325 Output.Write ("<=");
1327 case CodeBinaryOperatorType.GreaterThan:
1330 case CodeBinaryOperatorType.GreaterThanOrEqual:
1331 Output.Write (">=");
1336 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1338 TextWriter output = Output;
1339 TypeAttributes attributes = declaration.TypeAttributes;
1341 if (declaration.IsPartial)
1342 output.Write ("Partial ");
1344 switch (attributes & TypeAttributes.VisibilityMask) {
1345 case TypeAttributes.Public:
1346 case TypeAttributes.NestedPublic:
1347 output.Write ("Public ");
1349 case TypeAttributes.NestedPrivate:
1350 output.Write ("Private ");
1352 case TypeAttributes.NotPublic:
1353 case TypeAttributes.NestedFamANDAssem:
1354 case TypeAttributes.NestedAssembly:
1355 output.Write ("Friend ");
1357 case TypeAttributes.NestedFamily:
1358 output.Write ("Protected ");
1360 case TypeAttributes.NestedFamORAssem:
1361 output.Write ("Protected Friend ");
1365 if (declaration.IsStruct) {
1366 output.Write ("Structure ");
1367 } else if (declaration.IsEnum) {
1368 output.Write ("Enum ");
1370 if ((attributes & TypeAttributes.Interface) != 0) {
1371 output.Write ("Interface ");
1373 if ((attributes & TypeAttributes.Sealed) != 0)
1374 output.Write ("NotInheritable ");
1376 if ((attributes & TypeAttributes.Abstract) != 0)
1377 output.Write ("MustInherit ");
1379 output.Write ("Class ");
1384 void OutputTypeParameters (CodeTypeParameterCollection parameters)
1386 int count = parameters.Count;
1390 Output.Write ("(Of ");
1391 for (int i = 0; i < count; ++i) {
1393 Output.Write (", ");
1394 CodeTypeParameter p = parameters [i];
1395 Output.Write (p.Name);
1396 OutputTypeParameterConstraints (p);
1401 void OutputTypeParameterConstraints (CodeTypeParameter parameter)
1403 int constraint_count = parameter.Constraints.Count +
1404 (parameter.HasConstructorConstraint ? 1 : 0);
1406 if (constraint_count == 0)
1409 Output.Write (" As ");
1411 if (constraint_count > 1)
1412 Output.Write (" {");
1414 for (int i = 0; i < parameter.Constraints.Count; i++) {
1416 Output.Write (", ");
1417 OutputType (parameter.Constraints [i]);
1420 if (parameter.HasConstructorConstraint) {
1421 if (constraint_count > 1)
1422 Output.Write (", ");
1423 Output.Write ("New");
1426 if (constraint_count > 1)
1430 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
1432 if (name.Length == 0)
1433 name = "__exception";
1434 Output.Write (CreateEscapedIdentifier(name) + " As " + GetTypeOutput (typeRef));
1437 protected override void OutputType (CodeTypeReference type)
1439 Output.Write (GetTypeOutput (type));
1442 protected override string QuoteSnippetString (string value)
1444 StringBuilder mySBuilder = new StringBuilder(value.Length);
1445 mySBuilder.Append ("\"");
1446 bool inQuotes = true;
1447 for (int MyCounter = 0; MyCounter < value.Length; MyCounter++) {
1448 if (value[MyCounter] == 34) //quotation mark
1451 mySBuilder.Append ("&\"");
1454 mySBuilder.Append (value[MyCounter]);
1455 mySBuilder.Append (value[MyCounter]);
1457 else if (value[MyCounter] >= 32) //standard ansi/unicode characters
1460 mySBuilder.Append ("&\"");
1463 mySBuilder.Append (value[MyCounter]);
1465 else //special chars, e.g. line break
1468 mySBuilder.Append ("\"");
1471 mySBuilder.Append ("&Microsoft.VisualBasic.ChrW(");
1472 mySBuilder.Append ((int)value[MyCounter]);
1473 mySBuilder.Append (")");
1477 mySBuilder.Append ("\"");
1478 return mySBuilder.ToString();
1481 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1483 GenerateExpression (targetObject);
1485 Output.Write (memberName);
1492 protected override string CreateEscapedIdentifier (string value)
1494 for (int x = 0; x < Keywords.Length; x++)
1495 if (value.ToLower().Equals (Keywords[x].ToLower()))
1496 return "[" + value + "]";
1500 protected override string CreateValidIdentifier (string value)
1502 for (int x = 0; x < Keywords.Length; x++)
1503 if (value.ToLower().Equals (Keywords[x].ToLower()))
1508 protected override string GetTypeOutput (CodeTypeReference type)
1511 CodeTypeReference arrayType;
1513 arrayType = type.ArrayElementType;
1514 if (arrayType != null)
1515 output = GetTypeOutput (arrayType);
1517 switch (type.BaseType) {
1518 case "System.DateTime":
1521 case "System.Decimal":
1524 case "System.Double":
1527 case "System.Single":
1533 case "System.Int32":
1536 case "System.Int64":
1539 case "System.Int16":
1542 case "System.Boolean":
1548 case "System.String":
1551 case "System.Object":
1554 case "System.SByte":
1557 case "System.UInt16":
1560 case "System.UInt32":
1561 output = "UInteger";
1563 case "System.UInt64":
1567 output = type.BaseType.Replace('+', '.');
1568 output = CreateEscapedIdentifier (output);
1573 int rank = type.ArrayRank;
1576 for (--rank; rank > 0; --rank)
1584 protected override bool IsValidIdentifier (string identifier)
1586 for (int x = 0; x < Keywords.Length; x++)
1587 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1592 protected override bool Supports (GeneratorSupport supports)
1597 private bool IsOverloaded (CodeMemberProperty property, CodeTypeDeclaration type)
1599 if ((property.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1603 foreach (CodeTypeMember member in type.Members) {
1604 CodeMemberProperty p = member as CodeMemberProperty;
1606 // member is not a property
1610 if (p != property && p.Name == property.Name && p.PrivateImplementationType == null)
1616 private bool IsOverloaded (CodeMemberMethod method, CodeTypeDeclaration type)
1618 if ((method.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1622 foreach (CodeTypeMember member in type.Members) {
1623 CodeMemberMethod m = member as CodeMemberMethod;
1625 // member is not a method
1629 if (!(m is CodeTypeConstructor) && !(m is CodeConstructor) && m != method && m.Name == method.Name && m.PrivateImplementationType == null)
1635 private string GetEventName (CodeMemberEvent evt)
1637 if (evt.PrivateImplementationType == null)
1640 string baseType = evt.PrivateImplementationType.BaseType.Replace ('.', '_');
1641 return baseType + "_" + evt.Name;
1644 private string GetMethodName (CodeMemberMethod method)
1646 if (method.PrivateImplementationType == null)
1649 string baseType = method.PrivateImplementationType.BaseType.Replace ('.', '_');
1650 return baseType + "_" + method.Name;
1653 private string GetPropertyName (CodeMemberProperty property)
1655 if (property.PrivateImplementationType == null)
1656 return property.Name;
1658 string baseType = property.PrivateImplementationType.BaseType.Replace ('.', '_');
1659 return baseType + "_" + property.Name;
1662 static bool IsAbstract (MemberAttributes attributes)
1664 return (attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract;
1667 private void GenerateAssemblyAttributes ()
1669 OutputAttributes (assemblyCustomAttributes,
1670 "Assembly: ", LineHandling.NewLine);
1671 assemblyCustomAttributes = null;
1674 private enum LineHandling