Giter Site home page Giter Site logo

csharptovb's Introduction

languages products page_type name description
vb
dotnet-core
windows
Code Converter
CSharpToVB (Visual Basic)
C# to VB Converter

Build status badge

C# to VB.Net Converter

Requires

  • Visual Studio 2022 Version 17.3 or later
  • .NET Core 6.0 to use the converter

License

  • MIT

Technologies

  • Windows Forms
  • dotnet-core

Topics

  • Code Converter

Release Download

https://github.com/paul1956/CSharpToVB/releases/C#ToVB5.0.7.0.zip

Updated

  • 6/27/2022

Description

This application will convert C# to VB while trying to preserve comments, formatting and as many Directives as possible. It converts the True side of conditional directives, the False side is not converted. After conversion it tries to compile the code. If a file can't be compiled it can be add to an ignore list so you can continue to process other files.

You can convert text by typing or pasting in into the left Window, a file, project or folder from the menu's.

The Tests under "TestCompile" are designed to translate the C# code in Roslyn and uses GetRoslynRootDirectory to find it. Results of folder conversion are stored in with the same directory structure with the root directory renamed to _VB. The original directories are unchanged.

This version required at least Visual Studio 2019 version 16.3.0 to compile the code it produces because it uses the new Visual Basic feature _ ' Comment to preserve most comments and formatting. To build the converter application, Visual Studio 2019 Version 16.11.9 or Visual Studio 2022 and .Net Core 6.0

Opening the resulting Visual Basic files in Visual Studio will further improve the formatting.

The last five files compiled are saved in an MRU list and you can save the edited Source windows into a Snippet and reload it. This is useful when you are debugging and want to focus on the lines that are a problem. You can search Input or Output buffers and hide the search options by clicking on the X. You can stop folder conversion with the Stop button. You can restart from where you left off by selecting the option "Start Conversion from last file" or start at the beginning by deselecting this option, if this version is selected and you switch to convert a new folder the application will immediately return done and you will need to deselect the option. You can show or hide line numbers from the View Menu.

Work to be done: There are several Stop statements for debugging, and if you continue past them reasonable things will happen but a better translation is possible.

Important Notes

https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json is added to NuGet Package Source to find Microsoft.Dotnet.XUnitExtensions which provides ConditionalFact and PlatformSpecific attributes used for testing.

Any changes to CSharpToVB application needs to change the version information in the project file AND in MyProject/AssemblyInfo.vb until Visual Studio is able to general file automatically for a WinForms application.

What's New in this release

New in 5.0.7.0/5.0.2.11 Fix issue Pattern matching issues #83, add tests Add dark icons for menus Minor updates for CodeStyle violations

New in 5.0.6.5/5.0.2.10 Fix crash in project conversion Update Icons

New in 5.0.6.4/5.0.2.9 Update NuGet Packages and use IsKind instead of Kind

New in 5.0.6.3/5.0.2.8 Fix Cy.yml file to use .Net 6.0 Fix Form1.Designer to set Me.TSFindLookInComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList and remove setting in Form1

New in 5.0.6.1/5.0.2.7 Fix Crash in VisitEventDeclaration also preserve comments in Event Handlers

New in 5.0.6.1/5.0.2.6 Fix for #80

New in 5.0.6.1/5.0.2.4 Fix search dropdown to not use Simple to prevent toolstrip from growing

New in 5.0.6.0/5.0.2.4 Update to use .Net 6.0 Fix Issue #81

New in 5.0.4.0/5.0.2.2

  • Mostly cleanup

New in 5.0.4.0/5.0.2.1

  • Do a better job at not renaming Types
  • Local Types that conflict with Type names in Libraries will not be renamed

New in 5.0.4.0/5.0.2.0

  • Redesign of Event handling
  • Stopped renaming of object initializers

New in 5.0.4.0/5.0.1.22

  • Fix issue #76
  • Major improvement is project and solution conversion
  • Major improvement in custom event and invoke event handling

New in 5.0.3.5/5.0.1.21

  • Fixed issue #77
  • Small workaround for "path"

New in 5.0.3.5/5.0.1.20

  • Fixed issue #78

New in 5.0.3.5/5.0.1.19

  • Add support for Tuple ImplicitElementAccess
  • Fix new icon sizes

New in 5.0.3.4/5.0.1.18

  • Change logic for update checking
  • Better support dark mode with transparent icons

New in 5.0.3.3/5.0.1.18

  • Improved code that checks for updates and make it Async

New in 5.0.3.2/5.0.1.18

  • Improved fix for issue #75

New in 5.0.3.2/5.0.1.16

  • Fixes issue #74 conversion of "this" in Sub New for Class

New in 5.0.3.2/5.0.1.15

  • Add Update not available Icon

New in 5.0.3.1/5.0.1.15

  • Change Interlocked.Increment to Threading.Interlocked.Increment to partly address issue #72
  • Improve support for Dark Mode

New in 5.0.3.0/5.0.1.14

  • Major improvement in colorize performance
  • Improvement in StopButton responsiveness
  • Remove unused parameters

New in 5.0.2.13/5.0.1.14

  • Improve conversion of dynamic types
  • Improve converting += of strings to &=
  • When pasting into conversion buffers respect colorize settings

New in 5.0.2.12/5.0.1.13

  • Add support for Code Colorization on Paste

New in 5.0.2.11/5.0.1.13

  • Improve editing experience, remove old Color Mode code

New in 5.0.2.10/5.0.1.13

  • Fix crash when coloring code with no failures

New in 5.0.2.9/5.0.1.13

  • Very preliminary Dark Mode support based on work by @DualBrain

New in 5.0.2.8/5.0.1.13

  • Fix duplicate last statement when Switch expression is converted
  • Update Code Coverage which is now almost 95%
  • Correct spelling errors and eliminate more unused code
  • Fix Spelling errors in variable names and comments

New in 5.0.2.7/5.0.1.12

  • Fix Search to correctly put found text at top of visible window.
  • Speed up Trivia Conversion.
  • Improve Handling of Conditional Directives, using Comments where necessary

New in 5.0.2.6/5.0.1.11

  • Fix conversion of Lambda functions with multiple discard parameters
  • Update Roslyn Tests to only run if Environment variable "EnableRoslynTests" is set to "True"

New in 5.0.2.6/5.0.1.10

  • Fix conversion of Lambda functions with discard parameter

New in 5.0.2.6/5.0.1.9

  • Fix issue #72

New in 5.0.2.6/5.0.1.8

  • Fix messages for issue #70

New in 5.0.2.5/5.0.1.8

  • Fix version checking to correctly use Version.Parse and logic for detecting Generated Code

New in 5.0.2.4/5.0.1.8

  • Improve update needed checker logic

New in 5.0.2.3/5.0.1.8

  • Remove duplicate #endif trivia and converted comment

New in 5.0.2.3/5.0.1.7

  • Improve handling of empty CSS.BlockSyntax
  • Add update code coverage showing increase in Method coverage to 90%

New in 5.0.2.3/5.0.1.6

  • Fix Attributes in Enum list

New in 5.0.2.3/5.0.1.5

  • Ignore CA1826 for OrDefault extensions
  • Update IntPtr Arrays in TypeSyntax
  • Prevent application crash when compiler crashes

New in 5.0.2.2/5.0.1.4

  • Remove ~50 redundant test
  • Support IntPtr Arrays
  • Fix Interfaces properties that contain VB reserved names

New in 5.0.2.2/5.0.1.3

  • Make sure MethodStatements end in EOL
  • Use ProfessionalRender for ContextStrip. MenuStrip and ToolStrip
  • Don't convert .cs files that really contain VB code.
  • Handle multi-line Attributes with comments

