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
60 private string [] Keywords = new string [] {
61 "AddHandler", "AddressOf", "Alias", "And",
62 "AndAlso", "Ansi", "As", "Assembly",
63 "Auto", "Boolean", "ByRef", "Byte",
64 "ByVal", "Call", "Case", "Catch",
65 "CBool", "CByte", "CChar", "CDate",
66 "CDec", "CDbl", "Char", "CInt",
67 "Class", "CLng", "CObj", "Const",
68 "CShort", "CSng", "CStr", "CType",
69 "Date", "Decimal", "Declare", "Default",
70 "Delegate", "Dim", "DirectCast", "Do",
71 "Double", "Each", "Else", "ElseIf",
72 "End", "Enum", "Erase", "Error",
73 "Event", "Exit", "False", "Finally",
74 "For", "Friend", "Function", "Get",
75 "GetType", "Global", "GoSub", "GoTo", "Handles",
76 "If", "Implements", "Imports", "In",
77 "Inherits", "Integer", "Interface", "Is",
78 "Let", "Lib", "Like", "Long",
79 "Loop", "Me", "Mod", "Module",
80 "MustInherit", "MustOverride", "MyBase", "MyClass",
81 "Namespace", "New", "Next", "Not",
82 "Nothing", "NotInheritable", "NotOverridable", "Object",
83 "On", "Option", "Optional", "Or",
84 "OrElse", "Overloads", "Overridable", "Overrides",
85 "ParamArray", "Partial", "Preserve", "Private", "Property",
86 "Protected", "Public", "RaiseEvent", "ReadOnly",
87 "ReDim", "REM", "RemoveHandler", "Resume",
88 "Return", "Select", "Set", "Shadows",
89 "Shared", "Short", "Single", "Static",
90 "Step", "Stop", "String", "Structure",
91 "Sub", "SyncLock", "Then", "Throw",
92 "To", "True", "Try", "TypeOf",
93 "Unicode", "Until", "Variant", "When",
94 "While", "With", "WithEvents", "WriteOnly",
98 private string [] Keywords = new string [] {
99 "AddHandler", "AddressOf", "Alias", "And",
100 "AndAlso", "Ansi", "As", "Assembly",
101 "Auto", "Boolean", "ByRef", "Byte",
102 "ByVal", "Call", "Case", "Catch",
103 "CBool", "CByte", "CChar", "CDate",
104 "CDec", "CDbl", "Char", "CInt",
105 "Class", "CLng", "CObj", "Const",
106 "CShort", "CSng", "CStr", "CType",
107 "Date", "Decimal", "Declare", "Default",
108 "Delegate", "Dim", "DirectCast", "Do",
109 "Double", "Each", "Else", "ElseIf",
110 "End", "Enum", "Erase", "Error",
111 "Event", "Exit", "False", "Finally",
112 "For", "Friend", "Function", "Get",
113 "GetType", "GoSub", "GoTo", "Handles",
114 "If", "Implements", "Imports", "In",
115 "Inherits", "Integer", "Interface", "Is",
116 "Let", "Lib", "Like", "Long",
117 "Loop", "Me", "Mod", "Module",
118 "MustInherit", "MustOverride", "MyBase", "MyClass",
119 "Namespace", "New", "Next", "Not",
120 "Nothing", "NotInheritable", "NotOverridable", "Object",
121 "On", "Option", "Optional", "Or",
122 "OrElse", "Overloads", "Overridable", "Overrides",
123 "ParamArray", "Preserve", "Private", "Property",
124 "Protected", "Public", "RaiseEvent", "ReadOnly",
125 "ReDim", "REM", "RemoveHandler", "Resume",
126 "Return", "Select", "Set", "Shadows",
127 "Shared", "Short", "Single", "Static",
128 "Step", "Stop", "String", "Structure",
129 "Sub", "SyncLock", "Then", "Throw",
130 "To", "True", "Try", "TypeOf",
131 "Unicode", "Until", "Variant", "When",
132 "While", "With", "WithEvents", "WriteOnly",
137 public VBCodeGenerator()
141 protected override string NullToken {
147 protected override void ContinueOnNewLine (string st)
150 Output.WriteLine (" _");
153 protected override void GenerateBinaryOperatorExpression (CodeBinaryOperatorExpression e)
155 // We need to special case for comparisons against null;
156 // in Visual Basic the "Not (Expr) Is Nothing" construct is used
158 bool null_comparison = false;
159 bool reverse = false;
160 if (e.Operator == CodeBinaryOperatorType.IdentityInequality) {
161 CodePrimitiveExpression nothing;
162 nothing = e.Left as CodePrimitiveExpression;
163 if (nothing == null) {
164 nothing = e.Right as CodePrimitiveExpression;
168 null_comparison = nothing != null && nothing.Value == null;
171 if (null_comparison) {
172 TextWriter output = Output;
174 output.Write ("(Not (");
175 GenerateExpression (reverse ? e.Right : e.Left);
176 output.Write (") Is ");
177 GenerateExpression (reverse ? e.Left : e.Right);
180 base.GenerateBinaryOperatorExpression (e);
184 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
186 TextWriter output = Output;
188 output.Write ("New ");
190 CodeExpressionCollection initializers = expression.Initializers;
191 CodeTypeReference createType = expression.CreateType;
193 if (initializers.Count > 0) {
195 OutputType (createType);
197 output.Write ("() {");
199 OutputExpressionList (initializers);
203 CodeTypeReference arrayType = createType.ArrayElementType;
204 while (arrayType != null) {
205 createType = arrayType;
206 arrayType = arrayType.ArrayElementType;
209 OutputType (createType);
213 CodeExpression size = expression.SizeExpression;
215 GenerateExpression (size);
217 output.Write (expression.Size);
219 output.Write (") - 1) {}");
223 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
225 Output.Write ("MyBase");
228 protected override void GenerateCastExpression (CodeCastExpression expression)
230 TextWriter output = Output;
231 // ENHANCE: Use a DirectCast if it is known that expression.Expression is no Value-Type
232 output.Write ("CType(");
233 GenerateExpression (expression.Expression);
235 OutputType (expression.TargetType);
239 private bool AsBool (object datavalue)
241 return datavalue != null && datavalue is bool && (bool) datavalue;
244 private string OnOff (bool datavalue)
246 return datavalue ? "On" : "Off";
249 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
251 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
252 GenerateComment (new CodeComment (" <autogenerated>"));
253 GenerateComment (new CodeComment (" This code was generated by a tool."));
254 GenerateComment (new CodeComment (" Mono Runtime Version: " + System.Environment.Version));
255 GenerateComment (new CodeComment (""));
256 GenerateComment (new CodeComment (" Changes to this file may cause incorrect behavior and will be lost if "));
257 GenerateComment (new CodeComment (" the code is regenerated."));
258 GenerateComment (new CodeComment (" </autogenerated>"));
259 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
261 if (AsBool (compileUnit.UserData ["AllowLateBound"])) {
262 Output.WriteLine("Option Explicit {0}", OnOff (AsBool (compileUnit.UserData ["RequireVariableDeclaration"])));
263 Output.WriteLine("Option Strict Off");
265 Output.WriteLine("Option Explicit On"); // Strict On implies Explicit On
266 Output.WriteLine("Option Strict On");
271 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
273 GenerateCompileUnitStart (compileUnit);
275 OutputAttributes (compileUnit.AssemblyCustomAttributes,
276 "Assembly: ", LineHandling.NewLine);
278 GenerateNamespaces (compileUnit);
280 GenerateCompileUnitEnd (compileUnit);
283 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
285 TextWriter output = Output;
287 output.Write ("AddressOf ");
289 CodeExpression targetObject = expression.TargetObject;
290 if (targetObject != null) {
291 GenerateExpression (targetObject);
294 output.Write (expression.MethodName);
297 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
299 CodeExpression targetObject = expression.TargetObject;
300 if (targetObject != null) {
301 GenerateExpression (targetObject);
304 Output.Write (CreateEscapedIdentifier (expression.FieldName));
307 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
309 Output.Write (CreateEscapedIdentifier (expression.ParameterName));
312 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
314 Output.Write (CreateEscapedIdentifier (expression.VariableName));
317 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
319 TextWriter output = Output;
321 GenerateExpression (expression.TargetObject);
323 OutputExpressionList (expression.Indices);
327 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
329 TextWriter output = Output;
331 GenerateExpression (expression.TargetObject);
333 OutputExpressionList (expression.Indices);
337 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
339 Output.Write (expression.Value);
342 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
344 TextWriter output = Output;
346 GenerateMethodReferenceExpression (expression.Method);
349 OutputExpressionList (expression.Parameters);
353 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
355 if (expression.TargetObject != null) {
356 GenerateExpression (expression.TargetObject);
359 Output.Write (CreateEscapedIdentifier (expression.MethodName));
362 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
364 if (expression.TargetObject != null) {
365 GenerateExpression (expression.TargetObject);
367 if (expression.TargetObject is CodeThisReferenceExpression) {
368 // We're actually creating a reference to a compiler-generated field here...
369 Output.Write (expression.EventName + "Event");
371 Output.Write (CreateEscapedIdentifier (expression.EventName));
374 Output.Write (CreateEscapedIdentifier (expression.EventName + "Event"));
378 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
380 CodeEventReferenceExpression ev = expression.TargetObject as CodeEventReferenceExpression;
383 Output.Write ("RaiseEvent ");
387 Output.Write ("RaiseEvent ");
389 if (ev.TargetObject != null && !(ev.TargetObject is CodeThisReferenceExpression)) {
390 GenerateExpression (ev.TargetObject);
393 Output.Write (ev.EventName);
394 } else if (expression.TargetObject != null) {
395 GenerateExpression (expression.TargetObject);
398 OutputExpressionList (expression.Parameters);
402 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
404 Output.Write( "New " );
405 OutputType (expression.CreateType);
407 OutputExpressionList (expression.Parameters);
411 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
413 OutputAttributes (e.CustomAttributes, null, LineHandling.InLine);
414 OutputDirection (e.Direction);
415 OutputTypeNamePair (e.Type, e.Name);
418 protected override void GeneratePrimitiveExpression (CodePrimitiveExpression e)
420 if (e.Value is char) {
421 char c = (char) e.Value;
424 Output.Write("Global.Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
425 } else if (e.Value is ushort) {
426 ushort uc = (ushort) e.Value;
427 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
429 } else if (e.Value is uint) {
430 uint ui = (uint) e.Value;
431 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
433 } else if (e.Value is ulong) {
434 ulong ul = (ulong) e.Value;
435 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
437 } else if (e.Value is sbyte) {
438 sbyte sb = (sbyte) e.Value;
439 Output.Write ("CSByte(");
440 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
443 Output.Write("Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
446 base.GeneratePrimitiveExpression(e);
450 protected override void GenerateSingleFloatValue (float s)
452 base.GenerateSingleFloatValue (s);
453 base.Output.Write ('!');
456 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
458 if (expression.TargetObject != null) {
459 GenerateMemberReferenceExpression (expression.TargetObject, expression.PropertyName);
461 Output.Write (CreateEscapedIdentifier (expression.PropertyName));
465 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
467 Output.Write ("Value");
470 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
475 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
477 GenerateExpression (statement.Expression);
478 Output.WriteLine (); //start new line
481 protected override void GenerateIterationStatement (CodeIterationStatement statement)
483 TextWriter output = Output;
485 GenerateStatement (statement.InitStatement);
486 output.Write ("Do While ");
487 GenerateExpression (statement.TestExpression);
490 GenerateStatements (statement.Statements);
491 GenerateStatement (statement.IncrementStatement);
493 output.WriteLine ("Loop");
496 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
498 Output.Write ("Throw");
499 if (statement.ToThrow != null) {
501 GenerateExpression (statement.ToThrow);
506 protected override void GenerateComment (CodeComment comment)
508 TextWriter output = Output;
509 string commentChars = null;
511 if (comment.DocComment) {
512 commentChars = "'''";
517 output.Write (commentChars);
518 string text = comment.Text;
520 for (int i = 0; i < text.Length; i++) {
521 output.Write (text [i]);
522 if (text[i] == '\r') {
523 if (i < (text.Length - 1) && text [i + 1] == '\n') {
526 output.Write (commentChars);
527 } else if (text [i] == '\n') {
528 output.Write (commentChars);
535 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
537 TextWriter output = Output;
539 if (statement.Expression != null) {
540 output.Write ("Return ");
541 GenerateExpression (statement.Expression);
544 output.WriteLine ("Return");
548 protected override void GenerateConditionStatement (CodeConditionStatement statement)
550 TextWriter output = Output;
551 output.Write ("If ");
553 GenerateExpression (statement.Condition);
555 output.WriteLine (" Then");
557 GenerateStatements (statement.TrueStatements);
560 CodeStatementCollection falses = statement.FalseStatements;
561 if (falses.Count > 0) {
562 output.WriteLine ("Else");
564 GenerateStatements (falses);
568 if (Options.ElseOnClosing)
569 output.WriteLine ("Else");
571 output.WriteLine ("End If");
574 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
576 TextWriter output = Output;
578 output.WriteLine ("Try ");
580 GenerateStatements (statement.TryStatements);
583 foreach (CodeCatchClause clause in statement.CatchClauses) {
584 output.Write ("Catch ");
585 OutputTypeNamePair (clause.CatchExceptionType, clause.LocalName);
588 GenerateStatements (clause.Statements);
592 CodeStatementCollection finallies = statement.FinallyStatements;
593 if (finallies.Count > 0) {
594 output.WriteLine ("Finally");
596 GenerateStatements (finallies);
600 output.WriteLine("End Try");
603 protected override void GenerateAssignStatement (CodeAssignStatement statement)
605 TextWriter output = Output;
606 GenerateExpression (statement.Left);
607 output.Write (" = ");
608 GenerateExpression (statement.Right);
612 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
614 TextWriter output = Output;
616 Output.Write ("AddHandler ");
617 if (statement.Event.TargetObject != null) {
618 GenerateEventReferenceExpression (statement.Event);
620 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
622 Output.Write ( ", ");
623 GenerateExpression (statement.Listener);
627 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
629 TextWriter output = Output;
631 Output.Write ("RemoveHandler ");
632 if (statement.Event.TargetObject != null) {
633 GenerateEventReferenceExpression (statement.Event);
635 Output.Write (CreateEscapedIdentifier (statement.Event.EventName));
637 Output.Write ( ", ");
638 GenerateExpression (statement.Listener);
642 protected override void GenerateGotoStatement (CodeGotoStatement statement)
644 TextWriter output = Output;
646 output.Write ("goto ");
647 output.Write (statement.Label);
651 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
653 TextWriter output = Output;
656 output.WriteLine (statement.Label + ":");
658 if (statement.Statement != null) {
659 GenerateStatement (statement.Statement);
663 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
665 TextWriter output = Output;
667 output.Write ("GetType(");
672 protected override void GenerateVariableDeclarationStatement( CodeVariableDeclarationStatement statement )
674 TextWriter output = Output;
676 output.Write ("Dim ");
677 OutputTypeNamePair (statement.Type, statement.Name);
679 CodeExpression initExpression = statement.InitExpression;
680 if (initExpression != null) {
681 output.Write (" = ");
682 GenerateExpression (initExpression);
688 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
691 Output.Write ("#ExternalSource(\"");
692 Output.Write (linePragma.FileName);
693 Output.Write ("\",");
694 Output.Write (linePragma.LineNumber);
695 Output.WriteLine (")");
696 Output.WriteLine ("");
699 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
701 Output.WriteLine ("#End ExternalSource");
704 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
706 if (IsCurrentDelegate || IsCurrentEnum)
709 TextWriter output = Output;
711 OutputAttributes (eventRef.CustomAttributes, null,
712 LineHandling.ContinueLine);
714 OutputMemberAccessModifier (eventRef.Attributes);
716 output.Write ("Event ");
717 OutputTypeNamePair (eventRef.Type, GetEventName(eventRef));
720 if (eventRef.ImplementationTypes.Count > 0) {
721 OutputImplementationTypes (eventRef.ImplementationTypes, eventRef.Name);
722 } else if (eventRef.PrivateImplementationType != null) {
723 output.Write (" Implements ");
724 OutputType (eventRef.PrivateImplementationType);
726 output.Write (eventRef.Name);
733 protected override void GenerateField (CodeMemberField field)
735 if (IsCurrentDelegate || IsCurrentInterface)
738 TextWriter output = Output;
740 OutputAttributes (field.CustomAttributes, null,
741 LineHandling.ContinueLine);
744 output.Write (field.Name);
746 MemberAttributes attributes = field.Attributes;
747 OutputMemberAccessModifier (attributes);
748 OutputVTableModifier (attributes);
749 OutputFieldScopeModifier (attributes);
750 OutputTypeNamePair (field.Type, field.Name);
753 CodeExpression initExpression = field.InitExpression;
754 if (initExpression != null) {
755 output.Write (" = ");
756 GenerateExpression (initExpression);
762 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
764 Output.Write (member.Text);
767 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, CodeTypeDeclaration declaration)
770 OutputAttributes (method.CustomAttributes, null,
771 LineHandling.ContinueLine);
774 Output.WriteLine ("Public Shared Sub Main()");
776 GenerateStatements (method.Statements);
778 Output.WriteLine ("End Sub");
781 [MonoTODO ("partially implemented")]
782 protected override void GenerateMethod (CodeMemberMethod method, CodeTypeDeclaration declaration)
784 if (IsCurrentDelegate || IsCurrentEnum)
787 bool isSub = method.ReturnType.BaseType == typeof(void).FullName;
789 TextWriter output = Output;
791 OutputAttributes (method.CustomAttributes, null,
792 LineHandling.ContinueLine);
794 MemberAttributes attributes = method.Attributes;
796 if (!IsCurrentInterface) {
797 if (method.PrivateImplementationType == null) {
798 OutputMemberAccessModifier (attributes);
799 if (IsOverloaded (method, declaration)) {
800 output.Write ("Overloads ");
803 OutputVTableModifier (attributes);
804 OutputMemberScopeModifier (attributes);
806 OutputVTableModifier (attributes);
810 output.Write ("Sub ");
812 output.Write ("Function ");
814 output.Write (GetMethodName(method));
817 OutputTypeParameters (method.TypeParameters);
821 OutputParameters (method.Parameters);
825 output.Write (" As ");
826 OutputAttributes (method.ReturnTypeCustomAttributes, null,
827 LineHandling.InLine);
828 OutputType (method.ReturnType);
831 if (method.ImplementationTypes.Count > 0) {
832 OutputImplementationTypes (method.ImplementationTypes, method.Name);
833 } else if (method.PrivateImplementationType != null) {
834 output.Write (" Implements ");
835 OutputType (method.PrivateImplementationType);
837 output.Write (method.Name);
841 if (!IsCurrentInterface) {
842 if ((attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
844 GenerateStatements (method.Statements);
847 output.WriteLine ("End Sub");
849 output.WriteLine ("End Function");
854 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
856 if (IsCurrentDelegate || IsCurrentEnum)
859 TextWriter output = Output;
861 OutputAttributes (property.CustomAttributes, null,
862 LineHandling.ContinueLine);
864 MemberAttributes attributes = property.Attributes;
866 if (!IsCurrentInterface) {
867 if (property.PrivateImplementationType == null) {
868 OutputMemberAccessModifier (attributes);
869 if (IsOverloaded (property, declaration)) {
870 output.Write ("Overloads ");
873 OutputVTableModifier (attributes);
874 OutputMemberScopeModifier (attributes);
876 OutputVTableModifier (attributes);
879 // mark property as default property if we're dealing with an indexer
880 if (string.Compare (GetPropertyName(property), "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
881 output.Write ("Default ");
884 if (property.HasGet && (!property.HasSet))
885 output.Write ("ReadOnly " );
887 if (property.HasSet && (!property.HasGet))
888 output.Write ("WriteOnly " );
890 output.Write ("Property ");
891 Output.Write (GetPropertyName (property));
893 // in .NET 2.0, always output parantheses (whether or not there
894 // are any parameters to output
896 OutputParameters (property.Parameters);
899 if (property.Parameters.Count > 0) {
901 OutputParameters (property.Parameters);
905 Output.Write (" As ");
906 Output.Write (GetTypeOutput(property.Type));
908 if (property.ImplementationTypes.Count > 0) {
909 OutputImplementationTypes (property.ImplementationTypes, property.Name);
910 } else if (property.PrivateImplementationType != null) {
911 output.Write (" Implements ");
912 OutputType (property.PrivateImplementationType);
914 output.Write (property.Name);
919 if (!IsCurrentInterface) {
921 if (property.HasGet) {
922 output.WriteLine ("Get");
924 GenerateStatements (property.GetStatements);
926 output.WriteLine ("End Get");
929 if (property.HasSet) {
930 output.WriteLine ("Set");
932 GenerateStatements (property.SetStatements);
934 output.WriteLine ("End Set");
938 output.WriteLine ("End Property");
942 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
944 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
947 OutputAttributes (constructor.CustomAttributes, null,
948 LineHandling.ContinueLine);
949 OutputMemberAccessModifier (constructor.Attributes);
950 Output.Write ("Sub New(");
951 OutputParameters (constructor.Parameters);
952 Output.WriteLine (")");
954 // check if ctor passes args on to other ctor in class
955 CodeExpressionCollection ctorArgs = constructor.ChainedConstructorArgs;
956 if (ctorArgs.Count > 0) {
957 Output.Write ("Me.New(");
958 OutputExpressionList (ctorArgs);
959 Output.WriteLine (")");
961 // check if ctor passes args on to ctor in base class
962 ctorArgs = constructor.BaseConstructorArgs;
963 if (ctorArgs.Count > 0) {
964 Output.Write ("MyBase.New(");
965 OutputExpressionList (ctorArgs);
966 Output.WriteLine (")");
968 } else if (IsCurrentClass) {
972 // call default base ctor
973 Output.WriteLine ("MyBase.New");
976 GenerateStatements (constructor.Statements);
978 Output.WriteLine ("End Sub");
981 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
983 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface)
987 OutputAttributes (constructor.CustomAttributes, null,
988 LineHandling.ContinueLine);
991 Output.WriteLine ("Shared Sub New()");
993 GenerateStatements (constructor.Statements);
995 Output.WriteLine ("End Sub");
998 [MonoTODO ("partially implemented")]
999 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
1001 TextWriter output = Output;
1003 OutputAttributes (declaration.CustomAttributes, null,
1004 LineHandling.ContinueLine);
1006 TypeAttributes attributes = declaration.TypeAttributes;
1008 if (IsCurrentDelegate) {
1009 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
1011 if ((attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
1012 output.Write ("Public ");
1015 bool isSub = delegateDecl.ReturnType.BaseType == typeof (void).FullName;
1017 output.Write ("Delegate Sub ");
1019 output.Write ("Delegate Function ");
1022 output.Write (CreateEscapedIdentifier (delegateDecl.Name));
1024 OutputTypeParameters (delegateDecl.TypeParameters);
1027 OutputParameters (delegateDecl.Parameters);
1030 Output.Write (" As ");
1031 OutputType (delegateDecl.ReturnType);
1033 Output.WriteLine ("");
1035 OutputTypeAttributes (declaration);
1036 output.Write (CreateEscapedIdentifier (declaration.Name));
1038 OutputTypeParameters (declaration.TypeParameters);
1041 if (IsCurrentEnum) {
1042 if (declaration.BaseTypes.Count > 0) {
1043 output.Write (" As ");
1044 OutputType (declaration.BaseTypes[0]);
1046 output.WriteLine ();
1051 bool firstInherits = true;
1052 bool firstImplements = true;
1054 for (int i = 0; i < declaration.BaseTypes.Count; i++) {
1055 // a struct can only implement interfaces
1056 // an interface can only inherit from other interface
1058 CodeTypeReference typeRef = declaration.BaseTypes[i];
1060 if (firstInherits && !declaration.IsStruct && !typeRef.IsInterface) {
1061 output.WriteLine ();
1062 output.Write ("Inherits ");
1063 firstInherits = false;
1064 } else if (!declaration.IsInterface && firstImplements) {
1065 output.WriteLine ();
1066 output.Write ("Implements ");
1067 firstImplements = false;
1069 output.Write (", ");
1071 OutputType (typeRef);
1073 output.WriteLine ();
1078 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
1080 if (IsCurrentDelegate) {
1083 string output = string.Empty;
1086 if (declaration.IsStruct)
1087 output = "End Structure";
1088 if (declaration.IsInterface)
1089 output = "End Interface";
1090 if (declaration.IsEnum)
1091 output = "End Enum";
1092 if (declaration.IsClass)
1093 output = "End Class";
1095 Output.WriteLine (output);
1098 protected override void GenerateNamespace(CodeNamespace ns)
1100 GenerateNamespaceImports (ns);
1101 Output.WriteLine ();
1102 GenerateCommentStatements (ns.Comments);
1103 GenerateNamespaceStart (ns);
1105 GenerateNamespaceEnd (ns);
1109 protected override void GenerateNamespaceStart (CodeNamespace ns)
1111 TextWriter output = Output;
1113 string name = ns.Name;
1114 if (name != null && name != string.Empty) {
1115 output.Write ("Namespace ");
1116 output.WriteLine (name);
1121 protected override void GenerateNamespaceEnd (CodeNamespace ns)
1123 string name = ns.Name;
1124 if (name != null && name != string.Empty) {
1126 Output.WriteLine ("End Namespace");
1130 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
1132 TextWriter output = Output;
1134 output.Write ("Imports ");
1135 output.Write (import.Namespace);
1136 output.WriteLine ();
1139 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
1144 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
1149 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, LineHandling lineHandling) {
1150 if (attributes.Count == 0) {
1154 GenerateAttributeDeclarationsStart (attributes);
1156 IEnumerator enumerator = attributes.GetEnumerator ();
1157 if (enumerator.MoveNext ()) {
1158 CodeAttributeDeclaration att = (CodeAttributeDeclaration) enumerator.Current;
1159 if (prefix != null) {
1160 Output.Write (prefix);
1162 OutputAttributeDeclaration (att);
1164 while (enumerator.MoveNext ()) {
1165 Output.Write (", ");
1166 if (lineHandling != LineHandling.InLine) {
1167 ContinueOnNewLine ("");
1170 att = (CodeAttributeDeclaration) enumerator.Current;
1171 if (prefix != null) {
1172 Output.Write (prefix);
1174 OutputAttributeDeclaration (att);
1177 GenerateAttributeDeclarationsEnd (attributes);
1180 switch (lineHandling) {
1181 case LineHandling.ContinueLine:
1182 ContinueOnNewLine ("");
1184 case LineHandling.NewLine:
1185 Output.WriteLine ();
1190 protected override void OutputAttributeArgument (CodeAttributeArgument argument)
1192 string name = argument.Name;
1193 if (name != null && name.Length > 0) {
1194 Output.Write (name);
1195 Output.Write (":=");
1197 GenerateExpression (argument.Value);
1200 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
1202 Output.Write (attribute.Name.Replace ('+', '.'));
1204 IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
1205 if (enumerator.MoveNext ()) {
1206 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
1207 OutputAttributeArgument (argument);
1209 while (enumerator.MoveNext ()) {
1210 Output.Write (", ");
1211 argument = (CodeAttributeArgument) enumerator.Current;
1212 OutputAttributeArgument (argument);
1218 protected override void OutputDirection (FieldDirection direction)
1220 switch (direction) {
1221 case FieldDirection.In:
1222 Output.Write ("ByVal ");
1224 case FieldDirection.Out:
1225 case FieldDirection.Ref:
1226 Output.Write ("ByRef ");
1231 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1233 switch (attributes & MemberAttributes.ScopeMask) {
1234 case MemberAttributes.Static:
1235 Output.Write ("Shared ");
1237 case MemberAttributes.Const:
1238 Output.Write ("Const ");
1243 private void OutputImplementationTypes (CodeTypeReferenceCollection implementationTypes, string member)
1245 IEnumerator enumerator = implementationTypes.GetEnumerator ();
1246 if (enumerator.MoveNext ()) {
1247 Output.Write (" Implements ");
1249 CodeTypeReference typeReference = (CodeTypeReference) enumerator.Current;
1250 OutputType (typeReference);
1252 OutputIdentifier (member);
1254 while (enumerator.MoveNext ()) {
1255 Output.Write (" , ");
1256 typeReference = (CodeTypeReference) enumerator.Current;
1257 OutputType (typeReference);
1259 OutputIdentifier (member);
1264 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1266 switch (attributes & MemberAttributes.AccessMask) {
1267 case MemberAttributes.Assembly:
1268 case MemberAttributes.FamilyAndAssembly:
1269 Output.Write ("Friend ");
1271 case MemberAttributes.Family:
1272 Output.Write ("Protected ");
1274 case MemberAttributes.FamilyOrAssembly:
1275 Output.Write ("Protected Friend ");
1277 case MemberAttributes.Private:
1278 Output.Write ("Private ");
1280 case MemberAttributes.Public:
1281 Output.Write ("Public ");
1286 private void OutputVTableModifier (MemberAttributes attributes)
1288 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New)
1289 Output.Write ("Shadows ");
1292 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1294 switch (attributes & MemberAttributes.ScopeMask) {
1295 case MemberAttributes.Abstract:
1296 Output.Write ("MustOverride ");
1298 case MemberAttributes.Final:
1301 case MemberAttributes.Static:
1302 Output.Write ("Shared ");
1304 case MemberAttributes.Override:
1305 Output.Write ("Overrides ");
1307 case MemberAttributes.Overloaded:
1308 // based on http://gendotnet.com/Code%20Gen%20Articles/codedom.htm
1309 Output.Write ("Overloads ");
1311 MemberAttributes access_ovl = attributes & MemberAttributes.AccessMask;
1312 if (access_ovl == MemberAttributes.Public || access_ovl == MemberAttributes.Family)
1313 Output.Write ("Overridable ");
1317 // FUNNY! if the scope value is
1318 // rubbish (0 or >Const), and access
1319 // is public, protected make it
1322 // i'm not sure whether this is 100%
1323 // correct, but it seems to be MS
1326 // On MS.NET 2.0, internal properties
1327 // are also marked "virtual".
1329 MemberAttributes access = attributes & MemberAttributes.AccessMask;
1330 if (access == MemberAttributes.Public ||
1332 access == MemberAttributes.Family || access == MemberAttributes.Assembly)
1334 access == MemberAttributes.Family)
1336 Output.Write ("Overridable ");
1341 protected override void OutputOperator (CodeBinaryOperatorType op)
1344 case CodeBinaryOperatorType.Add:
1347 case CodeBinaryOperatorType.Subtract:
1350 case CodeBinaryOperatorType.Multiply:
1353 case CodeBinaryOperatorType.Divide:
1356 case CodeBinaryOperatorType.Modulus:
1357 Output.Write ("Mod");
1359 case CodeBinaryOperatorType.Assign:
1362 case CodeBinaryOperatorType.IdentityInequality:
1363 Output.Write ("<>");
1365 case CodeBinaryOperatorType.IdentityEquality:
1366 Output.Write ("Is");
1368 case CodeBinaryOperatorType.ValueEquality:
1371 case CodeBinaryOperatorType.BitwiseOr:
1372 Output.Write ("Or");
1374 case CodeBinaryOperatorType.BitwiseAnd:
1375 Output.Write ("And");
1377 case CodeBinaryOperatorType.BooleanOr:
1378 Output.Write ("OrElse");
1380 case CodeBinaryOperatorType.BooleanAnd:
1381 Output.Write ("AndAlso");
1383 case CodeBinaryOperatorType.LessThan:
1386 case CodeBinaryOperatorType.LessThanOrEqual:
1387 Output.Write ("<=");
1389 case CodeBinaryOperatorType.GreaterThan:
1392 case CodeBinaryOperatorType.GreaterThanOrEqual:
1393 Output.Write (">=");
1398 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1400 TextWriter output = Output;
1401 TypeAttributes attributes = declaration.TypeAttributes;
1404 if (declaration.IsPartial)
1405 output.Write ("Partial ");
1408 switch (attributes & TypeAttributes.VisibilityMask) {
1409 case TypeAttributes.Public:
1410 case TypeAttributes.NestedPublic:
1411 output.Write ("Public ");
1413 case TypeAttributes.NestedPrivate:
1414 output.Write ("Private ");
1417 case TypeAttributes.NotPublic:
1418 case TypeAttributes.NestedFamANDAssem:
1419 case TypeAttributes.NestedAssembly:
1420 output.Write ("Friend ");
1422 case TypeAttributes.NestedFamily:
1423 output.Write ("Protected ");
1425 case TypeAttributes.NestedFamORAssem:
1426 output.Write ("Protected Friend ");
1431 if (declaration.IsStruct) {
1432 output.Write ("Structure ");
1433 } else if (declaration.IsEnum) {
1434 output.Write ("Enum ");
1436 if ((attributes & TypeAttributes.Interface) != 0) {
1437 output.Write ("Interface ");
1439 if ((attributes & TypeAttributes.Sealed) != 0)
1440 output.Write ("NotInheritable ");
1442 if ((attributes & TypeAttributes.Abstract) != 0)
1443 output.Write ("MustInherit ");
1445 output.Write ("Class ");
1451 void OutputTypeParameters (CodeTypeParameterCollection parameters)
1453 int count = parameters.Count;
1457 Output.Write ("(Of ");
1458 for (int i = 0; i < count; ++i) {
1460 Output.Write (", ");
1461 CodeTypeParameter p = parameters [i];
1462 Output.Write (p.Name);
1463 OutputTypeParameterConstraints (p);
1468 void OutputTypeParameterConstraints (CodeTypeParameter parameter)
1470 int constraint_count = parameter.Constraints.Count +
1471 (parameter.HasConstructorConstraint ? 1 : 0);
1473 if (constraint_count == 0)
1476 Output.Write (" As ");
1478 if (constraint_count > 1)
1479 Output.Write (" {");
1481 for (int i = 0; i < parameter.Constraints.Count; i++) {
1483 Output.Write (", ");
1484 OutputType (parameter.Constraints [i]);
1487 if (parameter.HasConstructorConstraint) {
1488 if (constraint_count > 1)
1489 Output.Write (", ");
1490 Output.Write ("New");
1493 if (constraint_count > 1)
1498 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
1501 if (name.Length == 0)
1502 name = "__exception";
1504 Output.Write (CreateEscapedIdentifier(name) + " As " + GetTypeOutput (typeRef));
1507 protected override void OutputType (CodeTypeReference type)
1509 Output.Write (GetTypeOutput (type));
1512 protected override string QuoteSnippetString (string value)
1514 StringBuilder mySBuilder = new StringBuilder(value.Length);
1515 mySBuilder.Append ("\"");
1516 bool inQuotes = true;
1517 for (int MyCounter = 0; MyCounter < value.Length; MyCounter++) {
1518 if (value[MyCounter] == 34) //quotation mark
1521 mySBuilder.Append ("&\"");
1524 mySBuilder.Append (value[MyCounter]);
1525 mySBuilder.Append (value[MyCounter]);
1527 else if (value[MyCounter] >= 32) //standard ansi/unicode characters
1530 mySBuilder.Append ("&\"");
1533 mySBuilder.Append (value[MyCounter]);
1535 else //special chars, e.g. line break
1538 mySBuilder.Append ("\"");
1541 mySBuilder.Append ("&Microsoft.VisualBasic.ChrW(");
1542 mySBuilder.Append ((int)value[MyCounter]);
1543 mySBuilder.Append (")");
1547 mySBuilder.Append ("\"");
1548 return mySBuilder.ToString();
1551 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1553 GenerateExpression (targetObject);
1555 Output.Write (memberName);
1562 protected override string CreateEscapedIdentifier (string value)
1564 for (int x = 0; x < Keywords.Length; x++)
1565 if (value.ToLower().Equals (Keywords[x].ToLower()))
1566 return "[" + value + "]";
1570 protected override string CreateValidIdentifier (string value)
1572 for (int x = 0; x < Keywords.Length; x++)
1573 if (value.ToLower().Equals (Keywords[x].ToLower()))
1578 protected override string GetTypeOutput (CodeTypeReference type)
1581 CodeTypeReference arrayType;
1583 arrayType = type.ArrayElementType;
1584 if (arrayType != null)
1585 output = GetTypeOutput (arrayType);
1587 switch (type.BaseType) {
1588 case "System.DateTime":
1591 case "System.Decimal":
1594 case "System.Double":
1597 case "System.Single":
1603 case "System.Int32":
1606 case "System.Int64":
1609 case "System.Int16":
1612 case "System.Boolean":
1618 case "System.String":
1621 case "System.Object":
1625 case "System.SByte":
1628 case "System.UInt16":
1631 case "System.UInt32":
1632 output = "UInteger";
1634 case "System.UInt64":
1639 output = type.BaseType.Replace('+', '.');
1640 output = CreateEscapedIdentifier (output);
1645 int rank = type.ArrayRank;
1648 for (--rank; rank > 0; --rank)
1656 protected override bool IsValidIdentifier (string identifier)
1658 for (int x = 0; x < Keywords.Length; x++)
1659 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1664 protected override bool Supports (GeneratorSupport supports)
1669 private bool IsOverloaded (CodeMemberProperty property, CodeTypeDeclaration type)
1671 if ((property.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1675 foreach (CodeTypeMember member in type.Members) {
1676 CodeMemberProperty p = member as CodeMemberProperty;
1678 // member is not a property
1682 if (p != property && p.Name == property.Name && p.PrivateImplementationType == null)
1688 private bool IsOverloaded (CodeMemberMethod method, CodeTypeDeclaration type)
1690 if ((method.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1694 foreach (CodeTypeMember member in type.Members) {
1695 CodeMemberMethod m = member as CodeMemberMethod;
1697 // member is not a method
1701 if (!(m is CodeTypeConstructor) && !(m is CodeConstructor) && m != method && m.Name == method.Name && m.PrivateImplementationType == null)
1707 private string GetEventName (CodeMemberEvent evt)
1710 if (evt.PrivateImplementationType == null)
1713 string baseType = evt.PrivateImplementationType.BaseType.Replace ('.', '_');
1714 return baseType + "_" + evt.Name;
1720 private string GetMethodName (CodeMemberMethod method)
1722 if (method.PrivateImplementationType == null)
1725 string baseType = method.PrivateImplementationType.BaseType.Replace ('.', '_');
1726 return baseType + "_" + method.Name;
1729 private string GetPropertyName (CodeMemberProperty property)
1731 if (property.PrivateImplementationType == null)
1732 return property.Name;
1734 string baseType = property.PrivateImplementationType.BaseType.Replace ('.', '_');
1735 return baseType + "_" + property.Name;
1738 private enum LineHandling