Browse Source

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
shortcuts
Daniel Grunwald 18 years ago
parent
commit
d3ebdfcab4
  1. 14
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs
  2. 39
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs
  3. 5
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs
  4. 8
      src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs
  5. 2
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs
  6. 4
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs
  7. 2
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs
  8. 13
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputFormatter.cs
  9. 66
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs
  10. 27
      src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs
  11. 2
      src/Libraries/NRefactory/Test/NRefactoryTests.csproj
  12. 106
      src/Libraries/NRefactory/Test/Output/SpecialOutputVisitorTest.cs
  13. 38
      src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs
  14. 21
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs
  15. 91
      src/Main/Base/Test/CodeConverterTests.cs
  16. 272
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs

14
src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs

@ -75,6 +75,20 @@ namespace VBNetBinding
switch (project.OutputType) { switch (project.OutputType) {
case OutputType.WinExe: case OutputType.WinExe:
c.BaseTypes.Add(CreateTypeRef(cu, "Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase")); 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; break;
case OutputType.Exe: case OutputType.Exe:
c.BaseTypes.Add(CreateTypeRef(cu, "Microsoft.VisualBasic.ApplicationServices.ConsoleApplicationBase")); c.BaseTypes.Add(CreateTypeRef(cu, "Microsoft.VisualBasic.ApplicationServices.ConsoleApplicationBase"));

39
src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs

@ -26,23 +26,58 @@ namespace VBNetBinding
} }
} }
IList<string> 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) protected override void ConvertFile(FileProjectItem sourceItem, FileProjectItem targetItem)
{ {
ConvertFile(sourceItem, targetItem, ".cs", ".vb", SupportedLanguage.CSharp, new VBNetOutputVisitor()); ConvertFile(sourceItem, targetItem, ".cs", ".vb", SupportedLanguage.CSharp, new VBNetOutputVisitor());
} }
string startupObject;
protected override void ConvertAst(CompilationUnit compilationUnit, List<ISpecial> specials, FileProjectItem sourceItem) protected override void ConvertAst(CompilationUnit compilationUnit, List<ISpecial> specials, FileProjectItem sourceItem)
{ {
PreprocessingDirective.CSharpToVB(specials); PreprocessingDirective.CSharpToVB(specials);
IProjectContent pc = ParserService.GetProjectContent(sourceItem.Project) ?? ParserService.CurrentProjectContent; 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) protected override void CopyProperties(IProject sourceProject, IProject targetProject)
{ {
VBNetProject vbProject = (VBNetProject)targetProject;
base.CopyProperties(sourceProject, targetProject); base.CopyProperties(sourceProject, targetProject);
FixProperty((VBNetProject)targetProject, "DefineConstants", FixProperty(vbProject, "DefineConstants",
delegate(string v) { return v.Replace(';', ','); }); delegate(string v) { return v.Replace(';', ','); });
// determine the StartupObject
startupObject = vbProject.GetEvaluatedProperty("StartupObject");
if (string.IsNullOrEmpty(startupObject)) {
IList<IClass> 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);
}
}
}
} }
} }
} }

5
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs

@ -21,6 +21,11 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
void ReadPreProcessingDirective() void ReadPreProcessingDirective()
{ {
Location start = new Location(Col - 1, Line); Location start = new Location(Col - 1, Line);
// skip spaces between # and the directive
while (ReaderPeek() == ' ')
ReaderRead();
bool canBeKeyword; bool canBeKeyword;
string directive = ReadIdent('#', out canBeKeyword); string directive = ReadIdent('#', out canBeKeyword);
string argument = ReadToEndOfLine(); string argument = ReadToEndOfLine();

8
src/Libraries/NRefactory/Project/Src/Lexer/Special/PreProcessingDirective.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory
return cmd; return cmd;
} }
set { set {
cmd = value; cmd = value ?? string.Empty;
} }
} }
@ -95,7 +95,7 @@ namespace ICSharpCode.NRefactory
return arg; return arg;
} }
set { set {
arg = value; arg = value ?? string.Empty;
} }
} }
@ -109,8 +109,8 @@ namespace ICSharpCode.NRefactory
public PreprocessingDirective(string cmd, string arg, Location start, Location end) public PreprocessingDirective(string cmd, string arg, Location start, Location end)
: base(start, end) : base(start, end)
{ {
this.cmd = cmd; this.Cmd = cmd;
this.arg = arg; this.Arg = arg;
} }
public override object AcceptVisitor(ISpecialVisitor visitor, object data) public override object AcceptVisitor(ISpecialVisitor visitor, object data)