New in 5.0.2.0/5.0.1.1

  • Update default Font Setting for conversion buffers
  • Add helper for removing Option statements from result.

New in 5.0.1.5/5.0.1.0

  • Fix comments in ConditionalExpressions
  • Support additional places where directives are not allowed
  • Don't allow TopLevelStatement(TLS) conversion when buffer does not contain TLS and only allow snippet conversion for TLS's.
  • Add support for DLL definitions done as local functions

New in 5.0.1.4/5.0.0.29

  • Improve InitializerExpressionSyntax conversion

New in 5.0.1.4/5.0.0.28

  • Fixed Issues/67
  • Fixed Sub Main removal in top level code

New in 5.0.1.3/5.0.0.27

  • General code cleanup around Theme support

New in 5.0.1.1/5.0.0.27

  • Drop ReadOnly when converting Struct
  • Fix conversion of non value Nullable Types

New in 5.0.1.1/5.0.0.25

  • Add support for exact translation of Top Level Statements, this could be improved by deleting extra lines in output
  • Add theme support for Light and Dark Mode

New in 5.0.0.29/5.0.0.24

  • Improve edit experience of Colorized buffers

New in 5.0.0.28/5.0.0.24

  • Set edit buffers to read-only instead of Disabled when colorizing

New in 5.0.0.27/5.0.0.24

  • Improve Colorization to handle Regex and SubStrings, a new function AdjustAdditiveSpans was added to merger the new spans it would use a good design review.

New in 5.0.0.25/5.0.0.24

  • Fix Cref conversions
  • Add more Stops before throw to help debug
  • Change color from Yellow to Purple for String Escape

New in 5.0.0.25/5.0.0.23

  • Fix issue #63

New in 5.0.0.25/5.0.0.22

  • Improve ++ and -- handling and use more existing keywords and tokens

New in 5.0.0.25/5.0.0.21

  • Implement ToString for Records

New in 5.0.0.25/5.0.0.20

  • Add support for foreach variable with variable is a Tuple
  • Fix custom events to include RaiseEvent
  • Fix when Namespace and Class names are the same just differing by case

New in 5.0.0.25/5.0.0.19

  • Clean up Tuple Deconstruction
  • Optimize some trivia by creating them at startup
  • Fixes issues #56-58 and #61

New in 5.0.0.25/5.0.0.18

  • Fix removing ? from Nullable Strings and Objects

New in 5.0.0.24/5.0.0.17

  • Improve support C# 9.0 WithExpressions, including inherited Records
  • Cleanup and organize VisualBasicSyntaxFactory

New in 5.0.0.23/5.0.0.17

  • Improve support C# 9.0 WithExpressions
  • Add first unit test for WithExpressions

New in 5.0.0.23/5.0.0.16

  • Support C# 9.0 WithExpressions

New in 5.0.0.23/5.0.0.15

  • Application UI Changes

    • Fix Copy of items from File List in main UI using keyboard
  • Converter Changes

    • Add initial support for ImplicitObjectCreationExpression new()
    • Add support for "Using" local declarations from C# 8
    • Support Directives in Class header including implements, inherits, Directives are moved to end but logic is maintained

Not all cases may be covered for new features so please provide feedback

New in 5.0.0.22/5.0.0.14

  • Fix translation of Nullable Strings and some complex strings
  • Fix Roslyn Test where a .cs file only has VB code

New in 5.0.0.22/5.0.0.13

  • Fix ArrowExpression conversion that were sometime being converted to Functions instead of Subs when returning void

New in 5.0.0.22/5.0.0.12

  • Add limited support for init accessors

New in 5.0.0.22/5.0.0.11

  • Fix crash if MRU file is deleted
  • Run VB Code Cleanup and fix Name format violations

New in 5.0.0.21/5.0.0.10

  • Improve and simplify update notification handling

New in 5.0.0.20/5.0.0.10

  • Convert notify to StatusStrip Notify icon.

New in 5.0.0.19/5.0.0.10

  • Fixed formatting in ReadMe.MD file
  • Add ability to check for newer Master versions on GitHub automatically on startup and manually under Help

New in 5.0.0.18/5.0.0.10

  • Fixed Issue #55 Editing keys now work in edit buffers in addition to Edit and Context Menus
  • Fixed Issue #54 Guard against crash when LineNumbersForRichTextBox.Parent is nothing
  • Fixed Issue #53 Create a discard function when a C# discard assign (_) is converted to __ in VB
  • Fixed Issue #51 scoping of nested Blocks

New in 5.0.0.17/5.0.0.9

  • Fixed Issue #52 Merged fix by @elGuille-info to handle "Add Public to Sub Main when declared in non static class in C#"

New in 5.0.0.17/5.0.0.8

  • Fixed crash when trying to set controls in StartUp Form from MyApplication_Startup
  • Change default for editor buffers font to Consolas, added support for user to change font to anything they want, and save changes
  • Better handle Dim X = New Y to use "As" more often

New in 5.0.0.16/5.0.0.7

  • Fix issue where progress reporting was not happening
  • Use TextRenderer where easy to make text more readable

New in 5.0.0.15/5.0.0.7

  • Fix corner case with converting Dictionary types
  • Add support for display of Shortcut keys on Edit menu items
  • Update formating to comply with .editorConfig

New in 5.0.0.14/5.0.0.6

  • Fix Equals to Convert Record to Class (may not be complete yet)
  • Fix For Each where ElementType was not always used for loop variable type
  • Cleanup more style violations

New in 5.0.0.14/5.0.0.5

  • Add Equals to Convert Record to Class (may not be complete yet)

New in 5.0.0.14/5.0.0.4

  • Convert Record to Class (may not be complete yet)

New in 5.0.0.12/5.0.0.3

  • No logic changes, extensive formatting changes to support camelCase for locals

New in 5.0.0.11/5.0.0.2

  • Fix Yield as Reserved word
  • Formatting around New and Dim statement initializer starting on new line

New in 5.0.0.11/5.0.0.1

  • Fix Await Statements to not do temp assignments
  • Fix add and remove handler for SimpleMemberAccessExpressions

In Process

  • Simplify Trivia restructuring removing duplicate code
  • Finish supporting skipped test
  • Improvements in Formating long binary, octal and hex numbers as strings using _ separator

Code Coverage

+------------------+-------+--------+--------+
| Module           | Line  | Branch | Method |
+------------------+-------+--------+--------+
| VB.CodeConverter | 85.3% | 78.04% | 94.81% |
+------------------+-------+--------+--------+

+---------+-------+--------+--------+
|         | Line  | Branch | Method |
+---------+-------+--------+--------+
| Total   | 85.3% | 78.04% | 94.81% |
+---------+-------+--------+--------+
| Average | 85.3% | 78.04% | 94.81% |
+---------+-------+--------+--------+

csharptovb's People

Contributors

jnm2 avatar paul1956 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

csharptovb's Issues

Converting "variable scope" blocks.

It is relatively common to encounter C# code where variable scoping blocks are in use.

I recently encountered such when working on converting tests for the VB runtime:

    [Fact]
    public void Close()
    {
        var path = GetTestFilePath();
        File.WriteAllText(path, "abc123");
        // ...
        using (var parser = new TextFieldParser(path))
        {
            parser.Close();
        }
       // ...
        {
            TextFieldParser parser;
            using (parser = new TextFieldParser(path))
            {
            }
            parser.Close();
        }
    }

As you can see in the second block, the local parser variable is used "again" - but it's a new/different parser variable.

