Skip to content

Commit

Permalink
Merge pull request #1094 from icsharpcode/issue/1084
Browse files Browse the repository at this point in the history
Issue/1084
  • Loading branch information
GrahamTheCoder committed Apr 21, 2024
2 parents 5143c08 + 3ff9806 commit 6aea19a
Show file tree
Hide file tree
Showing 22 changed files with 82 additions and 66 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

### Vsix

* Compatible with Visual Studio 2022 17.1 onwards

### VB -> C#


### C# -> VB

* Converts file scoped namespaces

## [9.2.5] - 2024-01-31

Expand Down
6 changes: 3 additions & 3 deletions CodeConverter/CSharp/ClashingMemberRenamer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ internal static class ClashingMemberRenamer
/// Renames symbols in a VB project so that they don't clash with rules for C# member names, attempting to rename the least public ones first.
/// See https://github.com/icsharpcode/CodeConverter/issues/420
/// </summary>
public static async Task<Project> RenameClashingSymbolsAsync(Project project)
public static async Task<Project> RenameClashingSymbolsAsync(Project project, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync();
var compilation = await project.GetCompilationAsync(cancellationToken);
var memberRenames = SymbolRenamer.GetNamespacesAndTypesInAssembly(project, compilation)
.SelectMany(x => GetSymbolsWithNewNames(x, compilation));
return await SymbolRenamer.PerformRenamesAsync(project, memberRenames.ToList());
return await SymbolRenamer.PerformRenamesAsync(project, memberRenames.ToList(), cancellationToken);
}