2
src/Libraries/NRefactory/Project/Src/PrettyPrinter/AbstractOutputFormatter.cs

@ -23,6 +23,8 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
bool doNewLine = true; bool doNewLine = true;
AbstractPrettyPrintOptions prettyPrintOptions; AbstractPrettyPrintOptions prettyPrintOptions;
public bool IsInMemberBody { get; set; }
public int IndentationLevel { public int IndentationLevel {
get { get {
return indentationLevel; return indentationLevel;

4
src/Libraries/NRefactory/Project/Src/PrettyPrinter/IOutputAstVisitor.cs

@ -43,6 +43,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
string Text { string Text {
get; get;
} }
bool IsInMemberBody {
get;
set;
}
void NewLine(); void NewLine();
void Indent(); void Indent();
void PrintComment(Comment comment, bool forceWriteInPreviousBlock); void PrintComment(Comment comment, bool forceWriteInPreviousBlock);

2
src/Libraries/NRefactory/Project/Src/PrettyPrinter/SpecialNodesInserter.cs

@ -13,7 +13,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
{ {
public class SpecialOutputVisitor : ISpecialVisitor public class SpecialOutputVisitor : ISpecialVisitor
{ {
IOutputFormatter formatter; readonly IOutputFormatter formatter;
public SpecialOutputVisitor(IOutputFormatter formatter) public SpecialOutputVisitor(IOutputFormatter formatter)
{ {

13
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() public void PrintLineContinuation()
{ {
if (!LastCharacterIsWhiteSpace) if (!LastCharacterIsWhiteSpace)

66
src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs

@ -574,12 +574,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
outputFormatter.NewLine(); outputFormatter.NewLine();
if (!IsAbstract(propertyDeclaration)) { if (!IsAbstract(propertyDeclaration)) {
outputFormatter.IsInMemberBody = true;
++outputFormatter.IndentationLevel; ++outputFormatter.IndentationLevel;
exitTokenStack.Push(Tokens.Property); exitTokenStack.Push(Tokens.Property);
TrackedVisit(propertyDeclaration.GetRegion, data); TrackedVisit(propertyDeclaration.GetRegion, data);
TrackedVisit(propertyDeclaration.SetRegion, data); TrackedVisit(propertyDeclaration.SetRegion, data);
exitTokenStack.Pop(); exitTokenStack.Pop();
--outputFormatter.IndentationLevel; --outputFormatter.IndentationLevel;
outputFormatter.IsInMemberBody = false;
outputFormatter.Indent(); outputFormatter.Indent();
outputFormatter.PrintToken(Tokens.End); outputFormatter.PrintToken(Tokens.End);
@ -848,6 +850,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
outputFormatter.NewLine(); outputFormatter.NewLine();
if (!IsAbstract(methodDeclaration)) { if (!IsAbstract(methodDeclaration)) {
outputFormatter.IsInMemberBody = true;
BeginVisit(methodDeclaration.Body); BeginVisit(methodDeclaration.Body);
++outputFormatter.IndentationLevel; ++outputFormatter.IndentationLevel;
exitTokenStack.Push(isSub ? Tokens.Sub : Tokens.Function); exitTokenStack.Push(isSub ? Tokens.Sub : Tokens.Function);
@ -866,6 +869,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
} }
outputFormatter.NewLine(); outputFormatter.NewLine();
EndVisit(methodDeclaration.Body); EndVisit(methodDeclaration.Body);
outputFormatter.IsInMemberBody = false;
} }
return null; return null;
} }
@ -895,6 +899,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
outputFormatter.PrintToken(Tokens.CloseParenthesis); outputFormatter.PrintToken(Tokens.CloseParenthesis);
outputFormatter.NewLine(); outputFormatter.NewLine();
outputFormatter.IsInMemberBody = true;
++outputFormatter.IndentationLevel; ++outputFormatter.IndentationLevel;
exitTokenStack.Push(Tokens.Sub); exitTokenStack.Push(Tokens.Sub);
@ -903,6 +908,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
TrackedVisit(constructorDeclaration.Body, data); TrackedVisit(constructorDeclaration.Body, data);
exitTokenStack.Pop(); exitTokenStack.Pop();
--outputFormatter.IndentationLevel; --outputFormatter.IndentationLevel;
outputFormatter.IsInMemberBody = false;
outputFormatter.Indent(); outputFormatter.Indent();
outputFormatter.PrintToken(Tokens.End); outputFormatter.PrintToken(Tokens.End);
@ -2031,6 +2037,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
{ {
int op = 0; int op = 0;
switch (binaryOperatorExpression.Op) { switch (binaryOperatorExpression.Op) {
case BinaryOperatorType.Concat:
op = Tokens.ConcatString;
break;
case BinaryOperatorType.Add: case BinaryOperatorType.Add:
op = Tokens.Plus; op = Tokens.Plus;
break; break;
@ -2047,6 +2057,10 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
op = Tokens.Div; op = Tokens.Div;
break; break;
case BinaryOperatorType.DivideInteger:
op = Tokens.DivInteger;
break;
case BinaryOperatorType.Modulus: case BinaryOperatorType.Modulus:
op = Tokens.Mod; op = Tokens.Mod;
break; break;
@ -2100,13 +2114,11 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
TrackedVisit(binaryOperatorExpression.Right, data); TrackedVisit(binaryOperatorExpression.Right, data);
return null; return null;
case BinaryOperatorType.NullCoalescing: case BinaryOperatorType.NullCoalescing:
outputFormatter.PrintText("IIf("); outputFormatter.PrintText("If(");
TrackedVisit(binaryOperatorExpression.Left, data); TrackedVisit(binaryOperatorExpression.Left, data);
outputFormatter.PrintText(" Is Nothing, ");
TrackedVisit(binaryOperatorExpression.Right, data);
outputFormatter.PrintToken(Tokens.Comma); outputFormatter.PrintToken(Tokens.Comma);
outputFormatter.Space(); outputFormatter.Space();
TrackedVisit(binaryOperatorExpression.Left, data); TrackedVisit(binaryOperatorExpression.Right, data);
outputFormatter.PrintToken(Tokens.CloseParenthesis); outputFormatter.PrintToken(Tokens.CloseParenthesis);
return null; return null;
case BinaryOperatorType.LessThan: case BinaryOperatorType.LessThan:
@ -2232,31 +2244,9 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
break; break;
case AssignmentOperatorType.Add: case AssignmentOperatorType.Add:
op = Tokens.PlusAssign; 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; break;
case AssignmentOperatorType.Subtract: case AssignmentOperatorType.Subtract:
op = Tokens.MinusAssign; 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; break;
case AssignmentOperatorType.Multiply: case AssignmentOperatorType.Multiply:
op = Tokens.TimesAssign; op = Tokens.TimesAssign;
@ -2540,13 +2530,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
public override object TrackedVisitConditionalExpression(ConditionalExpression conditionalExpression, object data) public override object TrackedVisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
{ {
// No representation in VB.NET, but VB conversion is possible. outputFormatter.PrintText("If");
outputFormatter.PrintText("IIf");
outputFormatter.PrintToken(Tokens.OpenParenthesis); outputFormatter.PrintToken(Tokens.OpenParenthesis);
TrackedVisit(conditionalExpression.Condition, data); TrackedVisit(conditionalExpression.Condition, data);
outputFormatter.PrintToken(Tokens.Comma); outputFormatter.PrintToken(Tokens.Comma);
outputFormatter.Space();
TrackedVisit(conditionalExpression.TrueExpression, data); TrackedVisit(conditionalExpression.TrueExpression, data);
outputFormatter.PrintToken(Tokens.Comma); outputFormatter.PrintToken(Tokens.Comma);
outputFormatter.Space();
TrackedVisit(conditionalExpression.FalseExpression, data); TrackedVisit(conditionalExpression.FalseExpression, data);
outputFormatter.PrintToken(Tokens.CloseParenthesis); outputFormatter.PrintToken(Tokens.CloseParenthesis);
return null; 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) public override object TrackedVisitLambdaExpression(LambdaExpression lambdaExpression, object data)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

27
src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs

@ -149,18 +149,6 @@ namespace ICSharpCode.NRefactory.Visitors
return null; 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) public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
{ {
MethodDeclaration method = new MethodDeclaration { MethodDeclaration method = new MethodDeclaration {
@ -179,21 +167,6 @@ namespace ICSharpCode.NRefactory.Visitors
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) 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); base.VisitAssignmentExpression(assignmentExpression, data);
if (assignmentExpression.Op == AssignmentOperatorType.Assign && !(assignmentExpression.Parent is ExpressionStatement)) { if (assignmentExpression.Op == AssignmentOperatorType.Assign && !(assignmentExpression.Parent is ExpressionStatement)) {
AddInlineAssignHelper(); AddInlineAssignHelper();

2
src/Libraries/NRefactory/Test/NRefactoryTests.csproj

@ -144,7 +144,7 @@
<Compile Include="Output\VBNet\VBNetOutputTest.cs" /> <Compile Include="Output\VBNet\VBNetOutputTest.cs" />
<Compile Include="Output\VBNet\CSharpToVBConverterTest.cs" /> <Compile Include="Output\VBNet\CSharpToVBConverterTest.cs" />
<Compile Include="Output\CSharp\VBToCSharpConverterTest.cs" /> <Compile Include="Output\CSharp\VBToCSharpConverterTest.cs" />
<Compile Include="Output\SpecialOutputVisitor.cs" /> <Compile Include="Output\SpecialOutputVisitorTest.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Project\NRefactory.csproj"> <ProjectReference Include="..\Project\NRefactory.csproj">

106
src/Libraries/NRefactory/Test/Output/SpecialOutputVisitor.cs → src/Libraries/NRefactory/Test/Output/SpecialOutputVisitorTest.cs

@ -6,6 +6,7 @@
// </file> // </file>
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Parser;
@ -23,6 +24,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
parser.Parse(); parser.Parse();
Assert.AreEqual("", parser.Errors.ErrorOutput); Assert.AreEqual("", parser.Errors.ErrorOutput);
CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(); CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor();
outputVisitor.Options.IndentationChar = ' ';
outputVisitor.Options.TabSize = 2;
outputVisitor.Options.IndentSize = 2;
using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(),
outputVisitor)) { outputVisitor)) {
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
@ -38,6 +42,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
parser.Parse(); parser.Parse();
Assert.AreEqual("", parser.Errors.ErrorOutput); Assert.AreEqual("", parser.Errors.ErrorOutput);
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
outputVisitor.Options.IndentationChar = ' ';
outputVisitor.Options.TabSize = 2;
outputVisitor.Options.IndentSize = 2;
using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(),
outputVisitor)) { outputVisitor)) {
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
@ -53,8 +60,12 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
parser.Parse(); parser.Parse();
Assert.AreEqual("", parser.Errors.ErrorOutput); Assert.AreEqual("", parser.Errors.ErrorOutput);
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), List<ISpecial> specials = parser.Lexer.SpecialTracker.RetrieveSpecials();
outputVisitor)) { PreprocessingDirective.CSharpToVB(specials);
outputVisitor.Options.IndentationChar = ' ';
outputVisitor.Options.TabSize = 2;
outputVisitor.Options.IndentSize = 2;
using (SpecialNodesInserter.Install(specials, outputVisitor)) {
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
} }
Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
@ -80,7 +91,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
TestProgram("// before class\n" + TestProgram("// before class\n" +
"class A\n" + "class A\n" +
"{\n" + "{\n" +
"\t// in class\n" + " // in class\n" +
"}\n" + "}\n" +
"// after class"); "// after class");
} }
@ -91,7 +102,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
TestProgram("/* before class */\n" + TestProgram("/* before class */\n" +
"class A\n" + "class A\n" +
"{\n" + "{\n" +
"\t/* in class */\n" + " /* in class */\n" +
"}\n" + "}\n" +
"/* after class */"); "/* after class */");
} }
@ -104,9 +115,9 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
"/* block comment before */\n" + "/* block comment before */\n" +
"class A\n" + "class A\n" +
"{\n" + "{\n" +
"\t/* in class */\n" + " /* in class */\n" +
"\t// in class 2" + " // in class 2" +
"\t/* in class 3 */\n" + " /* in class 3 */\n" +
"}\n" + "}\n" +
"/* after class */\n" + "/* after class */\n" +
"// after class 2\n" + "// after class 2\n" +
@ -128,11 +139,11 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
{ {
TestProgram("enum Test\n" + TestProgram("enum Test\n" +
"{\n" + "{\n" +
"\t// a\n" + " // a\n" +
"\tm1,\n" + " m1,\n" +
"\t// b\n" + " // b\n" +
"\tm2\n" + " m2\n" +
"\t// c\n" + " // c\n" +
"}\n" + "}\n" +
"// d"); "// d");
} }
@ -141,11 +152,11 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
public void EnumVB() public void EnumVB()
{ {
TestProgramVB("Enum Test\n" + TestProgramVB("Enum Test\n" +
"\t' a\n" + " ' a\n" +
"\tm1\n" + " m1\n" +
"\t' b\n" + " ' b\n" +
"\tm2\n" + " m2\n" +
"\t' c\n" + " ' c\n" +
"End Enum\n" + "End Enum\n" +
"' d"); "' d");
} }
@ -155,26 +166,26 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
{ {
TestProgram(@"public class Class1 TestProgram(@"public class Class1
{ {
private bool test(int l, int lvw) private bool test(int l, int lvw)
{ {
#region Metodos Auxiliares #region Metodos Auxiliares
int i = 1; int i = 1;
return false; return false;
#endregion #endregion
} }
}"); }");
} }
[Test] [Test]
public void RegionInsideMethodVB() public void CommentsInsideMethodVB()
{ {
TestProgramVB(@"Public Class Class1 TestProgramVB(@"Public Class Class1
Private Function test(ByVal l As Integer, ByVal lvw As Integer) As Boolean Private Function test(ByVal l As Integer, ByVal lvw As Integer) As Boolean
' Begin ' Begin
Dim i As Integer = 1 Dim i As Integer = 1
Return False Return False
' End of method ' End of method
End Function End Function
End Class"); End Class");
} }
@ -199,10 +210,10 @@ End Class");
{ {
TestProgramCS2VB("class A { [PreserveSig] public void B(// comment\nint c) {} }", TestProgramCS2VB("class A { [PreserveSig] public void B(// comment\nint c) {} }",
"Class A\n" + "Class A\n" +
"\t\t' comment\n" + " ' comment\n" +
"\t<PreserveSig()> _\n" + " <PreserveSig()> _\n" +
"\tPublic Sub B(ByVal c As Integer)\n" + " Public Sub B(ByVal c As Integer)\n" +
"\tEnd Sub\n" + " End Sub\n" +
"End Class"); "End Class");
} }
@ -211,12 +222,29 @@ End Class");
{ {
TestProgram("class A\n" + TestProgram("class A\n" +
"{\n" + "{\n" +
"\t#if TEST\n" + " #if TEST\n" +
"\t[MyAttribute()]\n" + " [MyAttribute()]\n" +
"\t#endif\n" + " #endif\n" +
"\tpublic int Field;\n" + " public int Field;\n" +
"}\n" + "}\n" +
"#end if"); "#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");
}
} }
} }

38
src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs

@ -148,20 +148,6 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
"Next"); "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] [Test]
public void RaiseEvent() public void RaiseEvent()
{ {
@ -201,6 +187,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
"End If"); "End If");
} }
/*
[Test] [Test]
public void AnonymousMethod() public void AnonymousMethod()
{ {
@ -213,7 +200,6 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
"End Sub"); "End Sub");
} }
/*
[Test, Ignore("NRefactory cannot guess the anonymous method's return type")] [Test, Ignore("NRefactory cannot guess the anonymous method's return type")]
public void AnonymousMethodInVarDeclaration() 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] [Test]
public void StaticMethod() public void StaticMethod()
{ {
@ -346,7 +319,14 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter
public void NullCoalescing() public void NullCoalescing()
{ {
TestStatement("c = a ?? b;", 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] [Test]

21
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/ApplicationSettings.cs

@ -6,11 +6,13 @@
// </file> // </file>
using System; using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui.OptionPanels namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
@ -47,6 +49,9 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
b = helper.BindString("startupObjectComboBox", "StartupObject", TextBoxEditMode.EditEvaluatedProperty); b = helper.BindString("startupObjectComboBox", "StartupObject", TextBoxEditMode.EditEvaluatedProperty);
b.RegisterLocationButton(locationButton); b.RegisterLocationButton(locationButton);
foreach (IClass c in GetPossibleStartupObjects(project)) {
Get<ComboBox>("startupObject").Items.Add(c.FullyQualifiedName);
}
b = helper.BindString("applicationIconComboBox", "ApplicationIcon", TextBoxEditMode.EditEvaluatedProperty); b = helper.BindString("applicationIconComboBox", "ApplicationIcon", TextBoxEditMode.EditEvaluatedProperty);
Get<ComboBox>("applicationIcon").TextChanged += new EventHandler(ApplicationIconComboBoxTextChanged); Get<ComboBox>("applicationIcon").TextChanged += new EventHandler(ApplicationIconComboBoxTextChanged);
@ -66,6 +71,22 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
helper.AddConfigurationSelector(this); helper.AddConfigurationSelector(this);
} }
public static IList<IClass> GetPossibleStartupObjects(IProject project)
{
List<IClass> results = new List<IClass>();
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) void RefreshOutputNameTextBox(object sender, EventArgs e)
{ {
Get<TextBox>("outputName").Text = Get<TextBox>("assemblyName").Text + CompilableProject.GetExtension((OutputType)Get<ComboBox>("outputType").SelectedIndex); Get<TextBox>("outputName").Text = Get<TextBox>("assemblyName").Text + CompilableProject.GetExtension((OutputType)Get<ComboBox>("outputType").SelectedIndex);

91
src/Main/Base/Test/CodeConverterTests.cs

@ -166,6 +166,78 @@ namespace ICSharpCode.SharpDevelop.Tests
"End Sub"); "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] [Test]
public void ReferenceEqualityAndValueEquality() public void ReferenceEqualityAndValueEquality()
{ {
@ -266,6 +338,25 @@ namespace ICSharpCode.SharpDevelop.Tests
"MyArray = (int[,])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray(MyArray, new int[11, 11]);"); "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 #region InterfaceImplementation
[Test] [Test]
public void InterfaceImplementation1() public void InterfaceImplementation1()

272
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs

@ -21,6 +21,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
NRefactoryResolver _resolver; NRefactoryResolver _resolver;
ParseInformation _parseInfo; ParseInformation _parseInfo;
IProjectContent _pc; IProjectContent _pc;
public string RootNamespaceToStrip { get; set; }
public string StartupObjectToMakePublic { get; set; }
public IList<string> DefaultImportsToRemove { get; set; }
public CSharpToVBNetConvertVisitor(IProjectContent pc, ParseInformation parseInfo) public CSharpToVBNetConvertVisitor(IProjectContent pc, ParseInformation parseInfo)
{ {
@ -29,16 +32,54 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
_parseInfo = parseInfo; _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) IReturnType ResolveType(TypeReference typeRef)
{ {
return TypeVisitor.CreateReturnType(typeRef, _resolver); 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); base.VisitNamespaceDeclaration(namespaceDeclaration, data);
ToVBNetConvertVisitor v = new ToVBNetConvertVisitor(); if (RootNamespaceToStrip != null) {
compilationUnit.AcceptVisitor(v, data); 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; return null;
} }
@ -66,6 +107,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
} }
IMethod currentMethod = _resolver.CallingMember as IMethod; IMethod currentMethod = _resolver.CallingMember as IMethod;
CreateInterfaceImplementations(currentMethod, methodDeclaration, methodDeclaration.InterfaceImplementations); 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); return base.VisitMethodDeclaration(methodDeclaration, data);
} }
@ -164,40 +213,211 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
eventInvocation.Arguments)); 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) public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{ {
base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
if (_resolver.CompilationUnit == null) if (_resolver.CompilationUnit == null)
return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); return null;
base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); switch (binaryOperatorExpression.Op) {
if (binaryOperatorExpression.Op == BinaryOperatorType.Equality || binaryOperatorExpression.Op == BinaryOperatorType.InEquality) { case BinaryOperatorType.Equality:
// maybe we have to convert Equality operator to ReferenceEquality case BinaryOperatorType.InEquality:
ResolveResult left = _resolver.ResolveInternal(binaryOperatorExpression.Left, ExpressionContext.Default); ConvertEqualityToReferenceEqualityIfRequired(binaryOperatorExpression);
ResolveResult right = _resolver.ResolveInternal(binaryOperatorExpression.Right, ExpressionContext.Default); break;
if (left != null && right != null && left.ResolvedType != null && right.ResolvedType != null) { case BinaryOperatorType.Add:
IClass cLeft = left.ResolvedType.GetUnderlyingClass(); ConvertArgumentsForStringConcatenationIfRequired(binaryOperatorExpression);
IClass cRight = right.ResolvedType.GetUnderlyingClass(); break;
if (cLeft != null && cRight != null) { case BinaryOperatorType.Divide:
if ((cLeft.ClassType != ClassType.Struct && cLeft.ClassType != ClassType.Enum) ConvertDivisionToIntegerDivisionIfRequired(binaryOperatorExpression);
|| (cRight.ClassType != ClassType.Struct && cRight.ClassType != ClassType.Enum)) break;
{ }
// this is a reference comparison return null;
if (cLeft.FullyQualifiedName != "System.String") { }
// and it's not a string comparison, so we'll use reference equality
if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) { void ConvertEqualityToReferenceEqualityIfRequired(BinaryOperatorExpression binaryOperatorExpression)
binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality; {
} else { // maybe we have to convert Equality operator to ReferenceEquality
binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality; 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; 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);
}
}
}
}
} }
} }

Loading…
Cancel
Save