The simplest way to do something similar in VB (which I do rather regularly - unrelated to converting code) is to:

If True Then
    ' We now have a separate variable scope.
End If

So the question is can you detect these types of block and replace them with the If True Then ... End If blocks?

Enable Windows visual styles

I think in order to do this you have to change the project startup object to Sub Main and put this code inside Program.Main:

Application.EnableVisualStyles()
Application.Run(New Form1())

Indentation is not preserved in array literal

Source lines: https://github.com/dotnet/roslyn/blob/c0a1d1ec94efc2b4fcc2334580c84741e10e45ef/src/EditorFeatures/CSharpTest/SimplifyInterpolation/SimplifyInterpolationTests.cs#L40-L42

Expected:

                Assert.Equal(
                    {
                        ("IDE0071", DiagnosticSeverity.Info),
                        ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden),
                        ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden)

Expected (alternative):

                Assert.Equal({
                    ("IDE0071", DiagnosticSeverity.Info),
                    ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden),
                    ("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden)

Actual:

            Assert.Equal( _
                { _
("IDE0071", DiagnosticSeverity.Info),
("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden),
("IDE0071WithoutSuggestion", DiagnosticSeverity.Hidden)},

Me.New and MyBase.New

You convert this:

public Buyer(string identity) : this()

to:

Public Sub New(identity As String)
    MyBase.New()
End sub

but it should be:

Public Sub New(identity As String)
    Me.New()
End sub

Small things to Fix

Well done @
This is a very good converter, but I have some notes:

  1. I tried to convert a solution, but get a MsgBox saying something about Nugets. So I converted the folder instead.

  2. When converting the Namespace statement, try to exclude the root namespace, because it is the default namespace in VB
    in C#:
    Namespace Microsoft.eShopWeb.Infrastructure.Data
    in VB:
    Namespace Data

The project name is Infrastructure and the default namespace is Microsoft.eShopWeb.Infrastructure
This info stored in the .csprog file. Try to consider parsing it when converting a folder that contains it.

  1. A common error I face in converters, is to inherit an interface:
    Public Class CatalogTypeConfiguration
        Inherits IEntityTypeConfiguration(Of CatalogType)

If the name doesn't start with I , inherit, otherwise, search all files in the directly for class IEntityTypeConfiguration or interface IEntityTypeConfiguration to take an accurate decision. inheriting an interface means that all methods will miss the Implements part, and this needs a long manual correction.

  1. AddressOf is added for lamdas:
    Input:
    _items.RemoveAll(i => i.Quantity == 0);
    Output:
    _items.RemoveAll(AddressOf Function(i) i.Quantity = 0)

  2. you renamed a property BuyerId to BuyerId_Renamed because there is a param in the constructor with the same name but small cased buyerId. This caused errors in other files calling this property.
    It is not a problem in VB to have a param and a property with the same name. You just add Me. before the name of the property in the assignment:
    Me.BuyerId= buyerId

Hope you fix these, to have a perfect converter.
Thanks again. It is really useful.

Name clashes

Input

public class ClashingNames
{
    private string ab;

    void Test()
    {
        object aB = 5;
        int Ab = 7;
    }

    void Test2(int ab)
    {
        object aB = 5;
        int AB =  6;
        string s = nameof(AB);
        string s2 = nameof(ab);
    }
}

Expected output (from https://codeconverter.icsharpcode.net/)

Public Class x
    Private ab As String

    Private Sub Test()
        Dim lAB As Object = 5
        Dim Ab As Integer = 7
    End Sub

    Private Sub Test2(ByVal ab As Integer)
        Dim lAB As Object = 5
        Dim lAB1 As Integer = 6
        Dim s As String = NameOf(lAB1)
        Dim s2 As String = NameOf(ab)
    End Sub
End Class

Actual output

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On


Public Class x
    Private _ab As String

    Private Sub Test()
        Dim aB As Object = 5
        Dim Ab As Integer = 7
    End Sub

    Private Sub Test2(_ab As Integer)
        Dim aB As Object = 5
        Dim AB As Integer = 6
        Dim s As String = NameOf(AB)
        Dim s2 As String = NameOf(_ab)
    End Sub


End Class

Compilation errors

error BC30288: Local variable 'Ab' is already declared in the current block.
error BC30288: Local variable 'AB' is already declared in the current block.
  • Note: Obviously this is an extreme example. I did see the existing renaming code add "_Renamed" for one variable in another case I tried, so it does sometimes work.

Possible solution

After you forked from https://github.com/icsharpcode/CodeConverter/ I implemented a very robust and isolated way of renaming to avoid this issue. All you need to do is call this method on the project object just before you convert:
https://github.com/icsharpcode/CodeConverter/blob/master/CodeConverter/VB/ClashingMemberRenamer.cs#L21

It's not currently a public class, but I could make it public if you want to just use it via nuget rather than copying/converting?

Underscores are generated for multiline statements when not necessary

<RepositoryType> vbproj property isn't standard or might be invalid

The reason for the <RepositoryType> property is to specify the .nuspec <repository type= attribute value. I've never seen the value GitHub before; with GitHub projects, everyone uses git that I've seen. The <RepositoryType> value is referring to the protocol used to programmatically connect to the <repository url= URL.

https://docs.microsoft.com/en-us/nuget/reference/nuspec#repository shows an example which has a GitHub URL and a git repository type, so I'm pretty sure that's what it should be:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        ...
        <repository type="git" url="https://github.com/NuGet/NuGet.Client.git" branch="dev" commit="e1c65e4524cd70ee6e22abe33e6cb6ec73938cb3" />
        ...
    </metadata>
</package>

Enclose New with []

C#:

var x = Expression.New(constructor, parameter1, parameter2);

VB:

Private x = Expression.New(constructor, parameter1, parameter2)

Vb realizes the .New as a call to the constructor. Use .[New] as C# means to call a method named New. This differs than using base in C# that translates to a call to the MyBase.New . The result should be:
VB:

Private x = Expression.[New](constructor, parameter1, parameter2)

Change Bottom TextBox to List Boxes

The bottom TextBox that show file names, can be 2 list boxes, so we can double click on any item to view its content in both languages. and keep the two list sync: always select the same index in both.

Better would be to make Left box be file without extension and when clicked open source and destination file.

Could not load file or assembly NuGet.Versioning

The program shows this error message for all the csprojs that I've tried so far. Example:

https://github.com/Techsola/AmbientTasks/blob/d5a686e8dae0c578b7fe5487a5302d2dd52fd340/src/AmbientTasks/AmbientTasks.csproj

Msbuild failed when processing the file 'C:\Users\Joseph\Source\Repos\AmbientTasks\src\AmbientTasks\AmbientTasks.csproj' with message:Msbuild failed when processing the file 'C:\Users\Joseph C:\Program Files\dotnet\sdk\3.1.200-preview-015002\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets: (160, 5): The "GetAssemblyVersion" task failed unexpectedly.
System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.Versioning, Version=5.5.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
File name: 'NuGet.Versioning, Version=5.5.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
at Microsoft.NET.Build.Tasks.GetAssemblyVersion.ExecuteCore()
at Microsoft.NET.Build.Tasks.TaskBase.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

when clause in the case label

Input

Object o = "demo";

switch (o)
{
    case IEnumerable<string> s :
        Console.WriteLine("1"); break;
    case string s when s.Length > 5 :
        Console.WriteLine("2"); break;
    case string s :
        Console.WriteLine("3"); break;		
    default:
        Console.WriteLine("4"); break;
}
//result : 3

Actual output

Private o As [Object] = "demo"

Select Case True
    Case TypeOf o Is IEnumerable(Of String)
        Dim s As IEnumerable(Of String) = CType(o, IEnumerable(Of String))
        Console.WriteLine("1")
    Case TypeOf o Is String
        Dim s As String = CType(o, String)
        If Not TypeOf o Is String Then Exit Select
        Console.WriteLine("2")
    Case TypeOf o Is String
        Dim s As String = CType(o, String)
        Console.WriteLine("3")
    Case Else
        Console.WriteLine("4")
End Select
'!!! result : 2

Proposal

add a "TODO Check : " comment to the generated code

Add Public to Sub Main when declared in non static class in C#

Your code:

Dim modifiers As List(Of SyntaxToken)
If Me.IsModule AndAlso
    methodNameToken.ValueText = "Main" AndAlso
    node.Modifiers.Count = 1 AndAlso
    node.Modifiers(0).ValueText = "static" Then
    modifiers = PublicModifier.ToList
Else
    modifiers = ConvertModifiers(node.Modifiers, Me.IsModule, If(containingType?.IsInterfaceType() = True, TokenContext.Local, TokenContext.Member)).ToList
End If

I changed to this and works in all the test I made:
Declaring the class static or not.

The only thing is that Remove seems not to work on the List(Of SyntaxToken) and I use a simple for/netxt (and works!)

Dim modifiers As List(Of SyntaxToken)
If methodNameToken.ValueText = "Main" AndAlso
    node.Modifiers.Count = 1 AndAlso
    node.Modifiers(0).ValueText = "static" Then
    If Me.IsModule Then
        modifiers = PublicModifier.ToList
    Else
        modifiers = PublicModifier.ToList
        modifiers.AddRange(ConvertModifiers(node.Modifiers, Me.IsModule, If(containingType?.IsInterfaceType() = True, TokenContext.Local, TokenContext.Member)).ToList)
        ' Esto no funciona, no quita el privado
        'modifiers.Remove(PrivateKeyword)
        Dim index As Integer = -1
        For i As Integer = modifiers.Count - 1 To 0 Step -1
            If modifiers(i).Text = PrivateKeyword.Text Then
                index = i
                Exit For
            End If
        Next
        If index > -1 Then
            modifiers.RemoveAt(index)
        End If
    End If
Else
    modifiers = ConvertModifiers(node.Modifiers, Me.IsModule, If(containingType?.IsInterfaceType() = True, TokenContext.Local, TokenContext.Member)).ToList
End If

File: CSharpToVB\CodeConverter\CSharpToVBVisitors\DeclarationVisitor.vb

Guillermo

Task_Renamed!

C#:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;

namespace Microsoft.AspNetCore.Mvc.Razor
{
    /// <summary>
    /// Represents properties and methods that are needed in order to render a view that uses Razor syntax.
    /// </summary>
    public abstract class RazorPage : RazorPageBase
    {
        private readonly HashSet<string> _renderedSections = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        private bool _renderedBody;
        private bool _ignoreBody;
        private HashSet<string> _ignoredSections;

        /// <summary>
        /// An <see cref="HttpContext"/> representing the current request execution.
        /// </summary>
        public HttpContext Context => ViewContext?.HttpContext;

        /// <summary>
        /// In a Razor layout page, renders the portion of a content page that is not within a named section.
        /// </summary>
        /// <returns>The HTML content to render.</returns>
        protected virtual IHtmlContent RenderBody()
        {
            if (BodyContent == null)
            {
                var message = Resources.FormatRazorPage_MethodCannotBeCalled(nameof(RenderBody), Path);
                throw new InvalidOperationException(message);
            }

            _renderedBody = true;
            return BodyContent;
        }

        /// <summary>
        /// In a Razor layout page, ignores rendering the portion of a content page that is not within a named section.
        /// </summary>
        public void IgnoreBody()
        {
            _ignoreBody = true;
        }

        /// <summary>
        /// Creates a named content section in the page that can be invoked in a Layout page using
        /// <see cref="RenderSection(string)"/> or <see cref="RenderSectionAsync(string, bool)"/>.
        /// </summary>
        /// <param name="name">The name of the section to create.</param>
        /// <param name="section">The <see cref="RenderAsyncDelegate"/> to execute when rendering the section.</param>
        public override void DefineSection(string name, RenderAsyncDelegate section)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (section == null)
            {
                throw new ArgumentNullException(nameof(section));
            }

            if (SectionWriters.ContainsKey(name))
            {
                throw new InvalidOperationException(Resources.FormatSectionAlreadyDefined(name));
            }
            SectionWriters[name] = section;
        }

        /// <summary>
        /// Returns a value that indicates whether the specified section is defined in the content page.
        /// </summary>
        /// <param name="name">The section name to search for.</param>
        /// <returns><c>true</c> if the specified section is defined in the content page; otherwise, <c>false</c>.</returns>
        public bool IsSectionDefined(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            EnsureMethodCanBeInvoked(nameof(IsSectionDefined));
            return PreviousSectionWriters.ContainsKey(name);
        }

        /// <summary>
        /// In layout pages, renders the content of the section named <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the section to render.</param>
        /// <returns>An empty <see cref="IHtmlContent"/>.</returns>
        /// <remarks>The method writes to the <see cref="RazorPageBase.Output"/> and the value returned is a token
        /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        /// value does not represent the rendered content.</remarks>
        public HtmlString RenderSection(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            return RenderSection(name, required: true);
        }

        /// <summary>
        /// In layout pages, renders the content of the section named <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The section to render.</param>
        /// <param name="required">Indicates if this section must be rendered.</param>
        /// <returns>An empty <see cref="IHtmlContent"/>.</returns>
        /// <remarks>The method writes to the <see cref="RazorPageBase.Output"/> and the value returned is a token
        /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        /// value does not represent the rendered content.</remarks>
        public HtmlString RenderSection(string name, bool required)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            EnsureMethodCanBeInvoked(nameof(RenderSection));

            var task = RenderSectionAsyncCore(name, required);
            return task.GetAwaiter().GetResult();
        }

        /// <summary>
        /// In layout pages, asynchronously renders the content of the section named <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The section to render.</param>
        /// <returns>
        /// A <see cref="Task{HtmlString}"/> that on completion returns an empty <see cref="IHtmlContent"/>.
        /// </returns>
        /// <remarks>The method writes to the <see cref="RazorPageBase.Output"/> and the value returned is a token
        /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        /// value does not represent the rendered content.</remarks>
        public Task<HtmlString> RenderSectionAsync(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            return RenderSectionAsync(name, required: true);
        }

        /// <summary>
        /// In layout pages, asynchronously renders the content of the section named <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The section to render.</param>
        /// <param name="required">Indicates the <paramref name="name"/> section must be registered
        /// (using <c>@section</c>) in the page.</param>
        /// <returns>
        /// A <see cref="Task{HtmlString}"/> that on completion returns an empty <see cref="IHtmlContent"/>.
        /// </returns>
        /// <remarks>The method writes to the <see cref="RazorPageBase.Output"/> and the value returned is a token
        /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        /// value does not represent the rendered content.</remarks>
        /// <exception cref="InvalidOperationException">if <paramref name="required"/> is <c>true</c> and the section
        /// was not registered using the <c>@section</c> in the Razor page.</exception>
        public Task<HtmlString> RenderSectionAsync(string name, bool required)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            EnsureMethodCanBeInvoked(nameof(RenderSectionAsync));
            return RenderSectionAsyncCore(name, required);
        }

        private async Task<HtmlString> RenderSectionAsyncCore(string sectionName, bool required)
        {
            if (_renderedSections.Contains(sectionName))
            {
                var message = Resources.FormatSectionAlreadyRendered(nameof(RenderSectionAsync), Path, sectionName);
                throw new InvalidOperationException(message);
            }

            if (PreviousSectionWriters.TryGetValue(sectionName, out var renderDelegate))
            {
                _renderedSections.Add(sectionName);

                await renderDelegate();

                // Return a token value that allows the Write call that wraps the RenderSection \ RenderSectionAsync
                // to succeed.
                return HtmlString.Empty;
            }
            else if (required)
            {
                // If the section is not found, and it is not optional, throw an error.
                var viewContext = ViewContext;
                throw new InvalidOperationException(
                    Resources.FormatSectionNotDefined(
                        viewContext.ExecutingFilePath,
                        sectionName,
                        viewContext.View.Path));
            }
            else
            {
                // If the section is optional and not found, then don't do anything.
                return null;
            }
        }

        /// <summary>
        /// In layout pages, ignores rendering the content of the section named <paramref name="sectionName"/>.
        /// </summary>
        /// <param name="sectionName">The section to ignore.</param>
        public void IgnoreSection(string sectionName)
        {
            if (sectionName == null)
            {
                throw new ArgumentNullException(nameof(sectionName));
            }

            if (!PreviousSectionWriters.ContainsKey(sectionName))
            {
                // If the section is not defined, throw an error.
                throw new InvalidOperationException(Resources.FormatSectionNotDefined(
                    ViewContext.ExecutingFilePath,
                    sectionName,
                    ViewContext.View.Path));
            }

            if (_ignoredSections == null)
            {
                _ignoredSections = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            }

            _ignoredSections.Add(sectionName);
        }

        /// <inheritdoc />
        public override void EnsureRenderedBodyOrSections()
        {
            // a) all sections defined for this page are rendered.
            // b) if no sections are defined, then the body is rendered if it's available.
            if (PreviousSectionWriters != null && PreviousSectionWriters.Count > 0)
            {
                var sectionsNotRendered = PreviousSectionWriters.Keys.Except(
                    _renderedSections,
                    StringComparer.OrdinalIgnoreCase);

                string[] sectionsNotIgnored;
                if (_ignoredSections != null)
                {
                    sectionsNotIgnored = sectionsNotRendered.Except(_ignoredSections, StringComparer.OrdinalIgnoreCase).ToArray();
                }
                else
                {
                    sectionsNotIgnored = sectionsNotRendered.ToArray();
                }

                if (sectionsNotIgnored.Length > 0)
                {
                    var sectionNames = string.Join(", ", sectionsNotIgnored);
                    throw new InvalidOperationException(Resources.FormatSectionsNotRendered(Path, sectionNames, nameof(IgnoreSection)));
                }
            }
            else if (BodyContent != null && !_renderedBody && !_ignoreBody)
            {
                // There are no sections defined, but RenderBody was NOT called.
                // If a body was defined and the body not ignored, then RenderBody should have been called.
                var message = Resources.FormatRenderBodyNotCalled(nameof(RenderBody), Path, nameof(IgnoreBody));
                throw new InvalidOperationException(message);
            }
        }

        public override void BeginContext(int position, int length, bool isLiteral)
        {
            // noop
        }

        public override void EndContext()
        {
            // noop
        }

        private void EnsureMethodCanBeInvoked(string methodName)
        {
            if (PreviousSectionWriters == null)
            {
                throw new InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName, Path));
            }
        }
    }
}