private static IEnumerable<(ISymbol Original, string NewName)> GetSymbolsWithNewNames(INamespaceOrTypeSymbol containerSymbol, Compilation compilation)
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/HandledEventsAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private PropertyDeclarationSyntax GetDeclarationsForHandlingBaseMembers((EventCo
var prop = (PropertyDeclarationSyntax) _commonConversions.CsSyntaxGenerator.Declaration(basePropertyEventSubscription.PropertyDetails.Property);
var modifiers = prop.Modifiers.RemoveWhere(m => m.IsKind(SyntaxKind.VirtualKeyword)).Add(SyntaxFactory.Token(SyntaxKind.OverrideKeyword));
//TODO Stash away methodwithandles in constructor that don't match any symbol from that type, to match here against base symbols
return GetDeclarationsForFieldBackedProperty(basePropertyEventSubscription.HandledMethods, SyntaxFactory.List<SyntaxNode>(), modifiers,
return GetDeclarationsForFieldBackedProperty(basePropertyEventSubscription.HandledMethods, SyntaxFactory.List<AttributeListSyntax>(), modifiers,
prop.Type, prop.Identifier, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.BaseExpression(), ValidSyntaxFactory.IdentifierName(prop.Identifier)));
}

Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/LambdaConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public LambdaConverter(CommonConversions commonConversions, SemanticModel semant
// Could do: See if we can improve upon returning "object" for pretty much everything (which is what the symbols say)
// I believe that in general, special VB functions such as MultiplyObject are designed to work the same as integer when given two integers for example.
// If all callers currently pass an integer, perhaps it'd be more idiomatic in C# to specify "int", than to have Operators
var paramsWithTypes = anonFuncOp.Symbol.Parameters.Select(p => CommonConversions.CsSyntaxGenerator.ParameterDeclaration(p));
var paramsWithTypes = anonFuncOp.Symbol.Parameters.Select(p => (ParameterSyntax) CommonConversions.CsSyntaxGenerator.ParameterDeclaration(p));

var paramListWithTypes = param.WithParameters(SyntaxFactory.SeparatedList(paramsWithTypes));
if (potentialAncestorDeclarationOperation is IFieldInitializerOperation fieldInit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ public override async Task<SyntaxList<StatementSyntax>> VisitForBlock(VBSyntax.F
}


var preLoopStatements = new List<SyntaxNode>();
var preLoopStatements = new List<StatementSyntax>();
var csToValue = await stmt.ToValue.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
csToValue = CommonConversions.TypeConversionAnalyzer.AddExplicitConversion(stmt.ToValue, csToValue?.SkipIntoParens(), forceTargetType: controlVarType);

Expand Down
6 changes: 3 additions & 3 deletions CodeConverter/CSharp/TypeConversionAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,17 @@ private CSSyntax.NameSyntax GetCommonDelegateTypeOrNull(VBSyntax.ExpressionSynta
private CSSyntax.NameSyntax CreateCommonDelegateTypeSyntax(IMethodSymbol vbLambda)
{
var parameters = vbLambda.Parameters
.Select(p => _csSyntaxGenerator.TypeExpression(p.Type));
.Select(p => (TypeSyntax) _csSyntaxGenerator.TypeExpression(p.Type));

if (vbLambda.ReturnType.IsSystemVoid()) {
return CreateType("Action", parameters);
}

var typeExpression = _csSyntaxGenerator.TypeExpression(vbLambda.ReturnType);
var typeExpression = (TypeSyntax) _csSyntaxGenerator.TypeExpression(vbLambda.ReturnType);
return CreateType("Func", parameters.Concat(typeExpression));
}

private static CSSyntax.NameSyntax CreateType(string baseTypeName, IEnumerable<SyntaxNode> parameters)
private static CSSyntax.NameSyntax CreateType(string baseTypeName, IEnumerable<TypeSyntax> parameters)
{
var parameterList = SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(parameters));
if (!parameterList.Arguments.Any()) return ValidSyntaxFactory.IdentifierName(baseTypeName);
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal class VBToCSProjectContentsConverter : IProjectContentsConverter

public async Task InitializeSourceAsync(Project project)
{
project = await ClashingMemberRenamer.RenameClashingSymbolsAsync(project);
project = await ClashingMemberRenamer.RenameClashingSymbolsAsync(project, _cancellationToken);
var cSharpCompilationOptions = CSharpCompiler.CreateCompilationOptions();
_convertedCsProject = project.ToProjectFromAnyOptions(cSharpCompilationOptions, CSharpCompiler.ParseOptions);
_csharpReferenceProject = project.CreateReferenceOnlyProjectFromAnyOptions(cSharpCompilationOptions, CSharpCompiler.ParseOptions);
Expand Down
5 changes: 3 additions & 2 deletions CodeConverter/CodeConverter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/Common/SymbolRenamer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal static class SymbolRenamer
return m.Name;
}

public static async Task<Project> PerformRenamesAsync(Project project, IEnumerable<(ISymbol Original, string NewName)> symbolsWithNewNames)
public static async Task<Project> PerformRenamesAsync(Project project, IEnumerable<(ISymbol Original, string NewName)> symbolsWithNewNames, CancellationToken cancellationToken)
{
var solution = project.Solution;
foreach (var (originalSymbol, newName) in symbolsWithNewNames.OrderByDescending(s => s.Original.DeclaringSyntaxReferences.Select(x => x.Span.End).Max())) {
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/VB/CSToVBProjectContentsConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public CSToVBProjectContentsConverter(ConversionOptions conversionOptions, IProg
public async Task InitializeSourceAsync(Project project)
{
// TODO: Don't throw away solution-wide effects - write them to referencing files, and use in conversion of any other projects being converted at the same time.
project = await ClashingMemberRenamer.RenameClashingSymbolsAsync(project);
project = await ClashingMemberRenamer.RenameClashingSymbolsAsync(project, _cancellationToken);
_convertedVbProject = project.ToProjectFromAnyOptions(_vbCompilationOptions, _vbParseOptions);
_vbReferenceProject = project.CreateReferenceOnlyProjectFromAnyOptions(_vbCompilationOptions, _vbParseOptions);
_vbViewOfCsSymbols = (VisualBasicCompilation)await _vbReferenceProject.GetCompilationAsync(_cancellationToken);
Expand Down
6 changes: 3 additions & 3 deletions CodeConverter/VB/ClashingMemberRenamer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ internal static class ClashingMemberRenamer
/// Cases in different named scopes should be dealt with by <seealso cref="DocumentExtensions.ExpandAsync"/>.
/// For names scoped within a type member, see <seealso cref="SemanticModelSymbolSetExtensions.GetCsLocalSymbolsPerScope"/>.
/// </remarks>
public static async Task<Project> RenameClashingSymbolsAsync(Project project)
public static async Task<Project> RenameClashingSymbolsAsync(Project project, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync();
var compilation = await project.GetCompilationAsync(cancellationToken);
var memberRenames = SymbolRenamer.GetNamespacesAndTypesInAssembly(project, compilation)
.SelectMany(x => GetSymbolsWithNewNames(x, compilation));
return await SymbolRenamer.PerformRenamesAsync(project, memberRenames.ToList());
return await SymbolRenamer.PerformRenamesAsync(project, memberRenames.ToList(), cancellationToken);
}

private static IEnumerable<(ISymbol Original, string NewName)> GetSymbolsWithNewNames(INamespaceOrTypeSymbol containerSymbol, Compilation compilation)
Expand Down
8 changes: 6 additions & 2 deletions CodeConverter/VB/NodesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ public override VisualBasicSyntaxNode VisitAttributeArgument(CSSyntax.AttributeA
}
#endregion

public override VisualBasicSyntaxNode VisitNamespaceDeclaration(CSSyntax.NamespaceDeclarationSyntax node)
public override VisualBasicSyntaxNode VisitFileScopedNamespaceDeclaration(FileScopedNamespaceDeclarationSyntax node) => ConvertNamespaceDeclaration(node);

public override VisualBasicSyntaxNode VisitNamespaceDeclaration(CSSyntax.NamespaceDeclarationSyntax node) => ConvertNamespaceDeclaration(node);

private VisualBasicSyntaxNode ConvertNamespaceDeclaration(BaseNamespaceDeclarationSyntax node)
{
foreach (var @using in node.Usings)
_importsToConvert.AddRange(node.Usings);
Expand Down Expand Up @@ -653,7 +657,7 @@ public override VisualBasicSyntaxNode VisitEventDeclaration(CSSyntax.EventDeclar
);
} else {
if ((int)LanguageVersion < 14) {
var conditionalStatement = _vbSyntaxGenerator.IfStatement(
var conditionalStatement = (StatementSyntax) _vbSyntaxGenerator.IfStatement(
_vbSyntaxGenerator.ReferenceNotEqualsExpression(eventFieldIdentifier,
_vbSyntaxGenerator.NullLiteralExpression()),
SyntaxFactory.InvocationExpression(
Expand Down
10 changes: 5 additions & 5 deletions CommandLine/CodeConv.NetFramework/CodeConv.NetFramework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="16.10.56" />
<PackageReference Include="NuGet.Build.Tasks" Version="5.4.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
Expand Down
2 changes: 1 addition & 1 deletion CommandLine/CodeConv/CodeConv.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.4.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.1.0" />
Expand Down
12 changes: 6 additions & 6 deletions Func/Func.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Convert code from VB.NET to C# (and vice versa) using Roslyn - all free and open
* [Visual Studio extension](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter)
* To install close VS and double-click the downloadeded .vsix file
* [Online snippet converter](https://icsharpcode.github.io/CodeConverter/)
* Command line `dotnet tool install ICSharpCode.CodeConverter.codeconv --global` (still requires VS2019+ installed)
* Command line `dotnet tool install ICSharpCode.CodeConverter.codeconv --global` (still requires VS2022 17.1+ installed)
* [Nuget library](https://www.nuget.org/packages/ICSharpCode.CodeConverter/) (this underpins all other free converters you'll find online)

See [wiki](https://github.com/icsharpcode/CodeConverter/wiki) for advice on getting the best results, or the [changelog](https://github.com/icsharpcode/CodeConverter/blob/master/CHANGELOG.md) for recent improvements.
Expand All @@ -15,7 +15,7 @@ See [wiki](https://github.com/icsharpcode/CodeConverter/wiki) for advice on gett

Adds context menu items to convert projects/files between VB.NET and C#. See the [wiki documentation](https://github.com/icsharpcode/CodeConverter/wiki) for advice / help using it.

Download from [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter) (Use VS 2019+)
Download from [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.CodeConverter) (Use VS 2022 17.1+)

* Flexible: Convert a small selection, or a whole solution in one go, in either direction.
* Accurate: Full project context (through Roslyn) is used to get the most accurate conversion.
Expand Down
38 changes: 20 additions & 18 deletions Tests/CSharp/ExpressionTests/XmlExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,22 @@ private void TestMethod()
{
var catalog = new XDocument(
new XElement(""Catalog"",
new XElement(""Book"", new XAttribute(""id"", ""bk101""),
new XElement(""Author"", ""Garghentini, Davide""),
new XElement(""Title"", ""XML Developer's Guide""),
new XElement(""Price"", ""44.95""),
new XElement(""Description"", @""
new XElement(""Book"", new XAttribute(""id"", ""bk101""),
new XElement(""Author"", ""Garghentini, Davide""),
new XElement(""Title"", ""XML Developer's Guide""),
new XElement(""Price"", ""44.95""),
new XElement(""Description"", @""
An in-depth look at creating applications
with "", new XElement(""technology"", ""XML""), @"". For
"", new XElement(""audience"", ""beginners""), @"" or
"", new XElement(""audience"", ""advanced""), @"" developers.
"")
),
new XElement(""Book"", new XAttribute(""id"", ""bk331""),
new XElement(""Author"", ""Spencer, Phil""),
new XElement(""Title"", ""Developing Applications with Visual Basic .NET""),
new XElement(""Price"", ""45.95""),
new XElement(""Description"", @""
),
new XElement(""Book"", new XAttribute(""id"", ""bk331""),
new XElement(""Author"", ""Spencer, Phil""),
new XElement(""Title"", ""Developing Applications with Visual Basic .NET""),
new XElement(""Price"", ""45.95""),
new XElement(""Description"", @""
Get the expert insights, practical code samples,
and best practices you need
to advance your expertise with "", new XElement(""technology"", @""Visual
Expand All @@ -140,21 +140,23 @@ private void TestMethod()
based on professional,
pragmatic guidance by today's top "", new XElement(""audience"", ""developers""), @"".
"")
)
)
)
);
var htmlOutput = new XElement(""html"",
new XElement(""body"", from book in catalog.Elements(""Catalog"").Elements(""Book"")
select new XElement(""div"",
new XElement(""h1"", book.Elements(""Title"").Value),
new XElement(""h3"", ""By "" + book.Elements(""Author"").Value),
new XElement(""h3"", ""Price = "" + book.Elements(""Price"").Value),
new XElement(""h1"", book.Elements(""Title"").Value),
new XElement(""h3"", ""By "" + book.Elements(""Author"").Value),
new XElement(""h3"", ""Price = "" + book.Elements(""Price"").Value),
new XElement(""h2"", ""Description""), TransformDescription((string)book.Elements(""Description"").ElementAtOrDefault(0)), new XElement(""hr"")
)
)
);
)
)
);
}
public string TransformDescription(string s)
Expand Down
8 changes: 4 additions & 4 deletions Tests/Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
<ProjectReference Include="..\CommandLine\CodeConv.NetFramework\CodeConv.NetFramework.csproj" />
</ItemGroup>
<ItemGroup Label="ReSharper test runner requirements - test against latest Visual Studio version">
<PackageReference Include="Microsoft.CodeAnalysis.Features" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Features" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.1.0" />
<PackageReference Include="Microsoft.Build" Version="17.4.0" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="17.4.0" />
</ItemGroup>
Expand Down
15 changes: 15 additions & 0 deletions Tests/VB/NamespaceLevelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ End Class
End Namespace");
}

[Fact]
public async Task TestClassWithNamespaceStatementAsync()
{
await TestConversionCSharpToVisualBasicAsync(@"namespace Test.@class;
class TestClass<T>
{
}
", @"Namespace Test.class
Friend Class TestClass(Of T)
End Class
End Namespace");
}

[Fact]
public async Task TestInternalStaticClassAsync()
{
Expand Down
Loading

0 comments on commit 6aea19a

Please sign in to comment.