From d3ebdfcab4d5325f19f0aa7f05c4605931518aba Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 11 Aug 2007 14:37:32 +0000 Subject: [PATCH] Worked on C# -> VB converter. Fixed SD2-1022: Delegates usage not converted correctly from C# to VB. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2654 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/MyNamespaceBuilder.cs | 14 + .../Src/Project/CSharpToVBConverter.cs | 39 ++- .../Project/Src/Lexer/CSharp/Lexer.cs | 5 + .../Lexer/Special/PreProcessingDirective.cs | 8 +- .../PrettyPrinter/AbstractOutputFormatter.cs | 2 + .../Src/PrettyPrinter/IOutputAstVisitor.cs | 4 + .../Src/PrettyPrinter/SpecialNodesInserter.cs | 2 +- .../VBNet/VBNetOutputFormatter.cs | 13 + .../PrettyPrinter/VBNet/VBNetOutputVisitor.cs | 66 ++--- .../Src/Visitors/ToVBNetConvertVisitor.cs | 27 -- .../NRefactory/Test/NRefactoryTests.csproj | 2 +- ...Visitor.cs => SpecialOutputVisitorTest.cs} | 106 ++++--- .../Output/VBNet/CSharpToVBConverterTest.cs | 38 +-- .../ProjectOptions/ApplicationSettings.cs | 21 ++ src/Main/Base/Test/CodeConverterTests.cs | 91 ++++++ .../CSharpToVBNetConvertVisitor.cs | 272 ++++++++++++++++-- 16 files changed, 534 insertions(+), 176 deletions(-) rename src/Libraries/NRefactory/Test/Output/{SpecialOutputVisitor.cs => SpecialOutputVisitorTest.cs} (68%) diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs index 588500d9d1..b37a60ba37 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs @@ -75,6 +75,20 @@ namespace VBNetBinding switch (project.OutputType) { case OutputType.WinExe: c.BaseTypes.Add(CreateTypeRef(cu, "Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase")); + if (project.GetEvaluatedProperty("MyType") == "WindowsForms") { + c.Methods.Add( + new DefaultMethod(c, "Main") { + Modifiers = ModifierEnum.Internal | ModifierEnum.Static, + ReturnType = c.ProjectContent.SystemTypes.Void, + Parameters = new[] { + new DefaultParameter( + "args", + new ArrayReturnType(c.ProjectContent, c.ProjectContent.SystemTypes.String, 1), + DomRegion.Empty + ) + } + }); + } break; case OutputType.Exe: c.BaseTypes.Add(CreateTypeRef(cu, "Microsoft.VisualBasic.ApplicationServices.ConsoleApplicationBase")); diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs index fa73168281..4c8405f305 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs @@ -26,23 +26,58 @@ namespace VBNetBinding } } + IList defaultImports = new[] { "Microsoft.VisualBasic", "System" }; + + protected override IProject CreateProject(string targetProjectDirectory, IProject sourceProject) + { + VBNetProject project = (VBNetProject)base.CreateProject(targetProjectDirectory, sourceProject); + IProjectItemListProvider provider = (IProjectItemListProvider)project; + foreach (string import in defaultImports) { + provider.AddProjectItem(new ImportProjectItem(project, import)); + } + return project; + } + protected override void ConvertFile(FileProjectItem sourceItem, FileProjectItem targetItem) { ConvertFile(sourceItem, targetItem, ".cs", ".vb", SupportedLanguage.CSharp, new VBNetOutputVisitor()); } + string startupObject; + protected override void ConvertAst(CompilationUnit compilationUnit, List specials, FileProjectItem sourceItem) { PreprocessingDirective.CSharpToVB(specials); IProjectContent pc = ParserService.GetProjectContent(sourceItem.Project) ?? ParserService.CurrentProjectContent; - compilationUnit.AcceptVisitor(new CSharpToVBNetConvertVisitor(pc, ParserService.GetParseInformation(sourceItem.FileName)), null); + CSharpToVBNetConvertVisitor visitor = new CSharpToVBNetConvertVisitor(pc, ParserService.GetParseInformation(sourceItem.FileName)); + visitor.RootNamespaceToStrip = sourceItem.Project.RootNamespace; + visitor.DefaultImportsToRemove = defaultImports; + if (sourceItem.Project is MSBuildBasedProject) { + visitor.StartupObjectToMakePublic = startupObject; + } + compilationUnit.AcceptVisitor(visitor, null); } protected override void CopyProperties(IProject sourceProject, IProject targetProject) { + VBNetProject vbProject = (VBNetProject)targetProject; base.CopyProperties(sourceProject, targetProject); - FixProperty((VBNetProject)targetProject, "DefineConstants", + FixProperty(vbProject, "DefineConstants", delegate(string v) { return v.Replace(';', ','); }); + + // determine the StartupObject + startupObject = vbProject.GetEvaluatedProperty("StartupObject"); + if (string.IsNullOrEmpty(startupObject)) { + IList startupObjects = ICSharpCode.SharpDevelop.Gui.OptionPanels.ApplicationSettings.GetPossibleStartupObjects(sourceProject); + if (startupObjects.Count == 1) { + startupObject = startupObjects[0].FullyQualifiedName; + if (vbProject.OutputType == OutputType.WinExe) { + // we have to set StartupObject to prevent the VB compiler from choosing + // the generated Main method. + vbProject.SetProperty("StartupObject", startupObject); + } + } + } } } } diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs index dc57f689cb..a5826247be 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs @@ -21,6 +21,11 @@ namespace ICSharpCode.NRefactory.Parser.CSharp void ReadPreProcessingDirective() { Location start = new Location(Col - 1, Line); + + // skip spaces between # and the directive + while (ReaderPeek() == ' ') + ReaderRead(); + bool canBeKeyword; string directive = ReadIdent('#', out canBeKeyword); string argument = ReadToEndOfLine(); diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs b/src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs index 875fa3ad20..619c82f3ab 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs @@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory return cmd; } set { - cmd = value; + cmd = value ?? string.Empty; } } @@ -95,7 +95,7 @@ namespace ICSharpCode.NRefactory return arg; } set { - arg = value; + arg = value ?? string.Empty; } } @@ -109,8 +109,8 @@ namespace ICSharpCode.NRefactory public PreprocessingDirective(string cmd, string arg, Location start, Location end) : base(start, end) { - this.cmd = cmd; - this.arg = arg; + this.Cmd = cmd; + this.Arg = arg; } public override object AcceptVisitor(ISpecialVisitor visitor, object data) diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs index b5d3ea784f..7d89ab1062 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs @@ -23,6 +23,8 @@ namespace ICSharpCode.NRefactory.PrettyPrinter bool doNewLine = true; AbstractPrettyPrintOptions prettyPrintOptions; + public bool IsInMemberBody { get; set; } + public int IndentationLevel { get { return indentationLevel; diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs index 74b236df57..263a4fc6fa 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs @@ -43,6 +43,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter string Text { get; } + bool IsInMemberBody { + get; + set; + } void NewLine(); void Indent(); void PrintComment(Comment comment, bool forceWriteInPreviousBlock); diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs index c6df5bc3e1..e34528bbd0 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs @@ -13,7 +13,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter { public class SpecialOutputVisitor : ISpecialVisitor { - IOutputFormatter formatter; + readonly IOutputFormatter formatter; public SpecialOutputVisitor(IOutputFormatter formatter) { diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputFormatter.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputFormatter.cs index 7bc912f22a..63df84041a 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputFormatter.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputFormatter.cs @@ -51,6 +51,19 @@ namespace ICSharpCode.NRefactory.PrettyPrinter } } + public override void PrintPreprocessingDirective(PreprocessingDirective directive, bool forceWriteInPreviousBlock) + { + if (IsInMemberBody + && (string.Equals(directive.Cmd, "#Region", StringComparison.InvariantCultureIgnoreCase) + || string.Equals(directive.Cmd, "#End", StringComparison.InvariantCultureIgnoreCase) + && directive.Arg.ToLowerInvariant().StartsWith("region"))) + { + WriteLineInPreviousLine("'" + directive.Cmd + " " + directive.Arg, forceWriteInPreviousBlock); + } else { + base.PrintPreprocessingDirective(directive, forceWriteInPreviousBlock); + } + } + public void PrintLineContinuation() { if (!LastCharacterIsWhiteSpace) diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs index 0c8047b016..feb0b2fd2c 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -574,12 +574,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.NewLine(); if (!IsAbstract(propertyDeclaration)) { + outputFormatter.IsInMemberBody = true; ++outputFormatter.IndentationLevel; exitTokenStack.Push(Tokens.Property); TrackedVisit(propertyDeclaration.GetRegion, data); TrackedVisit(propertyDeclaration.SetRegion, data); exitTokenStack.Pop(); --outputFormatter.IndentationLevel; + outputFormatter.IsInMemberBody = false; outputFormatter.Indent(); outputFormatter.PrintToken(Tokens.End); @@ -848,6 +850,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.NewLine(); if (!IsAbstract(methodDeclaration)) { + outputFormatter.IsInMemberBody = true; BeginVisit(methodDeclaration.Body); ++outputFormatter.IndentationLevel; exitTokenStack.Push(isSub ? Tokens.Sub : Tokens.Function); @@ -866,6 +869,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter } outputFormatter.NewLine(); EndVisit(methodDeclaration.Body); + outputFormatter.IsInMemberBody = false; } return null; } @@ -895,6 +899,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.PrintToken(Tokens.CloseParenthesis); outputFormatter.NewLine(); + outputFormatter.IsInMemberBody = true; ++outputFormatter.IndentationLevel; exitTokenStack.Push(Tokens.Sub); @@ -903,6 +908,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter TrackedVisit(constructorDeclaration.Body, data); exitTokenStack.Pop(); --outputFormatter.IndentationLevel; + outputFormatter.IsInMemberBody = false; outputFormatter.Indent(); outputFormatter.PrintToken(Tokens.End); @@ -2031,6 +2037,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter { int op = 0; switch (binaryOperatorExpression.Op) { + case BinaryOperatorType.Concat: + op = Tokens.ConcatString; + break; + case BinaryOperatorType.Add: op = Tokens.Plus; break; @@ -2047,6 +2057,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter op = Tokens.Div; break; + case BinaryOperatorType.DivideInteger: + op = Tokens.DivInteger; + break; + case BinaryOperatorType.Modulus: op = Tokens.Mod; break; @@ -2100,13 +2114,11 @@ namespace ICSharpCode.NRefactory.PrettyPrinter TrackedVisit(binaryOperatorExpression.Right, data); return null; case BinaryOperatorType.NullCoalescing: - outputFormatter.PrintText("IIf("); + outputFormatter.PrintText("If("); TrackedVisit(binaryOperatorExpression.Left, data); - outputFormatter.PrintText(" Is Nothing, "); - TrackedVisit(binaryOperatorExpression.Right, data); outputFormatter.PrintToken(Tokens.Comma); outputFormatter.Space(); - TrackedVisit(binaryOperatorExpression.Left, data); + TrackedVisit(binaryOperatorExpression.Right, data); outputFormatter.PrintToken(Tokens.CloseParenthesis); return null; case BinaryOperatorType.LessThan: @@ -2232,31 +2244,9 @@ namespace ICSharpCode.NRefactory.PrettyPrinter break; case AssignmentOperatorType.Add: op = Tokens.PlusAssign; - if (IsEventHandlerCreation(assignmentExpression.Right)) { - outputFormatter.PrintToken(Tokens.AddHandler); - outputFormatter.Space(); - TrackedVisit(assignmentExpression.Left, data); - outputFormatter.PrintToken(Tokens.Comma); - outputFormatter.Space(); - outputFormatter.PrintToken(Tokens.AddressOf); - outputFormatter.Space(); - TrackedVisit(GetEventHandlerMethod(assignmentExpression.Right), data); - return null; - } break; case AssignmentOperatorType.Subtract: op = Tokens.MinusAssign; - if (IsEventHandlerCreation(assignmentExpression.Right)) { - outputFormatter.PrintToken(Tokens.RemoveHandler); - outputFormatter.Space(); - TrackedVisit(assignmentExpression.Left, data); - outputFormatter.PrintToken(Tokens.Comma); - outputFormatter.Space(); - outputFormatter.PrintToken(Tokens.AddressOf); - outputFormatter.Space(); - TrackedVisit(GetEventHandlerMethod(assignmentExpression.Right), data); - return null; - } break; case AssignmentOperatorType.Multiply: op = Tokens.TimesAssign; @@ -2540,13 +2530,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter public override object TrackedVisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { - // No representation in VB.NET, but VB conversion is possible. - outputFormatter.PrintText("IIf"); + outputFormatter.PrintText("If"); outputFormatter.PrintToken(Tokens.OpenParenthesis); TrackedVisit(conditionalExpression.Condition, data); outputFormatter.PrintToken(Tokens.Comma); + outputFormatter.Space(); TrackedVisit(conditionalExpression.TrueExpression, data); outputFormatter.PrintToken(Tokens.Comma); + outputFormatter.Space(); TrackedVisit(conditionalExpression.FalseExpression, data); outputFormatter.PrintToken(Tokens.CloseParenthesis); return null; @@ -2697,25 +2688,6 @@ namespace ICSharpCode.NRefactory.PrettyPrinter } } - - static bool IsEventHandlerCreation(Expression expr) - { - if (expr is ObjectCreateExpression) { - ObjectCreateExpression oce = (ObjectCreateExpression) expr; - if (oce.Parameters.Count == 1) { - return oce.CreateType.SystemType.EndsWith("Handler"); - } - } - return false; - } - - // can only get called if IsEventHandlerCreation returned true for the expression - static Expression GetEventHandlerMethod(Expression expr) - { - ObjectCreateExpression oce = (ObjectCreateExpression)expr; - return oce.Parameters[0]; - } - public override object TrackedVisitLambdaExpression(LambdaExpression lambdaExpression, object data) { throw new NotImplementedException(); diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs index 5da0706a7d..22e6abab4d 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs @@ -149,18 +149,6 @@ namespace ICSharpCode.NRefactory.Visitors return null; } - static string GetMethodNameOfDelegateCreation(Expression expr) - { - string name = GetMemberNameOnThisReference(expr); - if (name != null) - return name; - ObjectCreateExpression oce = expr as ObjectCreateExpression; - if (oce != null && oce.Parameters.Count == 1) { - return GetMemberNameOnThisReference(oce.Parameters[0]); - } - return null; - } - public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) { MethodDeclaration method = new MethodDeclaration { @@ -179,21 +167,6 @@ namespace ICSharpCode.NRefactory.Visitors public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) { - if (assignmentExpression.Op == AssignmentOperatorType.Add - || assignmentExpression.Op == AssignmentOperatorType.Subtract) - { - string methodName = GetMethodNameOfDelegateCreation(assignmentExpression.Right); - if (methodName != null && currentType != null) { - foreach (object c in currentType.Children) { - MethodDeclaration method = c as MethodDeclaration; - if (method != null && method.Name == methodName) { - // this statement is registering an event - assignmentExpression.Right = new AddressOfExpression(new IdentifierExpression(methodName)); - break; - } - } - } - } base.VisitAssignmentExpression(assignmentExpression, data); if (assignmentExpression.Op == AssignmentOperatorType.Assign && !(assignmentExpression.Parent is ExpressionStatement)) { AddInlineAssignHelper(); diff --git a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj b/src/Libraries/NRefactory/Test/NRefactoryTests.csproj index 067a7575c8..c77500988b 100644 --- a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj +++ b/src/Libraries/NRefactory/Test/NRefactoryTests.csproj @@ -144,7 +144,7 @@ - + diff --git a/src/Libraries/NRefactory/Test/Output/SpecialOutputVisitor.cs b/src/Libraries/NRefactory/Test/Output/SpecialOutputVisitorTest.cs similarity index 68% rename from src/Libraries/NRefactory/Test/Output/SpecialOutputVisitor.cs rename to src/Libraries/NRefactory/Test/Output/SpecialOutputVisitorTest.cs index 2b96b86180..992d127569 100644 --- a/src/Libraries/NRefactory/Test/Output/SpecialOutputVisitor.cs +++ b/src/Libraries/NRefactory/Test/Output/SpecialOutputVisitorTest.cs @@ -6,6 +6,7 @@ // using System; +using System.Collections.Generic; using System.IO; using NUnit.Framework; using ICSharpCode.NRefactory.Parser; @@ -23,6 +24,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter parser.Parse(); Assert.AreEqual("", parser.Errors.ErrorOutput); CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(); + outputVisitor.Options.IndentationChar = ' '; + outputVisitor.Options.TabSize = 2; + outputVisitor.Options.IndentSize = 2; using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), outputVisitor)) { outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); @@ -38,6 +42,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter parser.Parse(); Assert.AreEqual("", parser.Errors.ErrorOutput); VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); + outputVisitor.Options.IndentationChar = ' '; + outputVisitor.Options.TabSize = 2; + outputVisitor.Options.IndentSize = 2; using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), outputVisitor)) { outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); @@ -53,8 +60,12 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter parser.Parse(); Assert.AreEqual("", parser.Errors.ErrorOutput); VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); - using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), - outputVisitor)) { + List specials = parser.Lexer.SpecialTracker.RetrieveSpecials(); + PreprocessingDirective.CSharpToVB(specials); + outputVisitor.Options.IndentationChar = ' '; + outputVisitor.Options.TabSize = 2; + outputVisitor.Options.IndentSize = 2; + using (SpecialNodesInserter.Install(specials, outputVisitor)) { outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); } Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); @@ -80,7 +91,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter TestProgram("// before class\n" + "class A\n" + "{\n" + - "\t// in class\n" + + " // in class\n" + "}\n" + "// after class"); } @@ -91,7 +102,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter TestProgram("/* before class */\n" + "class A\n" + "{\n" + - "\t/* in class */\n" + + " /* in class */\n" + "}\n" + "/* after class */"); } @@ -104,9 +115,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "/* block comment before */\n" + "class A\n" + "{\n" + - "\t/* in class */\n" + - "\t// in class 2" + - "\t/* in class 3 */\n" + + " /* in class */\n" + + " // in class 2" + + " /* in class 3 */\n" + "}\n" + "/* after class */\n" + "// after class 2\n" + @@ -128,11 +139,11 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter { TestProgram("enum Test\n" + "{\n" + - "\t// a\n" + - "\tm1,\n" + - "\t// b\n" + - "\tm2\n" + - "\t// c\n" + + " // a\n" + + " m1,\n" + + " // b\n" + + " m2\n" + + " // c\n" + "}\n" + "// d"); } @@ -141,11 +152,11 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter public void EnumVB() { TestProgramVB("Enum Test\n" + - "\t' a\n" + - "\tm1\n" + - "\t' b\n" + - "\tm2\n" + - "\t' c\n" + + " ' a\n" + + " m1\n" + + " ' b\n" + + " m2\n" + + " ' c\n" + "End Enum\n" + "' d"); } @@ -155,26 +166,26 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter { TestProgram(@"public class Class1 { - private bool test(int l, int lvw) - { - #region Metodos Auxiliares - int i = 1; - return false; - #endregion - } + private bool test(int l, int lvw) + { + #region Metodos Auxiliares + int i = 1; + return false; + #endregion + } }"); } [Test] - public void RegionInsideMethodVB() + public void CommentsInsideMethodVB() { TestProgramVB(@"Public Class Class1 - Private Function test(ByVal l As Integer, ByVal lvw As Integer) As Boolean - ' Begin - Dim i As Integer = 1 - Return False - ' End of method - End Function + Private Function test(ByVal l As Integer, ByVal lvw As Integer) As Boolean + ' Begin + Dim i As Integer = 1 + Return False + ' End of method + End Function End Class"); } @@ -199,10 +210,10 @@ End Class"); { TestProgramCS2VB("class A { [PreserveSig] public void B(// comment\nint c) {} }", "Class A\n" + - "\t\t' comment\n" + - "\t _\n" + - "\tPublic Sub B(ByVal c As Integer)\n" + - "\tEnd Sub\n" + + " ' comment\n" + + " _\n" + + " Public Sub B(ByVal c As Integer)\n" + + " End Sub\n" + "End Class"); } @@ -211,12 +222,29 @@ End Class"); { TestProgram("class A\n" + "{\n" + - "\t#if TEST\n" + - "\t[MyAttribute()]\n" + - "\t#endif\n" + - "\tpublic int Field;\n" + + " #if TEST\n" + + " [MyAttribute()]\n" + + " #endif\n" + + " public int Field;\n" + "}\n" + "#end if"); } + + [Test] + public void RegionInsideMethodCS2VB() + { + TestProgramCS2VB("class A { void M() {\n" + + " #region PP\n" + + " return;" + + " #endregion\n" + + "} }", + "Class A\n" + + " Sub M()\n" + + " '#Region \"PP\"\n" + + " Return\n" + + " '#End Region\n" + + " End Sub\n" + + "End Class"); + } } } diff --git a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs index d26c948e4d..60a46986e5 100644 --- a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs +++ b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs @@ -148,20 +148,6 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "Next"); } - [Test] - public void AddEventHandler() - { - TestStatement("this.button1.Click += new System.EventHandler(this.OnButton1Click);", - "AddHandler Me.button1.Click, AddressOf Me.OnButton1Click"); - } - - [Test] - public void RemoveEventHandler() - { - TestStatement("this.button1.Click -= new System.EventHandler(this.OnButton1Click);", - "RemoveHandler Me.button1.Click, AddressOf Me.OnButton1Click"); - } - [Test] public void RaiseEvent() { @@ -201,6 +187,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "End If"); } + /* [Test] public void AnonymousMethod() { @@ -213,7 +200,6 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter "End Sub"); } - /* [Test, Ignore("NRefactory cannot guess the anonymous method's return type")] public void AnonymousMethodInVarDeclaration() { @@ -227,19 +213,6 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter } */ - [Test] - public void RegisterEvent() - { - TestStatement("someEvent += tmp2;", - "AddHandler someEvent, AddressOf tmp2"); - TestStatement("someEvent += this.tmp2;", - "AddHandler someEvent, AddressOf tmp2"); - TestStatement("someEvent += new SomeDelegate(tmp2);", - "AddHandler someEvent, AddressOf tmp2"); - TestStatement("someEvent += new SomeDelegate(this.tmp2);", - "AddHandler someEvent, AddressOf tmp2"); - } - [Test] public void StaticMethod() { @@ -346,7 +319,14 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter public void NullCoalescing() { TestStatement("c = a ?? b;", - "c = IIf(a Is Nothing, b, a)"); + "c = If(a, b)"); + } + + [Test] + public void Ternary() + { + TestStatement("d = a ? b : c;", + "d = If(a, b, c)"); } [Test] diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs index 44ff0985e6..260f8706a0 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs @@ -6,11 +6,13 @@ // using System; +using System.Collections.Generic; using System.Drawing; using System.IO; using System.Windows.Forms; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -47,6 +49,9 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels b = helper.BindString("startupObjectComboBox", "StartupObject", TextBoxEditMode.EditEvaluatedProperty); b.RegisterLocationButton(locationButton); + foreach (IClass c in GetPossibleStartupObjects(project)) { + Get("startupObject").Items.Add(c.FullyQualifiedName); + } b = helper.BindString("applicationIconComboBox", "ApplicationIcon", TextBoxEditMode.EditEvaluatedProperty); Get("applicationIcon").TextChanged += new EventHandler(ApplicationIconComboBoxTextChanged); @@ -66,6 +71,22 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels helper.AddConfigurationSelector(this); } + public static IList GetPossibleStartupObjects(IProject project) + { + List results = new List(); + IProjectContent pc = ParserService.GetProjectContent(project); + if (pc != null) { + foreach (IClass c in pc.Classes) { + foreach (IMethod m in c.Methods) { + if (m.IsStatic && m.Name == "Main") { + results.Add(c); + } + } + } + } + return results; + } + void RefreshOutputNameTextBox(object sender, EventArgs e) { Get("outputName").Text = Get("assemblyName").Text + CompilableProject.GetExtension((OutputType)Get("outputType").SelectedIndex); diff --git a/src/Main/Base/Test/CodeConverterTests.cs b/src/Main/Base/Test/CodeConverterTests.cs index d479dd3b31..f29be6e955 100644 --- a/src/Main/Base/Test/CodeConverterTests.cs +++ b/src/Main/Base/Test/CodeConverterTests.cs @@ -166,6 +166,78 @@ namespace ICSharpCode.SharpDevelop.Tests "End Sub"); } + + [Test] + public void EventHandlerTest() + { + TestMemberCS2VB("public event EventHandler Click;" + + "void T() {" + + " Click += T;" + + " Click -= this.T;" + + " Click += new EventHandler(T);" + + " Click += new EventHandler(this.T);" + + " EventHandler eh = new EventHandler(T);" + + " eh = T;" + + " eh += eh;" + + " eh -= eh;" + + " this.Click += eh;" + + "}", + "Public Event Click As EventHandler\n" + + "Private Sub T()\n" + + " AddHandler Click, AddressOf T\n" + + " RemoveHandler Click, AddressOf Me.T\n" + + " AddHandler Click, New EventHandler(AddressOf T)\n" + + " AddHandler Click, New EventHandler(AddressOf Me.T)\n" + + " Dim eh As New EventHandler(AddressOf T)\n" + + " eh = AddressOf T\n" + + " eh = DirectCast([Delegate].Combine(eh, eh), EventHandler)\n" + + " eh = DirectCast([Delegate].Remove(eh, eh), EventHandler)\n" + + " AddHandler Me.Click, eh\n" + + "End Sub"); + } + + [Test] + public void CreateDelegateCS2VB() + { + TestProgramCS2VB("using System; using System.Text.RegularExpressions;\n" + + "class Test {\n" + + " object M() {\n" + + " return new MatchEvaluator(X);\n" + + " }\n" + + " string X(Match match) {}" + + "}", + "Imports System\n" + + "Imports System.Text.RegularExpressions\n" + + "Class Test\n" + + " Private Function M() As Object\n" + + " Return New MatchEvaluator(AddressOf X)\n" + + " End Function\n" + + " Private Function X(ByVal match As Match) As String\n" + + " End Function\n" + + "End Class"); + } + + [Test] + public void ImplicitlyCreateDelegateCS2VB() + { + TestProgramCS2VB("using System; using System.Text.RegularExpressions;\n" + + "class Test {\n" + + " void M(Regex regex, string text) {\n" + + " regex.Replace(text, X);\n" + + " }\n" + + " string X(Match match) {}" + + "}", + "Imports System\n" + + "Imports System.Text.RegularExpressions\n" + + "Class Test\n" + + " Private Sub M(ByVal regex As Regex, ByVal text As String)\n" + + " regex.Replace(text, AddressOf X)\n" + + " End Sub\n" + + " Private Function X(ByVal match As Match) As String\n" + + " End Function\n" + + "End Class"); + } + [Test] public void ReferenceEqualityAndValueEquality() { @@ -266,6 +338,25 @@ namespace ICSharpCode.SharpDevelop.Tests "MyArray = (int[,])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray(MyArray, new int[11, 11]);"); } + [Test] + public void StringConcatWithException() + { + TestStatementsCS2VB("Exception ex;\n" + + "string a = \"Error: \" + ex + \"!\";", + "Dim ex As Exception\n" + + "Dim a As String = \"Error: \" & Convert.ToString(ex) & \"!\"\n"); + } + + [Test] + public void PerformIntegerDivision() + { + TestStatementsCS2VB("int a = 5; int b = 2;\n" + + "int c = a / b;", + "Dim a As Integer = 5\n" + + "Dim b As Integer = 2\n" + + "Dim c As Integer = a \\ b\n"); + } + #region InterfaceImplementation [Test] public void InterfaceImplementation1() 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 4f7a76dcf0..f1dcd7a66d 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs @@ -21,6 +21,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver NRefactoryResolver _resolver; ParseInformation _parseInfo; IProjectContent _pc; + public string RootNamespaceToStrip { get; set; } + public string StartupObjectToMakePublic { get; set; } + public IList DefaultImportsToRemove { get; set; } public CSharpToVBNetConvertVisitor(IProjectContent pc, ParseInformation parseInfo) { @@ -29,16 +32,54 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver _parseInfo = parseInfo; } + public override object VisitCompilationUnit(CompilationUnit compilationUnit, object data) + { + base.VisitCompilationUnit(compilationUnit, data); + ToVBNetConvertVisitor v = new ToVBNetConvertVisitor(); + compilationUnit.AcceptVisitor(v, data); + return null; + } + IReturnType ResolveType(TypeReference typeRef) { return TypeVisitor.CreateReturnType(typeRef, _resolver); } - public override object VisitCompilationUnit(CompilationUnit compilationUnit, object data) + public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { - base.VisitCompilationUnit(compilationUnit, data); - ToVBNetConvertVisitor v = new ToVBNetConvertVisitor(); - compilationUnit.AcceptVisitor(v, data); + base.VisitNamespaceDeclaration(namespaceDeclaration, data); + if (RootNamespaceToStrip != null) { + if (namespaceDeclaration.Name == RootNamespaceToStrip) { + // remove namespace declaration + foreach (INode child in namespaceDeclaration.Children) { + child.Parent = namespaceDeclaration.Parent; + namespaceDeclaration.Parent.Children.Add(child); + } + RemoveCurrentNode(); + } else if (namespaceDeclaration.Name.StartsWith(RootNamespaceToStrip + ".")) { + namespaceDeclaration.Name = namespaceDeclaration.Name.Substring(RootNamespaceToStrip.Length + 1); + } + } + return null; + } + + public override object VisitUsing(Using @using, object data) + { + base.VisitUsing(@using, data); + if (DefaultImportsToRemove != null && !@using.IsAlias) { + if (DefaultImportsToRemove.Contains(@using.Name)) { + RemoveCurrentNode(); + } + } + return null; + } + + public override object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + { + base.VisitUsingDeclaration(usingDeclaration, data); + if (usingDeclaration.Usings.Count == 0) { + RemoveCurrentNode(); + } return null; } @@ -66,6 +107,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } IMethod currentMethod = _resolver.CallingMember as IMethod; CreateInterfaceImplementations(currentMethod, methodDeclaration, methodDeclaration.InterfaceImplementations); + if (currentMethod != null && currentMethod.Name == "Main") { + if (currentMethod.DeclaringType.FullyQualifiedName == StartupObjectToMakePublic) { + if (currentMethod.IsStatic && currentMethod.IsPrivate) { + methodDeclaration.Modifier &= ~Modifiers.Private; + methodDeclaration.Modifier |= Modifiers.Internal; + } + } + } return base.VisitMethodDeclaration(methodDeclaration, data); } @@ -164,40 +213,211 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver eventInvocation.Arguments)); } } - return base.VisitExpressionStatement(expressionStatement, data); + base.VisitExpressionStatement(expressionStatement, data); + + HandleAssignmentStatement(expressionStatement.Expression as AssignmentExpression); + return null; } public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { + base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); + if (_resolver.CompilationUnit == null) - return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); + return null; - base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); - if (binaryOperatorExpression.Op == BinaryOperatorType.Equality || binaryOperatorExpression.Op == BinaryOperatorType.InEquality) { - // maybe we have to convert Equality operator to ReferenceEquality - ResolveResult left = _resolver.ResolveInternal(binaryOperatorExpression.Left, ExpressionContext.Default); - ResolveResult right = _resolver.ResolveInternal(binaryOperatorExpression.Right, ExpressionContext.Default); - if (left != null && right != null && left.ResolvedType != null && right.ResolvedType != null) { - IClass cLeft = left.ResolvedType.GetUnderlyingClass(); - IClass cRight = right.ResolvedType.GetUnderlyingClass(); - if (cLeft != null && cRight != null) { - if ((cLeft.ClassType != ClassType.Struct && cLeft.ClassType != ClassType.Enum) - || (cRight.ClassType != ClassType.Struct && cRight.ClassType != ClassType.Enum)) - { - // this is a reference comparison - if (cLeft.FullyQualifiedName != "System.String") { - // and it's not a string comparison, so we'll use reference equality - if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) { - binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality; - } else { - binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality; - } + switch (binaryOperatorExpression.Op) { + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + ConvertEqualityToReferenceEqualityIfRequired(binaryOperatorExpression); + break; + case BinaryOperatorType.Add: + ConvertArgumentsForStringConcatenationIfRequired(binaryOperatorExpression); + break; + case BinaryOperatorType.Divide: + ConvertDivisionToIntegerDivisionIfRequired(binaryOperatorExpression); + break; + } + return null; + } + + void ConvertEqualityToReferenceEqualityIfRequired(BinaryOperatorExpression binaryOperatorExpression) + { + // maybe we have to convert Equality operator to ReferenceEquality + ResolveResult left = _resolver.ResolveInternal(binaryOperatorExpression.Left, ExpressionContext.Default); + ResolveResult right = _resolver.ResolveInternal(binaryOperatorExpression.Right, ExpressionContext.Default); + if (left != null && right != null && left.ResolvedType != null && right.ResolvedType != null) { + IClass cLeft = left.ResolvedType.GetUnderlyingClass(); + IClass cRight = right.ResolvedType.GetUnderlyingClass(); + if (cLeft != null && cRight != null) { + if ((cLeft.ClassType != ClassType.Struct && cLeft.ClassType != ClassType.Enum) + || (cRight.ClassType != ClassType.Struct && cRight.ClassType != ClassType.Enum)) + { + // this is a reference comparison + if (cLeft.FullyQualifiedName != "System.String") { + // and it's not a string comparison, so we'll use reference equality + if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) { + binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality; + } else { + binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality; } } } } } + } + + void ConvertArgumentsForStringConcatenationIfRequired(BinaryOperatorExpression binaryOperatorExpression) + { + ResolveResult left = _resolver.ResolveInternal(binaryOperatorExpression.Left, ExpressionContext.Default); + ResolveResult right = _resolver.ResolveInternal(binaryOperatorExpression.Right, ExpressionContext.Default); + + if (left != null && right != null) { + if (IsString(left.ResolvedType)) { + binaryOperatorExpression.Op = BinaryOperatorType.Concat; + if (NeedsExplicitConversionToString(right.ResolvedType)) { + binaryOperatorExpression.Right = CreateExplicitConversionToString(binaryOperatorExpression.Right); + } + } else if (IsString(right.ResolvedType)) { + binaryOperatorExpression.Op = BinaryOperatorType.Concat; + if (NeedsExplicitConversionToString(left.ResolvedType)) { + binaryOperatorExpression.Left = CreateExplicitConversionToString(binaryOperatorExpression.Left); + } + } + } + } + + void ConvertDivisionToIntegerDivisionIfRequired(BinaryOperatorExpression binaryOperatorExpression) + { + ResolveResult left = _resolver.ResolveInternal(binaryOperatorExpression.Left, ExpressionContext.Default); + ResolveResult right = _resolver.ResolveInternal(binaryOperatorExpression.Right, ExpressionContext.Default); + + if (left != null && right != null) { + if (IsInteger(left.ResolvedType) && IsInteger(right.ResolvedType)) { + binaryOperatorExpression.Op = BinaryOperatorType.DivideInteger; + } + } + } + + bool IsString(IReturnType rt) + { + return rt != null && rt.IsDefaultReturnType && rt.FullyQualifiedName == "System.String"; + } + + bool IsInteger(IReturnType rt) + { + if (rt != null && rt.IsDefaultReturnType) { + switch (rt.FullyQualifiedName) { + case "System.Byte": + case "System.SByte": + case "System.Int16": + case "System.UInt16": + case "System.Int32": + case "System.UInt32": + case "System.Int64": + case "System.UInt64": + return true; + } + } + return false; + } + + bool NeedsExplicitConversionToString(IReturnType rt) + { + if (rt != null) { + if (rt.IsDefaultReturnType) { + if (rt.FullyQualifiedName == "System.Object" + || !TypeReference.PrimitiveTypesVBReverse.ContainsKey(rt.FullyQualifiedName)) + { + // object and non-primitive types need explicit conversion + return true; + } else { + // primitive types except object don't need explicit conversion + return false; + } + } else { + return true; + } + } + return false; + } + + Expression CreateExplicitConversionToString(Expression expr) + { + InvocationExpression ie = new InvocationExpression( + new FieldReferenceExpression(new IdentifierExpression("Convert"), "ToString")); + ie.Arguments.Add(expr); + return ie; + } + + public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + base.VisitIdentifierExpression(identifierExpression, data); + if (_resolver.CompilationUnit == null) + return null; + + InvocationExpression parentIE = identifierExpression.Parent as InvocationExpression; + if (!(identifierExpression.Parent is AddressOfExpression) + && (parentIE == null || parentIE.TargetObject != identifierExpression)) + { + ResolveResult rr = _resolver.ResolveInternal(identifierExpression, ExpressionContext.Default); + if (rr is MethodResolveResult) { + ReplaceCurrentNode(new AddressOfExpression(identifierExpression)); + } + } return null; } + + public override object VisitFieldReferenceExpression(FieldReferenceExpression fieldReferenceExpression, object data) + { + base.VisitFieldReferenceExpression(fieldReferenceExpression, data); + + if (_resolver.CompilationUnit == null) + return null; + + InvocationExpression parentIE = fieldReferenceExpression.Parent as InvocationExpression; + if (!(fieldReferenceExpression.Parent is AddressOfExpression) + && (parentIE == null || parentIE.TargetObject != fieldReferenceExpression)) + { + ResolveResult rr = _resolver.ResolveInternal(fieldReferenceExpression, ExpressionContext.Default); + if (rr is MethodResolveResult) { + ReplaceCurrentNode(new AddressOfExpression(fieldReferenceExpression)); + } + } + + return null; + } + + void HandleAssignmentStatement(AssignmentExpression assignmentExpression) + { + if (_resolver.CompilationUnit == null || assignmentExpression == null) + return; + + if (assignmentExpression.Op == AssignmentOperatorType.Add || assignmentExpression.Op == AssignmentOperatorType.Subtract) { + ResolveResult rr = _resolver.ResolveInternal(assignmentExpression.Left, ExpressionContext.Default); + if (rr is MemberResolveResult && (rr as MemberResolveResult).ResolvedMember is IEvent) { + if (assignmentExpression.Op == AssignmentOperatorType.Add) { + ReplaceCurrentNode(new AddHandlerStatement(assignmentExpression.Left, assignmentExpression.Right)); + } else { + ReplaceCurrentNode(new RemoveHandlerStatement(assignmentExpression.Left, assignmentExpression.Right)); + } + } else if (rr.ResolvedType != null) { + IClass c = rr.ResolvedType.GetUnderlyingClass(); + if (c.ClassType == ClassType.Delegate) { + InvocationExpression invocation = new InvocationExpression( + new FieldReferenceExpression( + new IdentifierExpression("Delegate"), + assignmentExpression.Op == AssignmentOperatorType.Add ? "Combine" : "Remove")); + invocation.Arguments.Add(assignmentExpression.Left); + invocation.Arguments.Add(assignmentExpression.Right); + + assignmentExpression.Op = AssignmentOperatorType.Assign; + assignmentExpression.Right = new CastExpression( + Refactoring.CodeGenerator.ConvertType(rr.ResolvedType, CreateContext()), + invocation, CastType.Cast); + } + } + } + } } }