VB:

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On
' Copyright (c) .NET Foundation. All rights reserved.
' Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Html
Imports Microsoft.AspNetCore.Http

Namespace Microsoft.AspNetCore.Mvc.Razor
    ''' <summary>
    ''' Represents properties and methods that are needed in order to render a view that uses Razor syntax.
    ''' </summary>
    Public MustInherit Class RazorPage
        Inherits RazorPageBase
        Private ReadOnly _renderedSections As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
        Private _renderedBody As Boolean
        Private _ignoreBody As Boolean
        Private _ignoredSections As HashSet(Of String)

        ''' <summary>
        ''' An <see cref= "HttpContext"/> representing the current request execution.
        ''' </summary>
        Public ReadOnly Property Context As HttpContext
            Get
                Return ViewContext?.HttpContext
            End Get
        End Property

        ''' <summary>
        ''' In a Razor layout page, renders the portion of a content page that is not within a named section.
        ''' </summary>
        ''' <returns>The HTML content to render.</returns>
        Protected Overridable Function RenderBody() As IHtmlContent
            If BodyContent Is Nothing Then
                Dim message = Resources.FormatRazorPage_MethodCannotBeCalled(NameOf(RenderBody), Path)
                Throw New InvalidOperationException(message)
            End If

            _renderedBody = True
            Return BodyContent
        End Function

        ''' <summary>
        ''' In a Razor layout page, ignores rendering the portion of a content page that is not within a named section.
        ''' </summary>
        Public Sub IgnoreBody()
            _ignoreBody = True
        End Sub

        ''' <summary>
        ''' Creates a named content section in the page that can be invoked in a Layout page using
        ''' <see cref= "RenderSection(String)"/> or <see cref= "RenderSectionAsync(String,Boolean)"/>.
        ''' </summary>
        ''' <param name="name">The name of the section to create.</param>
        ''' <param name="section">The <see cref= "RenderAsyncDelegate"/> to execute when rendering the section.</param>
        Public Overrides Sub DefineSection(name As String, section As RenderAsyncDelegate)
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            If section Is Nothing Then
                Throw New ArgumentNullException(NameOf(section))
            End If

            If SectionWriters.ContainsKey(name) Then
                Throw New InvalidOperationException(Resources.FormatSectionAlreadyDefined(name))
            End If
            SectionWriters(name) = section
        End Sub

        ''' <summary>
        ''' Returns a value that indicates whether the specified section is defined in the content page.
        ''' </summary>
        ''' <param name="name">The section name to search for.</param>
        ''' <returns><c>true</c> if the specified section is defined in the content page; otherwise, <c>false</c>.</returns>
        Public Function IsSectionDefined(name As String) As Boolean
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            EnsureMethodCanBeInvoked(NameOf(IsSectionDefined))
            Return PreviousSectionWriters.ContainsKey(name)
        End Function

        ''' <summary>
        ''' In layout pages, renders the content of the section named <paramref name="name"/>.
        ''' </summary>
        ''' <param name="name">The name of the section to render.</param>
        ''' <returns>An empty <see cref= "IHtmlContent"/>.</returns>
        ''' <remarks>The method writes to the <see cref= "RazorPageBase.Output"/> and the value returned is a token
        ''' value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        ''' value does not represent the rendered content.</remarks>
        Public Function RenderSection(name As String) As HtmlString
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            Return RenderSection(name, required:=True)
        End Function

        ''' <summary>
        ''' In layout pages, renders the content of the section named <paramref name="name"/>.
        ''' </summary>
        ''' <param name="name">The section to render.</param>
        ''' <param name="required">Indicates if this section must be rendered.</param>
        ''' <returns>An empty <see cref= "IHtmlContent"/>.</returns>
        ''' <remarks>The method writes to the <see cref= "RazorPageBase.Output"/> and the value returned is a token
        ''' value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        ''' value does not represent the rendered content.</remarks>
        Public Function RenderSection(name As String, required As Boolean) As HtmlString
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            EnsureMethodCanBeInvoked(NameOf(RenderSection))

            Dim task As System.Threading.Tasks.Task(Of HtmlString) = RenderSectionAsyncCore(name, required)
            Return task.GetAwaiter().GetResult()
        End Function

        ''' <summary>
        ''' In layout pages, asynchronously renders the content of the section named <paramref name="name"/>.
        ''' </summary>
        ''' <param name="name">The section to render.</param>
        ''' <returns>
        ''' A <see cref= "Task(OfHtmlString)"/> that on completion returns an empty <see cref= "IHtmlContent"/>.
        ''' </returns>
        ''' <remarks>The method writes to the <see cref= "RazorPageBase.Output"/> and the value returned is a token
        ''' value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        ''' value does not represent the rendered content.</remarks>
        Public Function RenderSectionAsync(name As String) As Task_Renamed(Of HtmlString)
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            Return RenderSectionAsync(name, required:=True)
        End Function

        ''' <summary>
        ''' In layout pages, asynchronously renders the content of the section named <paramref name="name"/>.
        ''' </summary>
        ''' <param name="name">The section to render.</param>
        ''' <param name="required">Indicates the <paramref name="name"/> section must be registered
        ''' (using <c>@section</c>) in the page.</param>
        ''' <returns>
        ''' A <see cref= "Task(OfHtmlString)"/> that on completion returns an empty <see cref= "IHtmlContent"/>.
        ''' </returns>
        ''' <remarks>The method writes to the <see cref= "RazorPageBase.Output"/> and the value returned is a token
        ''' value that allows the Write (produced due to @RenderSection(..)) to succeed. However the
        ''' value does not represent the rendered content.</remarks>
        ''' <exception cref= "InvalidOperationException">if <paramref name="required"/> is <c>true</c> and the section
        ''' was not registered using the <c>@section</c> in the Razor page.</exception>
        Public Function RenderSectionAsync(name As String, required As Boolean) As Task_Renamed(Of HtmlString)
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            EnsureMethodCanBeInvoked(NameOf(RenderSectionAsync))
            Return RenderSectionAsyncCore(name, required)
        End Function

        Private Async Function RenderSectionAsyncCore(sectionName As String, required As Boolean) As Task_Renamed(Of HtmlString)
            If _renderedSections.Contains(sectionName) Then
                Dim message = Resources.FormatSectionAlreadyRendered(NameOf(RenderSectionAsync), Path, sectionName)
                Throw New InvalidOperationException(message)
            End If

            Dim renderDelegate As String = Nothing

            If PreviousSectionWriters.TryGetValue(sectionName, renderDelegate) Then
                _renderedSections.Add(sectionName)

                Await renderDelegate()

                ' Return a token value that allows the Write call that wraps the RenderSection \ RenderSectionAsync
                ' to succeed.
                Return HtmlString.Empty
            ElseIf required Then
                ' If the section is not found, and it is not optional, throw an error.
                Dim _viewContext = ViewContext
                Throw New InvalidOperationException( _
                    Resources.FormatSectionNotDefined( _
                        _viewContext.ExecutingFilePath,
                        sectionName,
                        _viewContext.View.Path))

            Else
                ' If the section is optional and not found, then don't do anything.
                Return Nothing
            End If
        End Function

        ''' <summary>
        ''' In layout pages, ignores rendering the content of the section named <paramref name="sectionName"/>.
        ''' </summary>
        ''' <param name="sectionName">The section to ignore.</param>
        Public Sub IgnoreSection(sectionName As String)
            If sectionName Is Nothing Then
                Throw New ArgumentNullException(NameOf(sectionName))
            End If

            If Not PreviousSectionWriters.ContainsKey(sectionName) Then
                ' If the section is not defined, throw an error.
                Throw New InvalidOperationException(Resources.FormatSectionNotDefined( _
                    ViewContext.ExecutingFilePath,
                    sectionName,
                    ViewContext.View.Path))
            End If

            If _ignoredSections Is Nothing Then
                _ignoredSections = New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
            End If

            _ignoredSections.Add(sectionName)
        End Sub

        ''' <inheritdoc/>
        Public Overrides Sub EnsureRenderedBodyOrSections()
            ' a) all sections defined for this page are rendered.
            ' b) if no sections are defined, then the body is rendered if it's available.
            If PreviousSectionWriters IsNot Nothing AndAlso PreviousSectionWriters.Count > 0 Then
                Dim sectionsNotRendered = PreviousSectionWriters.Keys.Except( _
        _renderedSections,
        StringComparer.OrdinalIgnoreCase)

                Dim sectionsNotIgnored As String()
                If _ignoredSections IsNot Nothing Then
                    sectionsNotIgnored = sectionsNotRendered.Except(_ignoredSections, StringComparer.OrdinalIgnoreCase).ToArray()

                Else
                    sectionsNotIgnored = sectionsNotRendered.ToArray()
                End If

                If sectionsNotIgnored.Length > 0 Then
                    Dim sectionNames As String = String.Join(", ", sectionsNotIgnored)
                    Throw New InvalidOperationException(Resources.FormatSectionsNotRendered(Path, sectionNames, NameOf(IgnoreSection)))
                End If
            ElseIf BodyContent IsNot Nothing AndAlso Not _renderedBody AndAlso Not _ignoreBody Then
                ' There are no sections defined, but RenderBody was NOT called.
                ' If a body was defined and the body not ignored, then RenderBody should have been called.
                Dim message = Resources.FormatRenderBodyNotCalled(NameOf(RenderBody), Path, NameOf(IgnoreBody))
                Throw New InvalidOperationException(message)
            End If
        End Sub

        Public Overrides Sub BeginContext(position As Integer, _length As Integer, isLiteral As Boolean)
            ' noop
        End Sub

        Public Overrides Sub EndContext()
            ' noop
        End Sub

        Private Sub EnsureMethodCanBeInvoked(methodName As String)
            If PreviousSectionWriters Is Nothing Then
                Throw New InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName, Path))
            End If
        End Sub
    End Class
