diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs index 4c8405f305..509a91cc63 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs @@ -50,7 +50,7 @@ namespace VBNetBinding PreprocessingDirective.CSharpToVB(specials); IProjectContent pc = ParserService.GetProjectContent(sourceItem.Project) ?? ParserService.CurrentProjectContent; CSharpToVBNetConvertVisitor visitor = new CSharpToVBNetConvertVisitor(pc, ParserService.GetParseInformation(sourceItem.FileName)); - visitor.RootNamespaceToStrip = sourceItem.Project.RootNamespace; + visitor.RootNamespaceToRemove = sourceItem.Project.RootNamespace; visitor.DefaultImportsToRemove = defaultImports; if (sourceItem.Project is MSBuildBasedProject) { visitor.StartupObjectToMakePublic = startupObject; diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs index feb0b2fd2c..f765d99c75 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -2340,7 +2340,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter public override object TrackedVisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) { - UnsupportedNode(anonymousMethodExpression); + OutputAnonymousMethodWithStatementBody(anonymousMethodExpression.Parameters, anonymousMethodExpression.Body); return null; } @@ -2364,12 +2364,12 @@ namespace ICSharpCode.NRefactory.PrettyPrinter public override object TrackedVisitCastExpression(CastExpression castExpression, object data) { - if (castExpression.CastType == CastType.Cast) { - return PrintCast(Tokens.DirectCast, castExpression); - } if (castExpression.CastType == CastType.TryCast) { return PrintCast(Tokens.TryCast, castExpression); } + if (castExpression.CastType == CastType.Cast || castExpression.CastTo.IsArrayType) { + return PrintCast(Tokens.DirectCast, castExpression); + } switch (castExpression.CastTo.SystemType) { case "System.Boolean": outputFormatter.PrintToken(Tokens.CBool); @@ -2690,7 +2690,41 @@ namespace ICSharpCode.NRefactory.PrettyPrinter public override object TrackedVisitLambdaExpression(LambdaExpression lambdaExpression, object data) { - throw new NotImplementedException(); + if (!lambdaExpression.ExpressionBody.IsNull) { + outputFormatter.PrintToken(Tokens.Function); + outputFormatter.PrintToken(Tokens.OpenParenthesis); + AppendCommaSeparatedList(lambdaExpression.Parameters); + outputFormatter.PrintToken(Tokens.CloseParenthesis); + outputFormatter.Space(); + return lambdaExpression.ExpressionBody.AcceptVisitor(this, data); + } else { + OutputAnonymousMethodWithStatementBody(lambdaExpression.Parameters, lambdaExpression.StatementBody); + return null; + } + } + + void OutputAnonymousMethodWithStatementBody(List parameters, BlockStatement body) + { + Error("VB does not support anonymous methods/lambda expressions with a statement body", body.StartLocation); + + outputFormatter.PrintToken(Tokens.Function); + outputFormatter.PrintToken(Tokens.OpenParenthesis); + AppendCommaSeparatedList(parameters); + outputFormatter.PrintToken(Tokens.CloseParenthesis); + outputFormatter.Space(); + outputFormatter.PrintToken(Tokens.Do); + outputFormatter.NewLine(); + + ++outputFormatter.IndentationLevel; + exitTokenStack.Push(Tokens.Function); + body.AcceptVisitor(this, null); + exitTokenStack.Pop(); + --outputFormatter.IndentationLevel; + + outputFormatter.Indent(); + outputFormatter.PrintToken(Tokens.End); + outputFormatter.Space(); + outputFormatter.PrintToken(Tokens.Function); } public override object TrackedVisitQueryExpression(QueryExpression queryExpression, object data) diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs index a819eb0590..1517fa4177 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs @@ -72,6 +72,10 @@ namespace ICSharpCode.NRefactory.Visitors public override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) { BinaryOperatorExpression boe = ifElseStatement.Condition as BinaryOperatorExpression; + // the BinaryOperatorExpression might be inside a ParenthesizedExpression + if (boe == null && ifElseStatement.Condition is ParenthesizedExpression) { + boe = (ifElseStatement.Condition as ParenthesizedExpression).Expression as BinaryOperatorExpression; + } if (ifElseStatement.ElseIfSections.Count == 0 && ifElseStatement.FalseStatement.Count == 0 && ifElseStatement.TrueStatement.Count == 1 @@ -80,9 +84,7 @@ namespace ICSharpCode.NRefactory.Visitors && (IsNullLiteralExpression(boe.Left) || IsNullLiteralExpression(boe.Right)) ) { - IdentifierExpression ident = boe.Left as IdentifierExpression; - if (ident == null) - ident = boe.Right as IdentifierExpression; + string ident = GetPossibleEventName(boe.Left) ?? GetPossibleEventName(boe.Right); ExpressionStatement se = ifElseStatement.TrueStatement[0] as ExpressionStatement; if (se == null) { BlockStatement block = ifElseStatement.TrueStatement[0] as BlockStatement; @@ -92,17 +94,25 @@ namespace ICSharpCode.NRefactory.Visitors } if (ident != null && se != null) { InvocationExpression ie = se.Expression as InvocationExpression; - if (ie != null && - ie.TargetObject is IdentifierExpression && - (ie.TargetObject as IdentifierExpression).Identifier == ident.Identifier) - { - ReplaceCurrentNode(new RaiseEventStatement(ident.Identifier, ie.Arguments)); + if (ie != null && GetPossibleEventName(ie.TargetObject) == ident) { + ReplaceCurrentNode(new RaiseEventStatement(ident, ie.Arguments)); } } } return base.VisitIfElseStatement(ifElseStatement, data); } + string GetPossibleEventName(Expression expression) + { + IdentifierExpression ident = expression as IdentifierExpression; + if (ident != null) + return ident.Identifier; + FieldReferenceExpression fre = expression as FieldReferenceExpression; + if (fre != null && fre.TargetObject is ThisReferenceExpression) + return fre.FieldName; + return null; + } + public override object VisitForStatement(ForStatement forStatement, object data) { base.VisitForStatement(forStatement, data); @@ -202,8 +212,9 @@ namespace ICSharpCode.NRefactory.Visitors public override object VisitCastExpression(CastExpression castExpression, object data) { if (castExpression.CastType == CastType.Cast) { - // Casts to value types are marked as conversions - // currently only supporting primitive types... + // Casts to value types are marked as conversions + // this code only supports primitive types, user-defined value types are handled by + // the DOM-aware CSharpToVBNetConvertVisitor string type; if (TypeReference.PrimitiveTypesCSharpReverse.TryGetValue(castExpression.CastTo.SystemType, out type)) { if (type != "object" && type != "string") { diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs b/src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs index a8d3f9ee68..b9e50a0217 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs @@ -6,6 +6,7 @@ // using System; +using ICSharpCode.NRefactory.Ast; namespace ICSharpCode.NRefactory.Visitors { @@ -14,6 +15,14 @@ namespace ICSharpCode.NRefactory.Visitors /// public class ConvertVisitorBase : AbstractAstTransformer { - + // inserting before current position is not allowed in a Transformer + // but inserting after it is possible + protected void InsertAfterSibling(INode sibling, INode newNode) + { + if (sibling == null || sibling.Parent == null) return; + int index = sibling.Parent.Children.IndexOf(sibling); + sibling.Parent.Children.Insert(index + 1, newNode); + newNode.Parent = sibling.Parent; + } } } diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs index aa53f97786..24b3b0220c 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs @@ -41,16 +41,6 @@ namespace ICSharpCode.NRefactory.Visitors return base.VisitEventDeclaration(eventDeclaration, data); } - // inserting before current position is not allowed in a Transformer - // but inserting after it is possible - void InsertAfterSibling(INode sibling, INode newNode) - { - if (sibling == null || sibling.Parent == null) return; - int index = sibling.Parent.Children.IndexOf(sibling); - sibling.Parent.Children.Insert(index + 1, newNode); - newNode.Parent = sibling.Parent; - } - public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { ConvertInterfaceImplementation(methodDeclaration); diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs index 22e6abab4d..537613e8ab 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs @@ -105,25 +105,6 @@ namespace ICSharpCode.NRefactory.Visitors return base.VisitDelegateDeclaration(delegateDeclaration, data); } - string GetAnonymousMethodName() - { - for (int i = 1;; i++) { - string name = "ConvertedAnonymousMethod" + i; - bool ok = true; - if (currentType != null) { - foreach (object c in currentType.Children) { - MethodDeclaration method = c as MethodDeclaration; - if (method != null && method.Name == name) { - ok = false; - break; - } - } - } - if (ok) - return name; - } - } - public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) { base.VisitExpressionStatement(expressionStatement, data); @@ -151,17 +132,16 @@ namespace ICSharpCode.NRefactory.Visitors public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) { - MethodDeclaration method = new MethodDeclaration { - Name = GetAnonymousMethodName(), - Modifier = Modifiers.Private, - TypeReference = new TypeReference("System.Void"), - Parameters = anonymousMethodExpression.Parameters, - Body = anonymousMethodExpression.Body - }; - if (currentType != null) { - currentType.Children.Add(method); + base.VisitAnonymousMethodExpression(anonymousMethodExpression, data); + if (anonymousMethodExpression.Body.Children.Count == 1) { + ReturnStatement rs = anonymousMethodExpression.Body.Children[0] as ReturnStatement; + if (rs != null) { + LambdaExpression lambda = new LambdaExpression(); + lambda.ExpressionBody = rs.Expression; + lambda.Parameters = anonymousMethodExpression.Parameters; + ReplaceCurrentNode(lambda); + } } - ReplaceCurrentNode(new AddressOfExpression(new IdentifierExpression(method.Name))); return null; } diff --git a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs index 60a46986e5..60890ad1b6 100644 --- a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs +++ b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs @@ -153,8 +153,16 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter { TestStatement("if (MyEvent != null) MyEvent(this, EventArgs.Empty);", "RaiseEvent MyEvent(Me, EventArgs.Empty)"); + TestStatement("if ((MyEvent != null)) MyEvent(this, EventArgs.Empty);", + "RaiseEvent MyEvent(Me, EventArgs.Empty)"); TestStatement("if (null != MyEvent) { MyEvent(this, EventArgs.Empty); }", "RaiseEvent MyEvent(Me, EventArgs.Empty)"); + TestStatement("if (this.MyEvent != null) MyEvent(this, EventArgs.Empty);", + "RaiseEvent MyEvent(Me, EventArgs.Empty)"); + TestStatement("if (MyEvent != null) this.MyEvent(this, EventArgs.Empty);", + "RaiseEvent MyEvent(Me, EventArgs.Empty)"); + TestStatement("if ((this.MyEvent != null)) { this.MyEvent(this, EventArgs.Empty); }", + "RaiseEvent MyEvent(Me, EventArgs.Empty)"); } [Test] @@ -187,31 +195,14 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "End If"); } - /* [Test] public void AnonymousMethod() - { - TestMember("void A() { someEvent += delegate(int argument) { return argument * 2; }; }", - "Private Sub A()\n" + - "\tAddHandler someEvent, AddressOf ConvertedAnonymousMethod1\n" + - "End Sub\n" + - "Private Sub ConvertedAnonymousMethod1(ByVal argument As Integer)\n" + - "\tReturn argument * 2\n" + - "End Sub"); - } - - [Test, Ignore("NRefactory cannot guess the anonymous method's return type")] - public void AnonymousMethodInVarDeclaration() { TestMember("void A() { Converter i = delegate(int argument) { return argument * 2; }; }", "Private Sub A()\n" + - "\tDim i As Converter(Of Integer, Integer) = AddressOf ConvertedAnonymousMethod1\n" + - "End Sub\n" + - "Private Function ConvertedAnonymousMethod1(ByVal argument As Integer) As Integer\n" + - "\tReturn argument * 2\n" + - "End Function"); + "\tDim i As Converter(Of Integer, Integer) = Function(ByVal argument As Integer) argument * 2\n" + + "End Sub"); } - */ [Test] public void StaticMethod() @@ -460,6 +451,17 @@ End Class "Dim i As String(,) = New String(5, 5) {}"); } + [Test] + public void ArrayCast() + { + TestStatement("string[] i = (string[])obj;", + "Dim i As String() = DirectCast(obj, String())"); + + // ensure the converter does not use CInt: + TestStatement("int[] i = (int[])obj;", + "Dim i As Integer() = DirectCast(obj, Integer())"); + } + [Test] public void InlineAssignment() { diff --git a/src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs b/src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs index 666ba82ab9..261c4d896b 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs @@ -47,20 +47,22 @@ namespace ICSharpCode.SharpDevelop.Project engine.GlobalProperties.SetProperty("Platform", ptb.platform); } - Microsoft.Build.BuildEngine.Project project = buildRun.LoadProject(engine, ptb.file); - if (project == null) { - LoggingService.Debug("Error loading " + ptb.file); - return false; - } - foreach (string additionalTargetFile in MSBuildEngine.AdditionalTargetFiles) { - project.AddNewImport(additionalTargetFile, null); - } - bool success; - if (string.IsNullOrEmpty(ptb.targets)) { - success = engine.BuildProject(project); - } else { - success = engine.BuildProject(project, ptb.targets.Split(';')); + lock (MSBuildInternals.InProcessMSBuildLock) { + Microsoft.Build.BuildEngine.Project project = buildRun.LoadProject(engine, ptb.file); + if (project == null) { + LoggingService.Debug("Error loading " + ptb.file); + return false; + } + foreach (string additionalTargetFile in MSBuildEngine.AdditionalTargetFiles) { + project.AddNewImport(additionalTargetFile, null); + } + + if (string.IsNullOrEmpty(ptb.targets)) { + success = engine.BuildProject(project); + } else { + success = engine.BuildProject(project, ptb.targets.Split(';')); + } } logger.FlushCurrentError(); diff --git a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs index ee7dee033a..e92512fafb 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs @@ -26,6 +26,12 @@ namespace ICSharpCode.SharpDevelop.Project /// public static class MSBuildInternals { + /// + /// MSBuild does not support multi-threading, so every invocation of MSBuild that + /// runs inside the SharpDevelop process must lock on this object to prevent conflicts. + /// + public readonly static object InProcessMSBuildLock = new object(); + const string MSBuildXmlNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"; #region Escaping @@ -354,9 +360,11 @@ namespace ICSharpCode.SharpDevelop.Project #endif //Environment.CurrentDirectory = Path.GetDirectoryName(tempProject.FullFileName); - if (!tempProject.Build("ResolveAssemblyReferences")) { - LoggingService.Warn("ResolveAssemblyReferences exited with error"); - return; + lock (MSBuildInternals.InProcessMSBuildLock) { + if (!tempProject.Build("ResolveAssemblyReferences")) { + LoggingService.Warn("ResolveAssemblyReferences exited with error"); + return; + } } foreach (MSBuild.BuildItem item in tempProject.GetEvaluatedItemsByName("_ResolveAssemblyReferenceResolvedFiles")) { diff --git a/src/Main/Base/Project/Src/Util/ProcessRunner.cs b/src/Main/Base/Project/Src/Util/ProcessRunner.cs index 5eeb878f29..d2294d6073 100644 --- a/src/Main/Base/Project/Src/Util/ProcessRunner.cs +++ b/src/Main/Base/Project/Src/Util/ProcessRunner.cs @@ -19,6 +19,7 @@ namespace ICSharpCode.SharpDevelop.Util /// public class ProcessRunner : IDisposable { + readonly object lockObj = new object(); Process process; string standardOutput = String.Empty; string workingDirectory = String.Empty; @@ -97,7 +98,7 @@ namespace ICSharpCode.SharpDevelop.Util /// Gets the process exit code. /// public int ExitCode { - get { + get { int exitCode = 0; if (process != null) { exitCode = process.ExitCode; @@ -118,7 +119,7 @@ namespace ICSharpCode.SharpDevelop.Util /// Waits for the process to exit. /// /// A timeout in milliseconds. - /// if the associated process has + /// if the associated process has /// exited; otherwise, public bool WaitForExit(int timeout) { @@ -155,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Util /// The command line arguments to /// pass to the command. public void Start(string command, string arguments) - { + { process = new Process(); process.StartInfo.CreateNoWindow = true; process.StartInfo.FileName = command; @@ -170,30 +171,32 @@ namespace ICSharpCode.SharpDevelop.Util process.Exited += OnProcessExited; } - bool started = false; - try { - process.Start(); - started = true; - } finally { - if (!started) { - process.Exited -= OnProcessExited; - process = null; + lock (lockObj) { + bool started = false; + try { + process.Start(); + started = true; + } finally { + if (!started) { + process.Exited -= OnProcessExited; + process = null; + } } - } - standardOutputReader = new OutputReader(process.StandardOutput); - if (OutputLineReceived != null) { - standardOutputReader.LineReceived += new LineReceivedEventHandler(OnOutputLineReceived); - } - - standardOutputReader.Start(); - - standardErrorReader = new OutputReader(process.StandardError); - if (ErrorLineReceived != null) { - standardErrorReader.LineReceived += new LineReceivedEventHandler(OnErrorLineReceived); + standardOutputReader = new OutputReader(process.StandardOutput); + if (OutputLineReceived != null) { + standardOutputReader.LineReceived += new LineReceivedEventHandler(OnOutputLineReceived); + } + + standardOutputReader.Start(); + + standardErrorReader = new OutputReader(process.StandardError); + if (ErrorLineReceived != null) { + standardErrorReader.LineReceived += new LineReceivedEventHandler(OnErrorLineReceived); + } + + standardErrorReader.Start(); } - - standardErrorReader.Start(); } /// @@ -230,9 +233,10 @@ namespace ICSharpCode.SharpDevelop.Util protected void OnProcessExited(object sender, EventArgs e) { if (ProcessExited != null) { - - standardOutputReader.WaitForFinish(); - standardErrorReader.WaitForFinish(); + lock (lockObj) { + standardOutputReader.WaitForFinish(); + standardErrorReader.WaitForFinish(); + } ProcessExited(this, e); } diff --git a/src/Main/Base/Test/CodeConverterTests.cs b/src/Main/Base/Test/CodeConverterTests.cs index f29be6e955..72c4d729e3 100644 --- a/src/Main/Base/Test/CodeConverterTests.cs +++ b/src/Main/Base/Test/CodeConverterTests.cs @@ -67,6 +67,7 @@ namespace ICSharpCode.SharpDevelop.Tests if (sourceLanguage == SupportedLanguage.CSharp) { CSharpToVBNetConvertVisitor convertVisitor = new CSharpToVBNetConvertVisitor(pc, parseInfo); + convertVisitor.RootNamespaceToRemove = "RootNamespace"; parser.CompilationUnit.AcceptVisitor(convertVisitor, null); } else { VBNetToCSharpConvertVisitor convertVisitor = new VBNetToCSharpConvertVisitor(pc, parseInfo); @@ -148,6 +149,7 @@ namespace ICSharpCode.SharpDevelop.Tests } #endregion + #region Events and delegates [Test] public void RaiseEventCS2VB() { @@ -237,7 +239,9 @@ namespace ICSharpCode.SharpDevelop.Tests " End Function\n" + "End Class"); } + #endregion + #region ReferenceEqualityAndValueEquality [Test] public void ReferenceEqualityAndValueEquality() { @@ -274,7 +278,9 @@ namespace ICSharpCode.SharpDevelop.Tests "If a = b Then\n" + "End If"); } + #endregion + #region FixVBCasing [Test] public void FixVBCasing() { @@ -290,18 +296,9 @@ namespace ICSharpCode.SharpDevelop.Tests TestStatementsVB2CS("Dim i as Integer = appdomain.getcurrentthreadid", "int i = AppDomain.GetCurrentThreadId();"); } + #endregion - [Test] - public void IndexerExpression() - { - TestStatementsVB2CS("Dim i(10) as Integer\n" + - "Dim i2 As Integer = i(4)", - "int[] i = new int[11];\n" + - "int i2 = i[4];"); - TestStatementsVB2CS("Dim s as string = appdomain.currentdomain.GetAssemblies()(1).location", - "string s = AppDomain.CurrentDomain.GetAssemblies()[1].Location;"); - } - + #region Redim [Test] public void Redim() { @@ -337,6 +334,18 @@ namespace ICSharpCode.SharpDevelop.Tests "int[,] MyArray = new int[6, 6];\n" + "MyArray = (int[,])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray(MyArray, new int[11, 11]);"); } + #endregion + + [Test] + public void IndexerExpression() + { + TestStatementsVB2CS("Dim i(10) as Integer\n" + + "Dim i2 As Integer = i(4)", + "int[] i = new int[11];\n" + + "int i2 = i[4];"); + TestStatementsVB2CS("Dim s as string = appdomain.currentdomain.GetAssemblies()(1).location", + "string s = AppDomain.CurrentDomain.GetAssemblies()[1].Location;"); + } [Test] public void StringConcatWithException() @@ -357,6 +366,104 @@ namespace ICSharpCode.SharpDevelop.Tests "Dim c As Integer = a \\ b\n"); } + #region Casting + [Test] + public void CastToEnum() + { + TestStatementsCS2VB("DayOfWeek dow = (DayOfWeek)obj;\n", + "Dim dow As DayOfWeek = CType(obj, DayOfWeek)\n"); + } + + [Test] + public void CastToValueType() + { + TestStatementsCS2VB("Guid g = (Guid)obj;\n", + "Dim g As Guid = CType(obj, Guid)\n"); + } + + [Test] + public void CastToReferenceType() + { + TestStatementsCS2VB("Exception ex = (Exception)obj;\n", + "Dim ex As Exception = DirectCast(obj, Exception)\n"); + } + + [Test] + public void CastToInterface() + { + TestStatementsCS2VB("IDisposable ex = (IDisposable)obj;\n", + "Dim ex As IDisposable = DirectCast(obj, IDisposable)\n"); + } + #endregion + + #region MoveUsingOutOfNamespace + [Test] + public void MoveUsingOutOfNamespace() + { + TestProgramCS2VB("namespace Test\n" + + "{\n" + + " using System;\n" + + " class Test {}" + + "}\n", + "Imports System\n" + + "Namespace Test\n" + + " Class Test\n" + + " End Class\n" + + "End Namespace"); + } + + [Test] + public void MoveUsingOutOfNamespaceWithComments() + { + TestProgramCS2VB("// comment 1\n" + + "namespace Test\n" + + "{\n" + + " // comment 2\n" + + " using System;\n" + + " // comment 3\n" + + " class Test {}" + + "}\n", + "' comment 1\n" + + "' comment 2\n" + + "Imports System\n" + + "Namespace Test\n" + + " ' comment 3\n" + + " Class Test\n" + + " End Class\n" + + "End Namespace"); + } + + [Test] + public void MoveUsingOutOfRootNamespace() + { + TestProgramCS2VB("namespace RootNamespace\n" + + "{\n" + + " using System;\n" + + " class Test {}" + + "}\n", + "Imports System\n" + + "Class Test\n" + + "End Class"); + } + + [Test] + public void MultipleNamespaces() + { + TestProgramCS2VB("namespace RootNamespace {\n" + + " class Test { }" + + "}\n" + + "namespace RootNamespace.SubNamespace {\n" + + " class Test2 { }" + + "}", + "Class Test\n" + + "End Class\n" + + "Namespace SubNamespace\n" + + " Class Test2\n" + + " End Class\n" + + "End Namespace"); + } + #endregion + #region InterfaceImplementation [Test] public void InterfaceImplementation1() @@ -455,6 +562,36 @@ namespace ICSharpCode.SharpDevelop.Tests " }\n" + "}"); } + + [Test] + public void InterfaceImplementation5() + { + TestProgramCS2VB("using System;\n" + + "interface IObj { void T(object a); }\n" + + "interface IStr { void T(string a); }\n" + + "class Test : IObj, IStr {\n" + + " public void T(string a) { }\n" + + " public void T(int a) { }\n" + + " public void T(object a) { }\n" + + "}", + "Imports System\n" + + "Interface IObj\n" + + " Sub T(ByVal a As Object)\n" + + "End Interface\n" + + "Interface IStr\n" + + " Sub T(ByVal a As String)\n" + + "End Interface\n" + + "Class Test\n" + + " Implements IObj\n" + + " Implements IStr\n" + + " Public Sub T(ByVal a As String) Implements IStr.T\n" + + " End Sub\n" + + " Public Sub T(ByVal a As Integer)\n" + + " End Sub\n" + + " Public Sub T(ByVal a As Object) Implements IObj.T\n" + + " End Sub\n" + + "End Class"); + } #endregion } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs index f1dcd7a66d..fbf359f60e 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver NRefactoryResolver _resolver; ParseInformation _parseInfo; IProjectContent _pc; - public string RootNamespaceToStrip { get; set; } + public string RootNamespaceToRemove { get; set; } public string StartupObjectToMakePublic { get; set; } public IList DefaultImportsToRemove { get; set; } @@ -47,19 +47,21 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { - base.VisitNamespaceDeclaration(namespaceDeclaration, data); - if (RootNamespaceToStrip != null) { - if (namespaceDeclaration.Name == RootNamespaceToStrip) { + if (RootNamespaceToRemove != null) { + if (namespaceDeclaration.Name == RootNamespaceToRemove) { // remove namespace declaration + INode insertAfter = namespaceDeclaration; foreach (INode child in namespaceDeclaration.Children) { - child.Parent = namespaceDeclaration.Parent; - namespaceDeclaration.Parent.Children.Add(child); + InsertAfterSibling(insertAfter, child); + insertAfter = child; } + namespaceDeclaration.Children.Clear(); RemoveCurrentNode(); - } else if (namespaceDeclaration.Name.StartsWith(RootNamespaceToStrip + ".")) { - namespaceDeclaration.Name = namespaceDeclaration.Name.Substring(RootNamespaceToStrip.Length + 1); + } else if (namespaceDeclaration.Name.StartsWith(RootNamespaceToRemove + ".")) { + namespaceDeclaration.Name = namespaceDeclaration.Name.Substring(RootNamespaceToRemove.Length + 1); } } + base.VisitNamespaceDeclaration(namespaceDeclaration, data); return null; } @@ -125,7 +127,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver void CreateInterfaceImplementations(IMember currentMember, ParametrizedNode memberDecl, List interfaceImplementations) { - if (currentMember != null && interfaceImplementations.Count == 1) { + if (currentMember != null + && (memberDecl.Modifier & Modifiers.Visibility) == Modifiers.None + && interfaceImplementations.Count == 1) + { // member is explicitly implementing an interface member // to convert explicit interface implementations to VB, make the member private // and ensure its name does not collide with another member @@ -419,5 +424,25 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } } + + public override object VisitCastExpression(CastExpression castExpression, object data) + { + base.VisitCastExpression(castExpression, data); + + if (_resolver.CompilationUnit == null) + return null; + + // cast to value type is a conversion + if (castExpression.CastType == CastType.Cast) { + IReturnType rt = ResolveType(castExpression.CastTo); + if (rt != null) { + IClass c = rt.GetUnderlyingClass(); + if (c != null && (c.ClassType == ClassType.Struct || c.ClassType == ClassType.Enum)) { + castExpression.CastType = CastType.Conversion; + } + } + } + return null; + } } }