From 94d339bf97eb4f5c3b5dbcbcaf11b1280fc42d7a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 26 Feb 2006 14:57:00 +0000 Subject: [PATCH] Improved VB -> C# converter. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1187 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Visitors/VBNetConstructsConvertVisitor.cs | 89 +++++++++++++++++++ .../Output/CSharp/VBToCSharpConverterTest.cs | 42 +++++++++ .../ProjectBrowser/ProjectBrowserControl.cs | 8 +- .../Pads/ProjectBrowser/ProjectBrowserPad.cs | 12 +++ .../ProjectBrowser/ProjectBrowserPanel.cs | 6 ++ .../Project/Converter/LanguageConverter.cs | 3 + 6 files changed, 159 insertions(+), 1 deletion(-) diff --git a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs index 70e6e2fd81..a247735e61 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs @@ -10,6 +10,7 @@ using System.Text; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Reflection; using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Parser.VB; @@ -27,6 +28,8 @@ namespace ICSharpCode.NRefactory.Parser // MyBase.New() and MyClass.New() calls inside the constructor are converted to :base() and :this() // Add Public Modifier to methods and properties // Override Finalize => Destructor + // IIF(cond, true, false) => ConditionalExpression + // Built-in methods => Prefix with class name // The following conversions should be implemented in the future: // Function A() \n A = SomeValue \n End Function -> convert to return statement @@ -198,5 +201,91 @@ namespace ICSharpCode.NRefactory.Parser return base.Visit(propertyDeclaration, data); } + + static volatile Dictionary constantTable; + static volatile Dictionary methodTable; + + public static readonly string VBAssemblyName = "Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; + + static Dictionary CreateDictionary(params string[] classNames) + { + Dictionary d = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + Assembly asm = Assembly.Load(VBAssemblyName); + foreach (string className in classNames) { + Type type = asm.GetType("Microsoft.VisualBasic." + className); + Expression expr = new IdentifierExpression(className); + foreach (MemberInfo member in type.GetMembers()) { + if (member.DeclaringType == type) { // only direct members + d[member.Name] = expr; + } + } + } + return d; + } + + public override object Visit(IdentifierExpression identifierExpression, object data) + { + if (constantTable == null) { + constantTable = CreateDictionary("Constants"); + } + Expression expr; + if (constantTable.TryGetValue(identifierExpression.Identifier, out expr)) { + FieldReferenceExpression fre = new FieldReferenceExpression(expr, identifierExpression.Identifier); + ReplaceCurrentNode(fre); + return base.Visit(fre, data); + } + return base.Visit(identifierExpression, data); + } + + public override object Visit(InvocationExpression invocationExpression, object data) + { + IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression; + if (ident != null) { + if ("IIF".Equals(ident.Identifier, StringComparison.InvariantCultureIgnoreCase) + && invocationExpression.Arguments.Count == 3) + { + ConditionalExpression ce = new ConditionalExpression(invocationExpression.Arguments[0], + invocationExpression.Arguments[1], + invocationExpression.Arguments[2]); + ReplaceCurrentNode(new ParenthesizedExpression(ce)); + return base.Visit(ce, data); + } + if ("IsNothing".Equals(ident.Identifier, StringComparison.InvariantCultureIgnoreCase) + && invocationExpression.Arguments.Count == 1) + { + BinaryOperatorExpression boe = new BinaryOperatorExpression(invocationExpression.Arguments[0], + BinaryOperatorType.ReferenceEquality, + new PrimitiveExpression(null, "null")); + ReplaceCurrentNode(new ParenthesizedExpression(boe)); + return base.Visit(boe, data); + } + if (methodTable == null) { + methodTable = CreateDictionary("Conversion", "FileSystem", "Financial", "Information", + "Interaction", "Strings", "VBMath"); + } + Expression expr; + if (methodTable.TryGetValue(ident.Identifier, out expr)) { + FieldReferenceExpression fre = new FieldReferenceExpression(expr, ident.Identifier); + invocationExpression.TargetObject = fre; + } + } + return base.Visit(invocationExpression, data); + } + + public override object Visit(UnaryOperatorExpression unaryOperatorExpression, object data) + { + base.Visit(unaryOperatorExpression, data); + if (unaryOperatorExpression.Op == UnaryOperatorType.Not) { + ParenthesizedExpression pe = unaryOperatorExpression.Expression as ParenthesizedExpression; + if (pe != null) { + BinaryOperatorExpression boe = pe.Expression as BinaryOperatorExpression; + if (boe != null && boe.Op == BinaryOperatorType.ReferenceEquality) { + boe.Op = BinaryOperatorType.ReferenceInequality; + ReplaceCurrentNode(pe); + } + } + } + return null; + } } } diff --git a/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs b/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs index 0448885f16..d910543fb1 100644 --- a/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs +++ b/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs @@ -188,5 +188,47 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "\tDead();\n" + "}"); } + + [Test] + public void IIFExpression() + { + TestStatement("a = iif(cond, trueEx, falseEx)", + "a = (cond ? trueEx : falseEx);"); + } + + [Test] + public void IsNothing() + { + TestStatement("a = IsNothing(ex)", + "a = (ex == null);"); + } + + [Test] + public void IsNotNothing() + { + TestStatement("a = Not IsNothing(ex)", + "a = (ex != null);"); + } + + [Test] + public void CompatibilityMethods() + { + TestStatement("Beep()", + "Interaction.Beep();"); + } + + [Test] + public void EqualsCall() + { + TestStatement("Equals(a, b)", + "Equals(a, b);"); + } + + [Test] + public void VBConstants() + { + TestStatement("a = vbYesNo", + "a = Constants.vbYesNo;"); + } } } diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs index 78472fa2cc..fbf40b329e 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs @@ -47,6 +47,12 @@ namespace ICSharpCode.SharpDevelop.Project } } + public AbstractProjectBrowserTreeNode RootNode { + get { + return treeView.Nodes[0] as AbstractProjectBrowserTreeNode; + } + } + public ExtTreeView TreeView { get { return treeView; @@ -140,7 +146,7 @@ namespace ICSharpCode.SharpDevelop.Project return FindFileNode(treeView.Nodes, fileName); } - // stores the fileName of the last selected target so + // stores the fileName of the last selected target so // that we can select it again on opening a folder string lastSelectionTarget; diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPad.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPad.cs index 44bc2b8a86..2051b9dd1e 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPad.cs @@ -20,6 +20,9 @@ namespace ICSharpCode.SharpDevelop.Project static ProjectBrowserPad instance; public static ProjectBrowserPad Instance { get { + if (instance == null) { + WorkbenchSingleton.Workbench.GetPad(typeof(ProjectBrowserPad)).CreatePad(); + } return instance; } } @@ -31,6 +34,15 @@ namespace ICSharpCode.SharpDevelop.Project } } + /// + /// Gets the root node of the project tree view. + /// + public AbstractProjectBrowserTreeNode SolutionNode { + get { + return projectBrowserPanel.RootNode; + } + } + public ProjectBrowserControl ProjectBrowserControl { get { return projectBrowserPanel.ProjectBrowserControl; diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPanel.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPanel.cs index 7b911c1a3f..10beeeddce 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPanel.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserPanel.cs @@ -29,6 +29,12 @@ namespace ICSharpCode.SharpDevelop.Project } } + public AbstractProjectBrowserTreeNode RootNode { + get { + return projectBrowserControl.RootNode; + } + } + public ProjectBrowserControl ProjectBrowserControl { get { return projectBrowserControl; diff --git a/src/Main/Base/Project/Src/Project/Converter/LanguageConverter.cs b/src/Main/Base/Project/Src/Project/Converter/LanguageConverter.cs index 1951183b76..afcc81c005 100644 --- a/src/Main/Base/Project/Src/Project/Converter/LanguageConverter.cs +++ b/src/Main/Base/Project/Src/Project/Converter/LanguageConverter.cs @@ -140,6 +140,9 @@ namespace ICSharpCode.SharpDevelop.Project.Converter targetProject.Save(); targetProject.Dispose(); TreeNode node = ProjectBrowserPad.Instance.SelectedNode; + if (node == null) { + node = ProjectBrowserPad.Instance.SolutionNode; + } while (node != null) { if (node is ISolutionFolderNode) { AddExitingProjectToSolution.AddProject((ISolutionFolderNode)node, targetProject.FileName);