End Namespace

Task_renamed Appeared 3 times, such as:
Public Function RenderSectionAsync(name As String) As Task_Renamed(Of HtmlString)

Optimize property intialization

You convert this C#:

public List<int> Foo {get; set} = new List<int>();

To:

Public Property Foo As List(Of Integer) = new List(Of Integer) ( )

It can be optimized to:

Public Property Foo As new List(Of Integer)( )

Missing ()

When C# calls a property and adds () after it:
viewStarts[i] = viewStartItem.PageFactory();

Check that PageFactory is a property
and It returns a delegate.
If so, add extra () in VB. C# doesn't allow params for properties, but VB does:
viewStarts(i) = viewStartItem.PageFactory()()

It is an SDK Project but seems not

This is the csprog file that is considered non-sdk in #26:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RootNamespace>Microsoft.eShopWeb.Web</RootNamespace>
    <UserSecretsId>aspnet-Web2-1FA3F72E-E7E3-4360-9E49-1CCCD7FE85F7</UserSecretsId>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <Content Remove="compilerconfig.json" />
  </ItemGroup>


  <ItemGroup>
    <PackageReference Include="Ardalis.ListStartupServices" Version="1.1.3" />

    <PackageReference Include="MediatR" Version="7.0.0" />
    <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="7.0.0" />
    <PackageReference Include="BuildBundlerMinifier" Version="2.9.406" Condition="'$(Configuration)'=='Release'" PrivateAssets="All" />
    <PackageReference Include="Microsoft.CodeAnalysis" Version="3.4.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.0" />
    <PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.0.96" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" />
    <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.0.0-rc4" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Folder Include="wwwroot\fonts\" />
    <Folder Include="wwwroot\lib\" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\ApplicationCore\ApplicationCore.csproj" />
    <ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
  </ItemGroup>
  <ItemGroup>
    <None Include="compilerconfig.json" />
    <None Include="wwwroot\images\products\1.png" />
    <None Include="wwwroot\images\products\10.png" />
    <None Include="wwwroot\images\products\11.png" />
    <None Include="wwwroot\images\products\12.png" />
    <None Include="wwwroot\images\products\2.png" />
    <None Include="wwwroot\images\products\3.png" />
    <None Include="wwwroot\images\products\4.png" />
    <None Include="wwwroot\images\products\5.png" />
    <None Include="wwwroot\images\products\6.png" />
    <None Include="wwwroot\images\products\7.png" />
    <None Include="wwwroot\images\products\8.png" />
    <None Include="wwwroot\images\products\9.png" />
  </ItemGroup>
  <ItemGroup>
    <Content Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Content Update="Views\Shared\Error.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Update="Views\Shared\_Layout.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Update="Views\Shared\_LoginPartial.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Update="Views\Shared\_ValidationScriptsPartial.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Update="Views\_ViewImports.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Update="Views\_ViewStart.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>
