2 // Microsoft.VisualBasic.VBCodeGenerator.cs
5 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
6 // (partially based on CSharpCodeGenerator)
7 // Jochen Wezel (jwezel@compumaster.de)
9 // (C) 2003 Andreas Nahr
10 // (C) 2003 Jochen Wezel (http://www.compumaster.de)
13 // 2003-11-06 JW: some corrections regarding missing spaces in generated code (e. g. "Property ")
14 // 2003-11-06 JW: QuoteSnippetString implemented
15 // 2003-11-08 JW: automatically add Microsoft.VisualBasic
16 // 2003-11-12 JW: some corrections to allow correct compilation
17 // 2003-11-28 JW: implementing code differences into current build of this file
18 // 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 // Permission is hereby granted, free of charge, to any person obtaining
22 // a copy of this software and associated documentation files (the
23 // "Software"), to deal in the Software without restriction, including
24 // without limitation the rights to use, copy, modify, merge, publish,
25 // distribute, sublicense, and/or sell copies of the Software, and to
26 // permit persons to whom the Software is furnished to do so, subject to
27 // the following conditions:
29 // The above copyright notice and this permission notice shall be
30 // included in all copies or substantial portions of the Software.
32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
36 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
37 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
38 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 using System.Globalization;
45 using System.Text.RegularExpressions;
47 using System.CodeDom.Compiler;
49 using System.Reflection;
50 using System.Collections;
52 namespace Microsoft.VisualBasic
54 internal class VBCodeGenerator : CodeGenerator
56 private string[] Keywords = new string[] {
57 "AddHandler", "AddressOf", "Alias", "And",
58 "AndAlso", "Ansi", "As", "Assembly",
59 "Auto", "Boolean", "ByRef", "Byte",
60 "ByVal", "Call", "Case", "Catch",
61 "CBool", "CByte", "CChar", "CDate",
62 "CDec", "CDbl", "Char", "CInt",
63 "Class", "CLng", "CObj", "Const",
64 "CShort", "CSng", "CStr", "CType",
65 "Date", "Decimal", "Declare", "Default",
66 "Delegate", "Dim", "DirectCast", "Do",
67 "Double", "Each", "Else", "ElseIf",
68 "End", "Enum", "Erase", "Error",
69 "Event", "Exit", "False", "Finally",
70 "For", "Friend", "Function", "Get",
71 "GetType", "GoSub", "GoTo", "Handles",
72 "If", "Implements", "Imports", "In",
73 "Inherits", "Integer", "Interface", "Is",
74 "Let", "Lib", "Like", "Long",
75 "Loop", "Me", "Mod", "Module",
76 "MustInherit", "MustOverride", "MyBase", "MyClass",
77 "Namespace", "New", "Next", "Not",
78 "Nothing", "NotInheritable", "NotOverridable", "Object",
79 "On", "Option", "Optional", "Or",
80 "OrElse", "Overloads", "Overridable", "Overrides",
81 "ParamArray", "Preserve", "Private", "Property",
82 "Protected", "Public", "RaiseEvent", "ReadOnly",
83 "ReDim", "REM", "RemoveHandler", "Resume",
84 "Return", "Select", "Set", "Shadows",
85 "Shared", "Short", "Single", "Static",
86 "Step", "Stop", "String", "Structure",
87 "Sub", "SyncLock", "Then", "Throw",
88 "To", "True", "Try", "TypeOf",
89 "Unicode", "Until", "Variant", "When",
90 "While", "With", "WithEvents", "WriteOnly",
94 public VBCodeGenerator()
98 protected override string NullToken {
104 protected override void ContinueOnNewLine (string st)
107 Output.WriteLine (" _");
110 protected override void GenerateArrayCreateExpression (CodeArrayCreateExpression expression)
112 TextWriter output = Output;
114 output.Write ("New ");
116 CodeExpressionCollection initializers = expression.Initializers;
117 CodeTypeReference createType = expression.CreateType;
119 if (initializers.Count > 0) {
121 OutputType (createType);
123 output.WriteLine (" {");
125 OutputExpressionList (initializers, true);
131 CodeTypeReference arrayType = createType.ArrayElementType;
132 while (arrayType != null)
134 createType = arrayType;
135 arrayType = arrayType.ArrayElementType;
138 OutputType (createType);
142 CodeExpression size = expression.SizeExpression;
144 GenerateExpression (size);
146 output.Write (expression.Size);
152 protected override void GenerateBaseReferenceExpression (CodeBaseReferenceExpression expression)
154 Output.Write ("MyBase");
157 protected override void GenerateCastExpression (CodeCastExpression expression)
159 TextWriter output = Output;
160 // ENHANCE: Use a DirectCast if it is known that expression.Expression is no Value-Type
161 output.Write ("CType(");
162 GenerateExpression (expression.Expression);
164 OutputType (expression.TargetType);
168 private bool AsBool(object datavalue)
170 return datavalue != null && datavalue is bool && (bool)datavalue;
173 private string OnOff(bool datavalue)
175 return datavalue?"On":"Off";
178 protected override void GenerateCompileUnitStart (CodeCompileUnit compileUnit)
180 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
181 GenerateComment (new CodeComment (" <autogenerated>"));
182 GenerateComment (new CodeComment (" This code was generated by a tool."));
183 GenerateComment (new CodeComment (" Mono Runtime Version: " + System.Environment.Version));
184 GenerateComment (new CodeComment (""));
185 GenerateComment (new CodeComment (" Changes to this file may cause incorrect behavior and will be lost if "));
186 GenerateComment (new CodeComment (" the code is regenerated."));
187 GenerateComment (new CodeComment (" </autogenerated>"));
188 GenerateComment (new CodeComment ("------------------------------------------------------------------------------"));
190 if (AsBool(compileUnit.UserData["AllowLateBound"])) {
191 Output.WriteLine("Option Explicit {0}",OnOff(AsBool(compileUnit.UserData["RequireVariableDeclaration"])));
192 Output.WriteLine("Option Strict Off");
194 Output.WriteLine("Option Explicit On"); // Strict On implies Explicit On
195 Output.WriteLine("Option Strict On");
200 protected override void GenerateCompileUnit (CodeCompileUnit compileUnit)
202 GenerateCompileUnitStart (compileUnit);
204 OutputAttributes (compileUnit.AssemblyCustomAttributes,
205 "Assembly: ", LineHandling.NewLine);
207 GenerateNamespaces (compileUnit);
209 GenerateCompileUnitEnd (compileUnit);
212 protected override void GenerateDelegateCreateExpression (CodeDelegateCreateExpression expression)
214 TextWriter output = Output;
216 output.Write ("AddressOf ");
218 CodeExpression targetObject = expression.TargetObject;
219 if (targetObject != null) {
220 GenerateExpression (targetObject);
223 output.Write (expression.MethodName);
226 protected override void GenerateFieldReferenceExpression (CodeFieldReferenceExpression expression)
228 CodeExpression targetObject = expression.TargetObject;
229 if (targetObject != null) {
230 GenerateExpression (targetObject);
233 Output.Write (expression.FieldName);
236 protected override void GenerateArgumentReferenceExpression (CodeArgumentReferenceExpression expression)
238 Output.Write (expression.ParameterName);
241 protected override void GenerateVariableReferenceExpression (CodeVariableReferenceExpression expression)
243 Output.Write (expression.VariableName);
246 protected override void GenerateIndexerExpression (CodeIndexerExpression expression)
248 TextWriter output = Output;
250 GenerateExpression (expression.TargetObject);
252 OutputExpressionList (expression.Indices);
256 protected override void GenerateArrayIndexerExpression (CodeArrayIndexerExpression expression)
258 TextWriter output = Output;
260 GenerateExpression (expression.TargetObject);
261 output.Write (".Item(");
262 OutputExpressionList (expression.Indices);
266 protected override void GenerateSnippetExpression (CodeSnippetExpression expression)
268 Output.Write (expression.Value);
271 protected override void GenerateMethodInvokeExpression (CodeMethodInvokeExpression expression)
273 TextWriter output = Output;
275 GenerateMethodReferenceExpression (expression.Method);
278 OutputExpressionList (expression.Parameters);
282 protected override void GenerateMethodReferenceExpression (CodeMethodReferenceExpression expression)
284 GenerateExpression (expression.TargetObject);
286 Output.Write (expression.MethodName);
289 protected override void GenerateEventReferenceExpression (CodeEventReferenceExpression expression)
291 if (expression.TargetObject != null) {
292 GenerateExpression (expression.TargetObject);
295 Output.Write (CreateEscapedIdentifier(expression.EventName));
298 protected override void GenerateDelegateInvokeExpression (CodeDelegateInvokeExpression expression)
300 Output.Write ("RaiseEvent ");
301 GenerateExpression (expression.TargetObject);
303 OutputExpressionList (expression.Parameters);
304 Output.WriteLine (')');
307 protected override void GenerateObjectCreateExpression (CodeObjectCreateExpression expression)
309 Output.Write( "New " );
310 OutputType (expression.CreateType);
312 OutputExpressionList (expression.Parameters);
316 protected override void GenerateParameterDeclarationExpression (CodeParameterDeclarationExpression e)
318 OutputAttributes (e.CustomAttributes, null, LineHandling.InLine);
319 OutputDirection (e.Direction);
320 OutputTypeNamePair (e.Type, e.Name);
323 protected override void GeneratePrimitiveExpression (CodePrimitiveExpression e)
325 if (e.Value is char) {
326 char c = (char) e.Value;
329 Output.Write("Global.Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
330 } else if (e.Value is ushort) {
331 ushort uc = (ushort) e.Value;
332 Output.Write (uc.ToString(CultureInfo.InvariantCulture));
334 } else if (e.Value is uint) {
335 uint ui = (uint) e.Value;
336 Output.Write (ui.ToString(CultureInfo.InvariantCulture));
338 } else if (e.Value is ulong) {
339 ulong ul = (ulong) e.Value;
340 Output.Write (ul.ToString(CultureInfo.InvariantCulture));
342 } else if (e.Value is sbyte) {
343 sbyte sb = (sbyte) e.Value;
344 Output.Write ("CSByte(");
345 Output.Write (sb.ToString(CultureInfo.InvariantCulture));
348 Output.Write("Microsoft.VisualBasic.ChrW(" + ch.ToString(CultureInfo.InvariantCulture) + ")");
351 base.GeneratePrimitiveExpression(e);
355 protected override void GenerateSingleFloatValue (float s)
357 base.GenerateSingleFloatValue (s);
358 base.Output.Write ('!');
361 protected override void GeneratePropertyReferenceExpression (CodePropertyReferenceExpression expression)
363 GenerateMemberReferenceExpression (expression.TargetObject, expression.PropertyName);
366 protected override void GeneratePropertySetValueReferenceExpression (CodePropertySetValueReferenceExpression expression)
368 Output.Write ("Value");
371 protected override void GenerateThisReferenceExpression (CodeThisReferenceExpression expression)
376 protected override void GenerateExpressionStatement (CodeExpressionStatement statement)
378 GenerateExpression (statement.Expression);
379 Output.WriteLine (); //start new line
382 protected override void GenerateIterationStatement (CodeIterationStatement statement)
384 TextWriter output = Output;
386 GenerateStatement (statement.InitStatement);
387 output.Write ("Do While ");
388 GenerateExpression (statement.TestExpression);
391 GenerateStatements (statement.Statements);
392 GenerateStatement (statement.IncrementStatement);
394 output.WriteLine ("Loop");
397 protected override void GenerateThrowExceptionStatement (CodeThrowExceptionStatement statement)
399 Output.Write ("Throw");
400 if (statement.ToThrow != null) {
402 GenerateExpression (statement.ToThrow);
407 protected override void GenerateComment (CodeComment comment)
409 TextWriter output = Output;
410 string commentChars = null;
412 if (comment.DocComment) {
413 commentChars = "'''";
418 output.Write (commentChars);
419 string text = comment.Text;
421 for (int i = 0; i < text.Length; i++) {
422 output.Write (text[i]);
423 if (text[i] == '\r') {
424 if (i < (text.Length - 1) && text[i + 1] == '\n') {
427 output.Write (commentChars);
428 } else if (text[i] == '\n') {
429 output.Write (commentChars);
436 protected override void GenerateMethodReturnStatement (CodeMethodReturnStatement statement)
438 TextWriter output = Output;
440 if (statement.Expression != null) {
441 output.Write ("Return ");
442 GenerateExpression (statement.Expression);
445 output.WriteLine ("Return");
449 protected override void GenerateConditionStatement (CodeConditionStatement statement)
451 TextWriter output = Output;
452 output.Write ("If ");
454 GenerateExpression (statement.Condition);
456 output.WriteLine (" Then");
458 GenerateStatements (statement.TrueStatements);
461 CodeStatementCollection falses = statement.FalseStatements;
462 if (falses.Count > 0) {
463 output.WriteLine ("Else");
465 GenerateStatements (falses);
469 if (Options.ElseOnClosing)
470 output.WriteLine ("Else");
472 output.WriteLine ("End If");
475 protected override void GenerateTryCatchFinallyStatement (CodeTryCatchFinallyStatement statement)
477 TextWriter output = Output;
479 output.WriteLine ("Try ");
481 GenerateStatements (statement.TryStatements);
484 foreach (CodeCatchClause clause in statement.CatchClauses) {
485 output.Write ("Catch ");
486 OutputTypeNamePair (clause.CatchExceptionType, clause.LocalName);
489 GenerateStatements (clause.Statements);
493 CodeStatementCollection finallies = statement.FinallyStatements;
494 if (finallies.Count > 0) {
496 output.WriteLine ("Finally");
498 GenerateStatements (finallies);
502 output.WriteLine("End Try");
505 protected override void GenerateAssignStatement (CodeAssignStatement statement)
507 TextWriter output = Output;
508 GenerateExpression (statement.Left);
509 output.Write (" = ");
510 GenerateExpression (statement.Right);
514 protected override void GenerateAttachEventStatement (CodeAttachEventStatement statement)
516 TextWriter output = Output;
518 Output.Write ("AddHandler ");
519 GenerateEventReferenceExpression (statement.Event);
520 Output.Write ( ", ");
521 GenerateExpression (statement.Listener);
525 protected override void GenerateRemoveEventStatement (CodeRemoveEventStatement statement)
527 TextWriter output = Output;
529 Output.Write ("RemoveHandler ");
530 GenerateEventReferenceExpression (statement.Event);
531 Output.Write ( ", ");
532 GenerateExpression (statement.Listener);
536 protected override void GenerateGotoStatement (CodeGotoStatement statement)
538 TextWriter output = Output;
540 output.Write ("goto ");
541 output.Write (statement.Label);
545 protected override void GenerateLabeledStatement (CodeLabeledStatement statement)
547 TextWriter output = Output;
550 output.WriteLine (statement.Label + ":");
552 if (statement.Statement != null) {
553 GenerateStatement (statement.Statement);
557 protected override void GenerateTypeOfExpression (CodeTypeOfExpression e)
559 TextWriter output = Output;
561 output.Write ("GetType(");
566 protected override void GenerateVariableDeclarationStatement( CodeVariableDeclarationStatement statement )
568 TextWriter output = Output;
570 output.Write ("Dim ");
571 OutputTypeNamePair (statement.Type, statement.Name);
573 CodeExpression initExpression = statement.InitExpression;
574 if (initExpression != null)
576 output.Write (" = ");
577 GenerateExpression (initExpression);
583 protected override void GenerateLinePragmaStart (CodeLinePragma linePragma)
586 Output.Write ("#ExternalSource(");
587 Output.Write (linePragma.FileName);
589 Output.Write (linePragma.LineNumber);
590 Output.WriteLine (")");
593 protected override void GenerateLinePragmaEnd (CodeLinePragma linePragma)
595 Output.WriteLine ("#End ExternalSource");
598 protected override void GenerateEvent (CodeMemberEvent eventRef, CodeTypeDeclaration declaration)
600 if (IsCurrentDelegate || IsCurrentEnum) {
604 TextWriter output = Output;
606 OutputAttributes (eventRef.CustomAttributes, null,
607 LineHandling.ContinueLine);
609 OutputMemberAccessModifier (eventRef.Attributes);
611 output.Write ("Event ");
612 OutputTypeNamePair (eventRef.Type, GetEventName(eventRef));
615 if (eventRef.ImplementationTypes.Count > 0) {
616 OutputImplementationTypes (eventRef.ImplementationTypes, eventRef.Name);
617 } else if (eventRef.PrivateImplementationType != null) {
618 output.Write (" Implements ");
619 OutputType (eventRef.PrivateImplementationType);
621 output.Write (eventRef.Name);
628 protected override void GenerateField (CodeMemberField field)
630 if (IsCurrentDelegate || IsCurrentInterface) {
634 TextWriter output = Output;
636 OutputAttributes (field.CustomAttributes, null,
637 LineHandling.ContinueLine);
640 output.Write (field.Name);
642 MemberAttributes attributes = field.Attributes;
643 OutputMemberAccessModifier (attributes);
644 OutputVTableModifier (attributes);
645 OutputFieldScopeModifier (attributes);
646 OutputTypeNamePair (field.Type, field.Name);
649 CodeExpression initExpression = field.InitExpression;
650 if (initExpression != null) {
651 output.Write (" = ");
652 GenerateExpression (initExpression);
658 protected override void GenerateSnippetMember (CodeSnippetTypeMember member)
660 Output.Write (member.Text);
663 protected override void GenerateEntryPointMethod (CodeEntryPointMethod method, CodeTypeDeclaration declaration)
666 OutputAttributes (method.CustomAttributes, null,
667 LineHandling.ContinueLine);
670 Output.WriteLine ("Public Shared Sub Main()");
672 GenerateStatements (method.Statements);
674 Output.WriteLine ("End Sub");
677 [MonoTODO ("partially implemented")]
678 protected override void GenerateMethod (CodeMemberMethod method, CodeTypeDeclaration declaration)
680 if (IsCurrentDelegate || IsCurrentEnum) {
684 bool isSub = method.ReturnType.BaseType == typeof(void).FullName;
686 TextWriter output = Output;
688 OutputAttributes (method.CustomAttributes, null,
689 LineHandling.ContinueLine);
691 MemberAttributes attributes = method.Attributes;
693 if (!IsCurrentInterface) {
694 if (method.PrivateImplementationType == null) {
695 OutputMemberAccessModifier (attributes);
696 if (IsOverloaded (method, declaration)) {
697 output.Write ("Overloads ");
700 OutputVTableModifier (attributes);
701 OutputMemberScopeModifier (attributes);
703 OutputVTableModifier (attributes);
707 output.Write ("Sub ");
709 output.Write ("Function ");
711 output.Write (GetMethodName(method));
713 OutputParameters (method.Parameters);
717 output.Write (" As ");
718 OutputAttributes (method.ReturnTypeCustomAttributes, null,
719 LineHandling.InLine);
720 OutputType (method.ReturnType);
723 if (method.ImplementationTypes.Count > 0) {
724 OutputImplementationTypes (method.ImplementationTypes, method.Name);
725 } else if (method.PrivateImplementationType != null) {
726 output.Write (" Implements ");
727 OutputType (method.PrivateImplementationType);
729 output.Write (method.Name);
733 if (!IsCurrentInterface) {
734 if ((attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
736 GenerateStatements (method.Statements);
739 output.WriteLine ("End Sub");
741 output.WriteLine ("End Function");
746 protected override void GenerateProperty (CodeMemberProperty property, CodeTypeDeclaration declaration)
748 if (IsCurrentDelegate || IsCurrentEnum) {
752 TextWriter output = Output;
754 OutputAttributes (property.CustomAttributes, null,
755 LineHandling.ContinueLine);
757 MemberAttributes attributes = property.Attributes;
759 if (!IsCurrentInterface) {
760 if (property.PrivateImplementationType == null) {
761 OutputMemberAccessModifier (attributes);
762 if (IsOverloaded (property, declaration)) {
763 output.Write ("Overloads ");
766 OutputVTableModifier (attributes);
767 OutputMemberScopeModifier (attributes);
769 OutputVTableModifier (attributes);
772 // mark property as default property if we're dealing with an indexer
773 if (string.Compare (GetPropertyName(property), "Item", true, CultureInfo.InvariantCulture) == 0 && property.Parameters.Count > 0) {
774 output.Write ("Default ");
777 if (property.HasGet && (!property.HasSet))
778 output.Write ("ReadOnly " );
780 if (property.HasSet && (!property.HasGet))
781 output.Write ("WriteOnly " );
783 output.Write ("Property ");
784 Output.Write (GetPropertyName (property));
786 // in .NET 2.0, always output parantheses (whether or not there
787 // are any parameters to output
789 OutputParameters (property.Parameters);
792 if (property.Parameters.Count > 0) {
794 OutputParameters (property.Parameters);
798 Output.Write (" As ");
799 Output.Write (GetTypeOutput(property.Type));
801 if (property.ImplementationTypes.Count > 0) {
802 OutputImplementationTypes (property.ImplementationTypes, property.Name);
803 } else if (property.PrivateImplementationType != null) {
804 output.Write (" Implements ");
805 OutputType (property.PrivateImplementationType);
807 output.Write (property.Name);
812 if (!IsCurrentInterface) {
814 if (property.HasGet) {
815 output.WriteLine ("Get");
817 GenerateStatements (property.GetStatements);
819 output.WriteLine ("End Get");
822 if (property.HasSet) {
823 output.WriteLine ("Set");
825 GenerateStatements (property.SetStatements);
827 output.WriteLine ("End Set");
831 output.WriteLine ("End Property");
835 protected override void GenerateConstructor (CodeConstructor constructor, CodeTypeDeclaration declaration)
837 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
841 OutputAttributes (constructor.CustomAttributes, null,
842 LineHandling.ContinueLine);
843 OutputMemberAccessModifier (constructor.Attributes);
844 Output.Write ("Sub New(");
845 OutputParameters (constructor.Parameters);
846 Output.WriteLine (")");
848 // check if ctor passes args on to other ctor in class
849 CodeExpressionCollection ctorArgs = constructor.ChainedConstructorArgs;
850 if (ctorArgs.Count > 0) {
851 Output.Write ("Me.New(");
852 OutputExpressionList (ctorArgs);
853 Output.WriteLine (")");
855 // check if ctor passes args on to ctor in base class
856 ctorArgs = constructor.BaseConstructorArgs;
857 if (ctorArgs.Count > 0) {
858 Output.Write ("MyBase.New(");
859 OutputExpressionList (ctorArgs);
860 Output.WriteLine (")");
862 } else if (IsCurrentClass) {
866 // call default base ctor
867 Output.WriteLine ("MyBase.New()");
870 GenerateStatements (constructor.Statements);
872 Output.WriteLine ("End Sub");
875 protected override void GenerateTypeConstructor (CodeTypeConstructor constructor)
877 if (IsCurrentDelegate || IsCurrentEnum || IsCurrentInterface) {
882 OutputAttributes (constructor.CustomAttributes, null,
883 LineHandling.ContinueLine);
886 Output.WriteLine ("Shared Sub New()");
888 GenerateStatements (constructor.Statements);
890 Output.WriteLine ("End Sub");
893 [MonoTODO ("not implemented")]
894 protected override void GenerateTypeStart (CodeTypeDeclaration declaration)
896 TextWriter output = Output;
898 OutputAttributes (declaration.CustomAttributes, null,
899 LineHandling.ContinueLine);
901 TypeAttributes attributes = declaration.TypeAttributes;
903 if (IsCurrentDelegate) {
904 CodeTypeDelegate delegateDecl = (CodeTypeDelegate) declaration;
906 if ((attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
907 output.Write ("Public ");
910 bool isSub = delegateDecl.ReturnType.BaseType == typeof (void).FullName;
912 output.Write ("Delegate Sub ");
914 output.Write ("Delegate Function ");
917 output.Write (delegateDecl.Name);
921 Output.Write (" As ");
922 OutputType (delegateDecl.ReturnType);
924 Output.WriteLine ("");
926 OutputTypeAttributes (declaration);
928 output.Write (declaration.Name);
931 if (declaration.BaseTypes.Count > 0) {
932 output.Write (" As ");
933 OutputType (declaration.BaseTypes[0]);
940 bool firstInherits = true;
941 bool firstImplements = true;
943 for (int i = 0; i < declaration.BaseTypes.Count; i++) {
944 // a struct can only implement interfaces
945 // an interface can only inherit from other interface
947 CodeTypeReference typeRef = declaration.BaseTypes[i];
949 if (firstInherits && !declaration.IsStruct && !typeRef.IsInterface) {
951 output.Write ("Inherits ");
952 firstInherits = false;
953 } else if (!declaration.IsInterface && firstImplements) {
955 output.Write ("Implements ");
956 firstImplements = false;
960 OutputType (typeRef);
967 protected override void GenerateTypeEnd (CodeTypeDeclaration declaration)
969 if (IsCurrentDelegate) {
972 string output = string.Empty;
975 if (declaration.IsStruct)
976 output = "End Structure";
977 if (declaration.IsInterface)
978 output = "End Interface";
979 if (declaration.IsEnum)
981 if (declaration.IsClass)
982 output = "End Class";
984 Output.WriteLine (output);
987 protected override void GenerateNamespace(CodeNamespace ns)
989 GenerateCommentStatements (ns.Comments);
991 // add regular imports
992 GenerateNamespaceImports (ns);
995 GenerateNamespaceStart (ns);
997 GenerateNamespaceEnd (ns);
1001 protected override void GenerateNamespaceStart (CodeNamespace ns)
1003 TextWriter output = Output;
1005 string name = ns.Name;
1006 if (name != null && name != string.Empty) {
1007 output.Write ("Namespace ");
1008 output.WriteLine (name);
1013 protected override void GenerateNamespaceEnd (CodeNamespace ns)
1015 string name = ns.Name;
1016 if (name != null && name != string.Empty) {
1018 Output.WriteLine ("End Namespace");
1022 protected override void GenerateNamespaceImport (CodeNamespaceImport import)
1024 TextWriter output = Output;
1026 output.Write ("Imports ");
1027 output.Write (import.Namespace);
1028 output.WriteLine ();
1031 protected override void GenerateAttributeDeclarationsStart (CodeAttributeDeclarationCollection attributes)
1036 protected override void GenerateAttributeDeclarationsEnd (CodeAttributeDeclarationCollection attributes)
1041 private void OutputAttributes (CodeAttributeDeclarationCollection attributes, string prefix, LineHandling lineHandling) {
1042 if (attributes.Count == 0) {
1046 GenerateAttributeDeclarationsStart (attributes);
1048 IEnumerator enumerator = attributes.GetEnumerator ();
1049 if (enumerator.MoveNext ()) {
1050 CodeAttributeDeclaration att = (CodeAttributeDeclaration) enumerator.Current;
1051 if (prefix != null) {
1052 Output.Write (prefix);
1054 OutputAttributeDeclaration (att);
1056 while (enumerator.MoveNext ()) {
1057 Output.Write (", ");
1058 if (lineHandling != LineHandling.InLine) {
1059 ContinueOnNewLine ("");
1062 att = (CodeAttributeDeclaration) enumerator.Current;
1063 if (prefix != null) {
1064 Output.Write (prefix);
1066 OutputAttributeDeclaration (att);
1069 GenerateAttributeDeclarationsEnd (attributes);
1072 switch (lineHandling) {
1073 case LineHandling.ContinueLine:
1074 ContinueOnNewLine ("");
1076 case LineHandling.NewLine:
1077 Output.WriteLine ();
1082 protected override void OutputAttributeArgument (CodeAttributeArgument argument)
1084 string name = argument.Name;
1085 if (name != null && name.Length > 0) {
1086 Output.Write (name);
1087 Output.Write (":=");
1089 GenerateExpression (argument.Value);
1092 private void OutputAttributeDeclaration (CodeAttributeDeclaration attribute)
1094 Output.Write (attribute.Name.Replace ('+', '.'));
1096 IEnumerator enumerator = attribute.Arguments.GetEnumerator ();
1097 if (enumerator.MoveNext ()) {
1098 CodeAttributeArgument argument = (CodeAttributeArgument) enumerator.Current;
1099 OutputAttributeArgument (argument);
1101 while (enumerator.MoveNext ()) {
1102 Output.Write (", ");
1103 argument = (CodeAttributeArgument) enumerator.Current;
1104 OutputAttributeArgument (argument);
1110 protected override void OutputDirection (FieldDirection direction)
1112 switch (direction) {
1113 case FieldDirection.In:
1114 Output.Write ("ByVal ");
1116 case FieldDirection.Out:
1117 case FieldDirection.Ref:
1118 Output.Write ("ByRef ");
1123 protected override void OutputFieldScopeModifier (MemberAttributes attributes)
1125 switch (attributes & MemberAttributes.ScopeMask) {
1126 case MemberAttributes.Static:
1127 Output.Write ("Shared ");
1129 case MemberAttributes.Const:
1130 Output.Write ("Const ");
1135 private void OutputImplementationTypes (CodeTypeReferenceCollection implementationTypes, string member)
1137 IEnumerator enumerator = implementationTypes.GetEnumerator ();
1138 if (enumerator.MoveNext ()) {
1139 Output.Write (" Implements ");
1141 CodeTypeReference typeReference = (CodeTypeReference) enumerator.Current;
1142 OutputType (typeReference);
1144 OutputIdentifier (member);
1146 while (enumerator.MoveNext ()) {
1147 Output.Write (" , ");
1148 typeReference = (CodeTypeReference) enumerator.Current;
1149 OutputType (typeReference);
1151 OutputIdentifier (member);
1156 protected override void OutputMemberAccessModifier (MemberAttributes attributes)
1158 switch (attributes & MemberAttributes.AccessMask) {
1159 case MemberAttributes.Assembly:
1160 case MemberAttributes.FamilyAndAssembly:
1161 Output.Write ("Friend ");
1163 case MemberAttributes.Family:
1164 Output.Write ("Protected ");
1166 case MemberAttributes.FamilyOrAssembly:
1167 Output.Write ("Protected Friend ");
1169 case MemberAttributes.Private:
1170 Output.Write ("Private ");
1172 case MemberAttributes.Public:
1173 Output.Write ("Public ");
1178 private void OutputVTableModifier (MemberAttributes attributes)
1180 if ((attributes & MemberAttributes.VTableMask) == MemberAttributes.New) {
1181 Output.Write ("Shadows ");
1185 protected override void OutputMemberScopeModifier (MemberAttributes attributes)
1187 switch (attributes & MemberAttributes.ScopeMask) {
1188 case MemberAttributes.Abstract:
1189 Output.Write ("MustOverride ");
1191 case MemberAttributes.Final:
1194 case MemberAttributes.Static:
1195 Output.Write ("Shared ");
1197 case MemberAttributes.Override:
1198 Output.Write ("Overrides ");
1200 case MemberAttributes.Overloaded:
1201 // based on http://gendotnet.com/Code%20Gen%20Articles/codedom.htm
1202 Output.Write ("Overloads ");
1204 MemberAttributes access_ovl = attributes & MemberAttributes.AccessMask;
1205 if (access_ovl == MemberAttributes.Public || access_ovl == MemberAttributes.Family) {
1206 Output.Write ("Overridable ");
1211 // FUNNY! if the scope value is
1212 // rubbish (0 or >Const), and access
1213 // is public, protected make it
1216 // i'm not sure whether this is 100%
1217 // correct, but it seems to be MS
1220 // On MS.NET 2.0, internal properties
1221 // are also marked "virtual".
1223 MemberAttributes access = attributes & MemberAttributes.AccessMask;
1224 if (access == MemberAttributes.Public ||
1226 access == MemberAttributes.Family || access == MemberAttributes.Assembly)
1228 access == MemberAttributes.Family)
1230 Output.Write ("Overridable ");
1235 protected override void OutputOperator (CodeBinaryOperatorType op)
1238 case CodeBinaryOperatorType.Add:
1241 case CodeBinaryOperatorType.Subtract:
1244 case CodeBinaryOperatorType.Multiply:
1247 case CodeBinaryOperatorType.Divide:
1250 case CodeBinaryOperatorType.Modulus:
1251 Output.Write ("Mod");
1253 case CodeBinaryOperatorType.Assign:
1256 case CodeBinaryOperatorType.IdentityInequality:
1257 Output.Write ("<>");
1259 case CodeBinaryOperatorType.IdentityEquality:
1260 Output.Write ("Is");
1262 case CodeBinaryOperatorType.ValueEquality:
1265 case CodeBinaryOperatorType.BitwiseOr:
1266 Output.Write ("Or");
1268 case CodeBinaryOperatorType.BitwiseAnd:
1269 Output.Write ("And");
1271 case CodeBinaryOperatorType.BooleanOr:
1272 Output.Write ("OrElse");
1274 case CodeBinaryOperatorType.BooleanAnd:
1275 Output.Write ("AndAlso");
1277 case CodeBinaryOperatorType.LessThan:
1280 case CodeBinaryOperatorType.LessThanOrEqual:
1281 Output.Write ("<=");
1283 case CodeBinaryOperatorType.GreaterThan:
1286 case CodeBinaryOperatorType.GreaterThanOrEqual:
1287 Output.Write (">=");
1292 private void OutputTypeAttributes (CodeTypeDeclaration declaration)
1294 TextWriter output = Output;
1295 TypeAttributes attributes = declaration.TypeAttributes;
1297 switch (attributes & TypeAttributes.VisibilityMask) {
1298 case TypeAttributes.Public:
1299 case TypeAttributes.NestedPublic:
1300 output.Write ("Public ");
1302 case TypeAttributes.NestedPrivate:
1303 output.Write ("Private ");
1306 case TypeAttributes.NotPublic:
1307 case TypeAttributes.NestedFamANDAssem:
1308 case TypeAttributes.NestedAssembly:
1309 output.Write ("Friend ");
1311 case TypeAttributes.NestedFamily:
1312 output.Write ("Protected ");
1314 case TypeAttributes.NestedFamORAssem:
1315 output.Write ("Protected Friend ");
1320 if (declaration.IsStruct) {
1321 output.Write ("Structure ");
1322 } else if (declaration.IsEnum) {
1323 output.Write ("Enum ");
1325 if ((attributes & TypeAttributes.Interface) != 0) {
1326 output.Write ("Interface ");
1328 if ((attributes & TypeAttributes.Sealed) != 0)
1329 output.Write ("NotInheritable ");
1331 if ((attributes & TypeAttributes.Abstract) != 0)
1332 output.Write ("MustInherit ");
1334 output.Write ("Class ");
1339 protected override void OutputTypeNamePair (CodeTypeReference typeRef, String name)
1342 if (name.Length == 0) {
1343 name = "__exception";
1346 Output.Write (CreateEscapedIdentifier(name) + " As " + GetTypeOutput (typeRef));
1349 protected override void OutputType (CodeTypeReference type)
1351 Output.Write (GetTypeOutput (type));
1354 protected override string QuoteSnippetString (string value)
1356 StringBuilder mySBuilder = new StringBuilder(value.Length);
1357 mySBuilder.Append ("\"");
1358 bool inQuotes = true;
1359 for (int MyCounter = 0; MyCounter < value.Length; MyCounter++)
1361 if (value[MyCounter] == 34) //quotation mark
1365 mySBuilder.Append ("&\"");
1368 mySBuilder.Append (value[MyCounter]);
1369 mySBuilder.Append (value[MyCounter]);
1371 else if (value[MyCounter] >= 32) //standard ansi/unicode characters
1375 mySBuilder.Append ("&\"");
1378 mySBuilder.Append (value[MyCounter]);
1380 else //special chars, e.g. line break
1384 mySBuilder.Append ("\"");
1387 mySBuilder.Append ("&Microsoft.VisualBasic.ChrW(");
1388 mySBuilder.Append ((int)value[MyCounter]);
1389 mySBuilder.Append (")");
1393 mySBuilder.Append ("\"");
1394 return mySBuilder.ToString();
1397 private void GenerateMemberReferenceExpression (CodeExpression targetObject, string memberName)
1399 GenerateExpression (targetObject);
1401 Output.Write (memberName);
1408 protected override string CreateEscapedIdentifier (string value)
1410 for (int x = 0; x < Keywords.Length; x++)
1411 if (value.ToLower().Equals (Keywords[x].ToLower()))
1412 return "[" + value + "]";
1416 protected override string CreateValidIdentifier (string value)
1418 for (int x = 0; x < Keywords.Length; x++)
1419 if (value.ToLower().Equals (Keywords[x].ToLower()))
1424 protected override string GetTypeOutput (CodeTypeReference type)
1427 CodeTypeReference arrayType;
1429 arrayType = type.ArrayElementType;
1430 if (arrayType != null)
1431 output = GetTypeOutput (arrayType);
1433 switch (type.BaseType) {
1434 case "System.DateTime":
1437 case "System.Decimal":
1440 case "System.Double":
1443 case "System.Single":
1449 case "System.Int32":
1452 case "System.Int64":
1455 case "System.Int16":
1458 case "System.Boolean":
1464 case "System.String":
1467 case "System.Object":
1471 case "System.SByte":
1474 case "System.UInt16":
1477 case "System.UInt32":
1478 output = "UInteger";
1480 case "System.UInt64":
1485 output = type.BaseType.Replace('+', '.');
1490 int rank = type.ArrayRank;
1493 for (--rank; rank > 0; --rank)
1501 protected override bool IsValidIdentifier (string identifier)
1503 for (int x = 0; x < Keywords.Length; x++)
1504 if (identifier.ToLower().Equals (Keywords[x].ToLower()))
1509 protected override bool Supports (GeneratorSupport supports)
1514 private bool IsOverloaded (CodeMemberProperty property, CodeTypeDeclaration type)
1516 if ((property.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1520 foreach (CodeTypeMember member in type.Members) {
1521 CodeMemberProperty p = member as CodeMemberProperty;
1523 // member is not a property
1527 if (p != property && p.Name == property.Name && p.PrivateImplementationType == null) {
1534 private bool IsOverloaded (CodeMemberMethod method, CodeTypeDeclaration type)
1536 if ((method.Attributes & MemberAttributes.Overloaded) == MemberAttributes.Overloaded) {
1540 foreach (CodeTypeMember member in type.Members) {
1541 CodeMemberMethod m = member as CodeMemberMethod;
1543 // member is not a method
1547 if (!(m is CodeTypeConstructor) && !(m is CodeConstructor) && m != method && m.Name == method.Name && m.PrivateImplementationType == null) {
1554 private string GetEventName (CodeMemberEvent evt)
1557 if (evt.PrivateImplementationType == null) {
1561 string baseType = evt.PrivateImplementationType.BaseType.Replace ('.', '_');
1562 return baseType + "_" + evt.Name;
1568 private string GetMethodName (CodeMemberMethod method)
1570 if (method.PrivateImplementationType == null) {
1574 string baseType = method.PrivateImplementationType.BaseType.Replace ('.', '_');
1575 return baseType + "_" + method.Name;
1578 private string GetPropertyName (CodeMemberProperty property)
1580 if (property.PrivateImplementationType == null) {
1581 return property.Name;
1584 string baseType = property.PrivateImplementationType.BaseType.Replace ('.', '_');
1585 return baseType + "_" + property.Name;
1588 private enum LineHandling