icsharpcode / CodeConverter

Convert code from C# to VB.NET and vice versa using Roslyn
https://icsharpcode.github.io/CodeConverter/
MIT License
842 stars 219 forks source link

C# -> VB: Target typed new does not convert #1112

Open jcbonnett opened 4 months ago

jcbonnett commented 4 months ago

Input code

using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace CMM_AutoPostProcess
{
    public class GetTargets2
    {
        public void Targets(string file)
        {
            string JobID;
            int FileNameStart;
            int FileNameLength;
            int row, i;
            bool closed;

            bool autoProcess;
            string Autofile;
            string? L;
            string Job;

            FileNameStart = file.LastIndexOf('\\') + 1;
            FileNameLength = file.Length - FileNameStart;
            JobID = file.Substring(FileNameStart, FileNameLength);

            // Convert to Uppercase
            JobID = JobID.ToUpper();

            // Find JobID in list and then extract relevant information
            i = 1;
            row = 0;
            do
            {
                try
                {
                    Job = "Test";

                    if (JobID.Contains(Job))
                    {
                        row = i;
                        autoProcess = true;
                    }
                    i++;
                }
                catch
                {
                    //Safe to skip
                }
            }
            while (row == 0);

            const string target = "Mesh";
            autoProcess = File.Exists(target);

            if (autoProcess)
            {
                Autofile = "Post.txt";
                var sw = new StreamWriter(Autofile);

                sw.WriteLine("$TEXT");
                sw.WriteLine("Endjob");
                sw.WriteLine("Execute");
                sw.WriteLine("$TXTEND");

                sw.Close();

                if (File.Exists(Autofile))
                {
                    var reader = new StreamReader(Autofile);
                    closed = false;
                    do
                    {
                        L = reader.ReadLine();

                        if (L == "$TXTEND")
                        {
                            closed = true;
                        }
                    }
                    while (!closed && reader.Peek() != -1);

                    reader.Close();
                    StreamWriter tw = new("runfile.txt");
                    string msg;

                    try
                    {
                        if (closed)
                        {
                            tw.WriteLine("Running software for " + JobID);
                            string AppRef = Path.Combine(
                                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                @"Microsoft\Windows\Start Menu\Programs\Zeiss BG VisionCare\CMMProcess.appref-ms");
                            if (File.Exists(AppRef))
                            {
                                new Process
                                {
                                    StartInfo = new ProcessStartInfo(AppRef)
                                    {
                                        UseShellExecute = true,
                                        CreateNoWindow = true,
                                        Arguments = Autofile
                                    }
                                }.Start();
                            }
                            else
                            {
                                msg = "Cannot find click-once application " + AppRef;
                                tw.WriteLine(msg);
                                MessageBox.Show(msg);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                         MessageBox.Show(ex.ToString());
                    }
                    finally
                    {
                        tw.Close();
                    }
                }
            }
            else
            {
                var sw = new StreamWriter("PostError.txt");
                sw.WriteLine("Did not manage to find any target information");
                sw.Close();
            }
        }
    }
}

Erroneous output

Imports System
Imports System.Diagnostics
Imports System.IO
Imports System.Windows.Forms

Namespace CMM_AutoPostProcess
    Public Class GetTargets2
        Public Sub Targets(file As String)
            Dim JobID As String
            Dim FileNameStart As Integer
            Dim FileNameLength As Integer
            Dim row, i As Integer
            Dim closed As Boolean

            Dim autoProcess As Boolean
            Dim Autofile As String
            Dim L As String?
            Dim Job As String

            FileNameStart = file.LastIndexOf("\"c) + 1
            FileNameLength = file.Length - FileNameStart
            JobID = file.Substring(FileNameStart, FileNameLength)

            ' Convert to Uppercase
            JobID = JobID.ToUpper()

            ' Find JobID in list and then extract relevant information
            i = 1
            row = 0
            Do
                Try
                    Job = "Test"

                    If JobID.Contains(Job) Then
                        row = i
                        autoProcess = True
                    End If
                    i += 1
                Catch
                    'Safe to skip
                End Try
            Loop While row = 0

            Const target = "Mesh"
            autoProcess = IO.File.Exists(target)

            If autoProcess Then
                Autofile = "Post.txt"
                Dim sw = New StreamWriter(Autofile)

                sw.WriteLine("$TEXT")
                sw.WriteLine("Endjob")
                sw.WriteLine("Execute")
                sw.WriteLine("$TXTEND")

                sw.Close()

                If IO.File.Exists(Autofile) Then
                    Dim reader = New StreamReader(Autofile)
                    closed = False
                    Do
                        L = reader.ReadLine()

                        If Equals(L, "$TXTEND") Then
                            closed = True
                        End If
                    Loop While Not closed AndAlso reader.Peek() <> -1

                    reader.Close()
                    ''' Cannot convert LocalDeclarationStatementSyntax, System.InvalidCastException: Unable to cast object of type 'Microsoft.CodeAnalysis.VisualBasic.Syntax.EmptyStatementSyntax' to type 'Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax'.
                    '''    at ICSharpCode.CodeConverter.VB.CommonConversions.RemodelVariableDeclaration(VariableDeclarationSyntax declaration)
                    '''    at ICSharpCode.CodeConverter.VB.MethodBodyExecutableStatementVisitor.VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
                    '''    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
                    '''    at ICSharpCode.CodeConverter.VB.CommentConvertingMethodBodyVisitor.DefaultVisit(SyntaxNode node)
                    ''' 
                    ''' Input:
                    '''                     System.IO.StreamWriter tw = new("runfile.txt");
                    ''' 
                    ''' 
                    Dim msg As String

                    Try
                        If closed Then
                            tw.WriteLine("Running software for " & JobID)
                            Dim AppRef = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft\Windows\Start Menu\Programs\Zeiss BG VisionCare\CMMProcess.appref-ms")
                            If IO.File.Exists(AppRef) Then
                                Call New Process With {
                                        .StartInfo = New ProcessStartInfo(AppRef) With {
        .UseShellExecute = True,
        .CreateNoWindow = True,
        .Arguments = Autofile
    }
}.Start()
                            Else
                                msg = "Cannot find click-once application " & AppRef
                                tw.WriteLine(msg)
                                MessageBox.Show(msg)
                            End If
                        End If
                    Catch ex As Exception
                        Call MessageBox.Show(ex.ToString())
                    Finally
                        tw.Close()
                    End Try
                End If
            Else
                Dim sw = New StreamWriter("PostError.txt")
                sw.WriteLine("Did not manage to find any target information")
                sw.Close()
            End If
        End Sub
    End Class
End Namespace

Expected output

In the above you can see a problem converting nested constructors just after "Call New Process With". Easy to fix with a local variable for StartInfo and un-nesting constructors.

There is also a problem with converting

System.IO.StreamWriter tw = new("runfile.txt");

but that is very new syntax. The exceptions seem to relate to this problem where there is no type after the new.

Details

Phase 1 of 2:

Phase 2 of 2:

Code conversion completed with 1 error 1 files have been written to disk. Please report issues at https://github.com/icsharpcode/CodeConverter/issues

GrahamTheCoder commented 4 months ago

Pre-conversion workaround: Use a code formatting tool to change all "target typed new" expressions to have the type name in