</Project>

It is an SDK, isn't it?
May be the problem comes from line termination. Some files use Lf termination, while others use CrLf. Try converting both and see if this is the problem.

Create a discard function when a C# discard assign (_) is converted to __ in VB

I note that the discard assignement in C# _ (underscore) is converted to __ (double underscore)
But there is no double underscore function or property defined in the VB code so... an Error is thrown.

If it's possible the converter shoul add a property like this:

' Shared is not optional only if is using a Class instead of a Module
Private [Shared] Property __ As Object

I don't know how to add this functionality in your code... but hope it's help, and it's easy for you to do ;-)

Thanks!
Guillermo

Wrong type for out param

C#

        protected static PropertyHelper[] GetVisibleProperties(
            Type type,
            Func<PropertyInfo, PropertyHelper> createPropertyHelper,
            ConcurrentDictionary<Type, PropertyHelper[]> allPropertiesCache,
            ConcurrentDictionary<Type, PropertyHelper[]> visiblePropertiesCache)
        {
            if (visiblePropertiesCache.TryGetValue(type, out var result))
            {
                return result;
            }
        }

VB:

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On
Protected Shared Function GetVisibleProperties( _
_type As Type,
createPropertyHelper As Func(Of PropertyInfo, PropertyHelper),
allPropertiesCache As ConcurrentDictionary(Of Type, PropertyHelper()),
visiblePropertiesCache As ConcurrentDictionary(Of Type, PropertyHelper())) As PropertyHelper()
    Dim result As Type = Nothing

    If visiblePropertiesCache.TryGetValue(_type, result) Then
        Return result
    End If
