Browse Source

Improved C#->VB converter.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2655 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
b78db77094
  1. 2
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Project/CSharpToVBConverter.cs
  2. 44
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs
  3. 31
      src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs
  4. 11
      src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs
  5. 10
      src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs
  6. 38
      src/Libraries/NRefactory/Project/Src/Visitors/ToVBNetConvertVisitor.cs
  7. 40
      src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs
  8. 28
      src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs
  9. 14
      src/Main/Base/Project/Src/Project/MSBuildInternals.cs
  10. 58
      src/Main/Base/Project/Src/Util/ProcessRunner.cs
  11. 159
      src/Main/Base/Test/CodeConverterTests.cs
  12. 43
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs

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

@ -50,7 +50,7 @@ namespace VBNetBinding @@ -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;

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

@ -2340,7 +2340,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter @@ -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 @@ -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 @@ -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<ParameterDeclarationExpression> 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)

31
src/Libraries/NRefactory/Project/Src/Visitors/CSharpConstructsVisitor.cs

@ -72,6 +72,10 @@ namespace ICSharpCode.NRefactory.Visitors @@ -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 @@ -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 @@ -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 @@ -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") {

11
src/Libraries/NRefactory/Project/Src/Visitors/ConvertVisitorBase.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using ICSharpCode.NRefactory.Ast;
namespace ICSharpCode.NRefactory.Visitors
{
@ -14,6 +15,14 @@ namespace ICSharpCode.NRefactory.Visitors @@ -14,6 +15,14 @@ namespace ICSharpCode.NRefactory.Visitors
/// </summary>
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;
}
}
}

10
src/Libraries/NRefactory/Project/Src/Visitors/ToCSharpConvertVisitor.cs

@ -41,16 +41,6 @@ namespace ICSharpCode.NRefactory.Visitors @@ -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);

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

@ -105,25 +105,6 @@ namespace ICSharpCode.NRefactory.Visitors @@ -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 @@ -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;
}

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

@ -153,8 +153,16 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter @@ -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 @@ -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<int, int> 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 @@ -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()
{

28
src/Main/Base/Project/Src/Project/MSBuildEngineWorker.cs

@ -47,20 +47,22 @@ namespace ICSharpCode.SharpDevelop.Project @@ -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();

14
src/Main/Base/Project/Src/Project/MSBuildInternals.cs

@ -26,6 +26,12 @@ namespace ICSharpCode.SharpDevelop.Project @@ -26,6 +26,12 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary>
public static class MSBuildInternals
{
/// <summary>
/// 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.
/// </summary>
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 @@ -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")) {

58
src/Main/Base/Project/Src/Util/ProcessRunner.cs

@ -19,6 +19,7 @@ namespace ICSharpCode.SharpDevelop.Util @@ -19,6 +19,7 @@ namespace ICSharpCode.SharpDevelop.Util
/// </summary>
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 @@ -97,7 +98,7 @@ namespace ICSharpCode.SharpDevelop.Util
/// Gets the process exit code.
/// </summary>
public int ExitCode {
get {
get {
int exitCode = 0;
if (process != null) {
exitCode = process.ExitCode;
@ -118,7 +119,7 @@ namespace ICSharpCode.SharpDevelop.Util @@ -118,7 +119,7 @@ namespace ICSharpCode.SharpDevelop.Util
/// Waits for the process to exit.
/// </summary>
/// <param name="timeout">A timeout in milliseconds.</param>
/// <returns><see langword="true"/> if the associated process has
/// <returns><see langword="true"/> if the associated process has
/// exited; otherwise, <see langword="false"/></returns>
public bool WaitForExit(int timeout)
{
@ -155,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Util @@ -155,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Util
/// <param name="arguments">The command line arguments to
/// pass to the command.</param>
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 @@ -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();
}
/// <summary>
@ -230,9 +233,10 @@ namespace ICSharpCode.SharpDevelop.Util @@ -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);
}

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

@ -67,6 +67,7 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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
}
}

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

@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -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<string> DefaultImportsToRemove { get; set; }
@ -47,19 +47,21 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -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 @@ -125,7 +127,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
void CreateInterfaceImplementations(IMember currentMember, ParametrizedNode memberDecl, List<InterfaceImplementation> 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 @@ -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;
}
}
}

Loading…
Cancel
Save