End Function

This declaration:
'Dim result As Type = Nothing'
is wrong, since Type is the first param type, and you need the second param type.
Try it with know methods to reproduce it.

And by the way, I hope you format the separated lines as in the function param list , by adding some taps to start of each line.

Explicit Interface Implementation

Check this out. Has many issues:
C#:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections;
using System.Collections.Generic;

namespace Microsoft.AspNetCore.Mvc.Diagnostics
{
    public abstract class EventData : IReadOnlyList<KeyValuePair<string, object>>
    {
        protected const string EventNamespace = "Microsoft.AspNetCore.Mvc.";

        protected abstract int Count { get; }
        protected abstract KeyValuePair<string, object> this[int index] { get; }

        int IReadOnlyCollection<KeyValuePair<string, object>>.Count => Count;
        KeyValuePair<string, object> IReadOnlyList<KeyValuePair<string, object>>.this[int index] => this[index];

        Enumerator GetEnumerator() => new Enumerator(this);

        IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
            => GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator()
            => GetEnumerator();

        public struct Enumerator : IEnumerator<KeyValuePair<string, object>>
        {
            private readonly EventData _eventData;
            private readonly int _count;

            private int _index;

            public KeyValuePair<string, object> Current { get; private set; }

            internal Enumerator(EventData eventData)
            {
                _eventData = eventData;
                _count = eventData.Count;
                _index = -1;
                Current = default;
            }

            public bool MoveNext()
            {
                var index = _index + 1;
                if (index >= _count)
                {
                    return false;
                }

                _index = index;

                Current = _eventData[index];
                return true;
            }

            public void Dispose() { }
            object IEnumerator.Current => Current;
            void IEnumerator.Reset() => throw new NotSupportedException();
        }
    }
}

CI build to validate PRs

Would you be interested in adding a GitHub Actions CI build that simply builds the solution and runs all tests? That way the build errors I missed in #2 would have prevented the PR from being merged without overriding.

A missing comment

This Code:

    public class Address // ValueObject
    {
    }

loses the comment:

Public Class Address

End Class

Error in LineNumbersForRichTextBox

When checking

If String.IsNullOrWhiteSpace(Me.ZParent.Text) Then

A null error is thrown because Me.ZParent is Nothing.

I check if it's nothing then return.

' Da error en la siguiente comprobación de que esto es nulo (It gives error in the following check that this is null)
If Me.ZParent Is Nothing Then
    Exit Sub
End If

If String.IsNullOrWhiteSpace(Me.ZParent.Text) Then
    Exit Sub
End If

Guillermo

dynamic

C#
public dynamic ViewBag => ViewContext?.ViewBag;

VB:

Public ReadOnly Property ViewBag As dynamic
    Get
        Return ViewContext?.ViewBag
    End Get
End Property

Change dynamic to Object in VB.

Missing ReadOnly and Get body code

C#

    public sealed class BeforeViewPageEventData : EventData
    {
        protected override KeyValuePair<string, object> this[int index] => index switch
        {
            0 => new KeyValuePair<string, object>(nameof(Page), Page),
            1 => new KeyValuePair<string, object>(nameof(ViewContext), ViewContext),
            2 => new KeyValuePair<string, object>(nameof(ActionDescriptor), ActionDescriptor),
            3 => new KeyValuePair<string, object>(nameof(HttpContext), HttpContext),
            _ => throw new IndexOutOfRangeException(nameof(index))
        };
    }

VB:

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On

Public NotInheritable Class BeforeViewPageEventData
    Inherits EventData
    Default Protected Overrides Property Item(index As Integer) As KeyValuePair(Of String, Object)
        Get
            Return tempVar
        End Get
    End Property
End Class

You missed the ReadOnly and the Select Case in the Get body.

        Default Protected Overrides ReadOnly Property Item(index As Integer) As KeyValuePair(Of String, Object)
            Get
                Select Case index
                    Case 0
                        Return New KeyValuePair(Of String, Object)(NameOf(Page), Page)
                    Case 1
                        Return New KeyValuePair(Of String, Object)(NameOf(ViewContext), ViewContext)
                    Case 2
                        Return New KeyValuePair(Of String, Object)(NameOf(ActionDescriptor), ActionDescriptor)
                    Case 3
                        Return New KeyValuePair(Of String, Object)(NameOf(HttpContext), HttpContext)
                    Case Else
                        Throw New IndexOutOfRangeException(NameOf(index))
                End Select
            End Get
        End Property

Evaluate type param

C#:

var activateInfo = propertiesToActivate[i];

VB:

Dim activateInfo As PropertyActivator(Of TContext) = propertiesToActivate(i)

No need to explicit declaration here. This is OK:
Dim activateInfo = propertiesToActivate(i)

But if you have to mention the type, you should evaluate the type param, instead using TContext which is the raw generic declaration not a real type. In this context, TContext is evaluated to be ViewContext(). You need to use a valid sample to reproduce this case.

Property errors

C#:

public virtual string Name { get; protected set; }

VB:

 Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On
Private _name As String
Public Overridable Property Name As String
    Private Get
        Return _name
    End Get
    Protected Set(Value As String)
        Name = _name
    End Set
End Property

Why adding Private to the set?.. It causes errors.

also 'Name = _nameMust be:_name = Value`

"Convert a project" inhancements

I tested the convert a project:
1- It hanged for a long time, then showed a massage that sdk like projects can only converted. Then a message that 48 files are converted. When I tried with class libraries, worked fine.
2- open the output folder after finishing.
3- clear text boxes after finishing, because they show contents of last file.
4- The bottom textboxs that show file names, can be 2 list boxes, so we can double click on any item to view its content in both languages. and keep the two list sync: always select the same index in both.
5- any non cs files, copy them to the output. I tried a project with cshtml files, but they are missing from the converted project.
6- the project file is missing too. Just copy the project file and change its extension from .csprog to ,vbprog. In the file content, Replace any ".cs" in the end of any word (to ignore .cshtml files) to ".vb".
7- I can select the text while it is converted. For safety, make textbox readonly while converting.
show percentage and elapsed time somewhere (at the window title bar for example).
8- While converting, I opened the file menu and clicked the convert project. The file dialog appeared. This can make a mess. Disable un wanted menus while converting, and add a cancel command ot a cancel button with keyboard shortcut (like escape) with a confirm msg box.
9- I also suggest to add a Convert a solution command. If the UI is interactive and the user can cancel, so no fear of large solutions.

Set Option Infer to ON and on Sub Main remove Private access modifier

In a small file for console application I found this:
Set Option Infer to On because in for loops the variable isn't assigned a type
For i = 1 To args.Length -1
And in C# the "infer" is default when using var.

I know you can set in the CSharpToVB application, but... it should be as default ON (like Option Strict is).

The Sub Main method was set as Private Sub Main and as a console application (even on WinForms) should be the entry point.

On the Editor will be a good idea to use another font type for view the code (Cosnsolas, etc.) or at least an option to set the font.

These are my 2 cents :-)
Thanks!

Guillermo
(#evolveVB #evolucionarVB)

Parameters and property names conflictions

C#:

        public override void Write(char[] buffer, int index, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (index < 0 || index >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            if (count < 0 || (buffer.Length - index < count))
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            Buffer.AppendHtml(new string(buffer, index, count));
        }

VB.NET:

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On
Public Overrides Sub Write(buffer As Char(), index As Integer, count As Integer)
    If buffer Is Nothing Then
        Throw New ArgumentNullException(NameOf(buffer))
    End If

    If index < 0 OrElse index >= buffer.Length Then
        Throw New ArgumentOutOfRangeException(NameOf(index))
    End If

    If count < 0 OrElse (buffer.Length - index < count) Then
        Throw New ArgumentOutOfRangeException(NameOf(count))
    End If

    Buffer_Renamed.AppendHtml(New String(buffer, index, count))
End Sub

the Buffer_Renamed.AppendHtml(New String(buffer, index, count)) is wrong. Buffer is not buffer in C#. As I mentioned b4, changing param name leads to errors in EF and other tech. so the only solution is to add Me. b4 any variable has the same name as a param but starting with Uppercase letter.
Me.Buffer_Renamed.AppendHtml(New String(buffer, index, count))
is the equivalent VB for:
Buffer.AppendHtml(new string(buffer, index, count));

And by the way, turn Option Infer On, as it is the default for C#, and turning it of causes errors in VB.

Options must be ON

You add these statements at top of each converted file:

Option Explicit Off
Option Infer On
Option Strict Off

In fact this will hide many conversion errors. C# is a strict language, so the code converted from it must work will VB option Explicit and Strict are On:

Option Explicit On
Option Infer On
Option Strict On

For example, tour decision hides this problem:
C#

if (quantities.TryGetValue(item.Id.ToString(), out var quantity))

VB:

    Dim quantity As Object= Nothing
    If quantities.TryGetValue(item.Id.ToString(), quantity) Then

Which will be obvious when truning options off. The correct code is:

   Dim quantity As Integer = 0
   If quantities.TryGetValue(item.Id.ToString(), quantity) Then

private_set propertes is converted to public properties

This C# code

public string BuyerId { get; private set; }

is converted to:

Public Property BuyerId As String

but it should be:

Dim _buyerId As String
Public Property BuyerId As String
   Get
       Return _buyerId
   End Get

   Private Set(value As String)
       _buyerId = value
   End Set
End Property

New Dictionary_Renamed

C#

        public static IDictionary<string, object> ObjectToDictionary(object value)
        {
            var dictionary = value as IDictionary<string, object>;
            if (dictionary != null)
            {
                return new Dictionary<string, object>(dictionary, StringComparer.OrdinalIgnoreCase);
            }

            dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

            if (value != null)
            {
                foreach (var helper in GetProperties(value.GetType()))
                {
                    dictionary[helper.Name] = helper.GetValue(value);
                }
            }

            return dictionary;
        }

VB:

Option Compare Text
Option Explicit On
Option Infer Off
Option Strict On
Public Shared Function ObjectToDictionary(value As Object) As IDictionary(Of String, Object)
    Dim dictionary = TryCast(value, IDictionary(Of String, Object))
    If dictionary IsNot Nothing Then
        Return New Dictionary_Renamed(Of String, Object)(dictionary, StringComparer.OrdinalIgnoreCase)
    End If

    dictionary = New Dictionary_Renamed(Of String, Object)(StringComparer.OrdinalIgnoreCase)

    If value IsNot Nothing Then
        For Each helper In GetProperties(value.GetType())
            dictionary(helper.Name) = helper.GetValue(value)
        Next
    End If

    Return dictionary
End Function

Dictionary is a type. You cant rename types. If it's necessary to rename something, it should be a local var. Any other types with New keyword or followed by . can't be renamed unless you find their local declaration in the scope.

Open Project fails

Error
Msbuild failed when processing the file '...roslyn\src\Compilers\CSharp\Test\Syntax\Microsoft.CodeAnalysis.CSharp.Syntax.UnitTests.csproj' with message: The SDK 'Microsoft.DotNet.Arcade.Sdk'

Ordinal comparisons should be used rather than culture comparisons

Things like syntax and keywords shouldn't be processed through .NET culture transforms, invariant or not. The characters should be treated symbolically instead of linguistically. InvariantCulture considers ss to equal ß, for example. This doesn't apply to keywords and syntax.

Ordinal and OrdinalIgnoreCase are slightly faster than InvariantCulture and InvariantCultureIgnoreCase too because of the lack of culture processing.

Friend Shared Function ConvertNamedTypeToTypeString(TypeString As String) As String
Dim SplitTypeString() As String = TypeString.Trim.Split(" "c, StringComparison.InvariantCulture)
If SplitTypeString.Length > 2 Then
Stop
End If
Dim IndexOfLessThan As Integer = TypeString.IndexOf("<", StringComparison.InvariantCulture)
Dim TypeName As String = SplitTypeString(0)
Dim Name As String = If(SplitTypeString.Length = 1, "", MakeVBSafeName(SplitTypeString(1)) & " As ")
If IndexOfLessThan > 0 Then
Return $"{Name}{TypeName.Left(IndexOfLessThan)}{TypeName.Substring(IndexOfLessThan).
Replace("<", "(Of ", StringComparison.InvariantCulture).
Replace(">", ")", StringComparison.InvariantCulture)}"
End If
Return Name & ConvertToType(TypeName).ToString
End Function

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.