diff --git a/.gitignore b/.gitignore
index 940794e60..e0978f64f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -286,3 +286,4 @@ __pycache__/
*.btm.cs
*.odx.cs
*.xsd.cs
+/.nuget
diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config
deleted file mode 100644
index 67f8ea046..000000000
--- a/.nuget/NuGet.Config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.nuget/NuGet.exe b/.nuget/NuGet.exe
deleted file mode 100644
index 6bb79fe53..000000000
Binary files a/.nuget/NuGet.exe and /dev/null differ
diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets
deleted file mode 100644
index 3f8c37b22..000000000
--- a/.nuget/NuGet.targets
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
- $(MSBuildProjectDirectory)\..\
-
-
- false
-
-
- false
-
-
- true
-
-
- false
-
-
-
-
-
-
-
-
-
-
- $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
-
-
-
-
- $(SolutionDir).nuget
-
-
-
- $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
- $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
-
-
-
- $(MSBuildProjectDirectory)\packages.config
- $(PackagesProjectConfig)
-
-
-
-
- $(NuGetToolsPath)\NuGet.exe
- @(PackageSource)
-
- "$(NuGetExePath)"
- mono --runtime=v4.0.30319 "$(NuGetExePath)"
-
- $(TargetDir.Trim('\\'))
-
- -RequireConsent
- -NonInteractive
-
- "$(SolutionDir) "
- "$(SolutionDir)"
-
-
- $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
- $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
-
-
-
- RestorePackages;
- $(BuildDependsOn);
-
-
-
-
- $(BuildDependsOn);
- BuildPackage;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.nuget/packages.config b/.nuget/packages.config
deleted file mode 100644
index 0fa4618df..000000000
--- a/.nuget/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2fcc6e92..97d666144 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [Unreleased]
+* Decrease horrendousness of performance for large projects containing large files
+
+### API
+
+* IEnumerable> becomes IAsyncEnumerable
+* Upgraded target framework from netstandard 1.3 to netstandard 2.0
+* Introduced cancellation token
### Vsix
@@ -21,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Exclude project file from conversion result if it hasn't changed
* Further efforts to stop the roslyn library crashing Visual Studio
+* Conversion tasks are now cancellable
### VB -> C#
@@ -30,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Avoid incorrectly renaming symbols
* Prevent "SyntaxTree is not part of the compilation" error [#527](https://github.com/icsharpcode/CodeConverter/issues/527)
+* Avoid incorrectly renaming symbols (#524)[https://github.com/icsharpcode/CodeConverter/issues/524]
## [7.8.0] - 2020-02-15
diff --git a/CodeConverter.Web/Pages/Index.cshtml.cs b/CodeConverter.Web/Pages/Index.cshtml.cs
deleted file mode 100644
index 8dd3ccdd6..000000000
--- a/CodeConverter.Web/Pages/Index.cshtml.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
-
-namespace CodeConverter.Web.Pages
-{
- public class IndexModel : PageModel
- {
- public void OnGet()
- {
-
- }
- }
-}
diff --git a/CodeConverter.Web/Pages/Privacy.cshtml.cs b/CodeConverter.Web/Pages/Privacy.cshtml.cs
deleted file mode 100644
index 22313d539..000000000
--- a/CodeConverter.Web/Pages/Privacy.cshtml.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
-
-namespace CodeConverter.Web.Pages
-{
- public class PrivacyModel : PageModel
- {
- public void OnGet()
- {
- }
- }
-}
diff --git a/CodeConverter.sln b/CodeConverter.sln
index 33588d6a1..ac5a19be0 100644
--- a/CodeConverter.sln
+++ b/CodeConverter.sln
@@ -1,9 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2010
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29721.120
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.CodeConverter", "ICSharpCode.CodeConverter\ICSharpCode.CodeConverter.csproj", "{7EA075C6-6406-445C-AB77-6C47AFF88D58}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeConverter", "CodeConverter\CodeConverter.csproj", "{7EA075C6-6406-445C-AB77-6C47AFF88D58}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{21DBA1CE-AF55-4159-B04B-B8C621BE8921}"
EndProject
@@ -14,7 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeConverter.Web", "CodeConverter.Web\CodeConverter.Web.csproj", "{08A20D4F-6310-43BB-B339-6317ACF3B52E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "Web\Web.csproj", "{08A20D4F-6310-43BB-B339-6317ACF3B52E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/CodeConverter/AssemblyInfo.cs b/CodeConverter/AssemblyInfo.cs
new file mode 100644
index 000000000..f7afff2b9
--- /dev/null
+++ b/CodeConverter/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("ICSharpCode.CodeConverter.Tests")]
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/CSharp/AdditionalInitializers.cs b/CodeConverter/CSharp/AdditionalInitializers.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/AdditionalInitializers.cs
rename to CodeConverter/CSharp/AdditionalInitializers.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/AdditionalLocal.cs b/CodeConverter/CSharp/AdditionalLocal.cs
similarity index 91%
rename from ICSharpCode.CodeConverter/CSharp/AdditionalLocal.cs
rename to CodeConverter/CSharp/AdditionalLocal.cs
index 7b40cf29e..0decb9205 100644
--- a/ICSharpCode.CodeConverter/CSharp/AdditionalLocal.cs
+++ b/CodeConverter/CSharp/AdditionalLocal.cs
@@ -1,6 +1,4 @@
using System;
-using System.Text;
-using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/AdditionalLocals.cs b/CodeConverter/CSharp/AdditionalLocals.cs
similarity index 97%
rename from ICSharpCode.CodeConverter/CSharp/AdditionalLocals.cs
rename to CodeConverter/CSharp/AdditionalLocals.cs
index 46adc9695..1d2234320 100644
--- a/ICSharpCode.CodeConverter/CSharp/AdditionalLocals.cs
+++ b/CodeConverter/CSharp/AdditionalLocals.cs
@@ -1,7 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ICSharpCode.CodeConverter.CSharp
{
diff --git a/ICSharpCode.CodeConverter/CSharp/ByRefParameterVisitor.cs b/CodeConverter/CSharp/ByRefParameterVisitor.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/ByRefParameterVisitor.cs
rename to CodeConverter/CSharp/ByRefParameterVisitor.cs
index 0bd2ea8f0..eba3aa7cd 100644
--- a/ICSharpCode.CodeConverter/CSharp/ByRefParameterVisitor.cs
+++ b/CodeConverter/CSharp/ByRefParameterVisitor.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Text;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
diff --git a/ICSharpCode.CodeConverter/CSharp/CachedReflectedDelegates.cs b/CodeConverter/CSharp/CachedReflectedDelegates.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/CachedReflectedDelegates.cs
rename to CodeConverter/CSharp/CachedReflectedDelegates.cs
index c60dd1a65..bcf1d7ed0 100644
--- a/ICSharpCode.CodeConverter/CSharp/CachedReflectedDelegates.cs
+++ b/CodeConverter/CSharp/CachedReflectedDelegates.cs
@@ -3,7 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using ICSharpCode.CodeConverter.Util;
+using System.Reflection;
using Microsoft.CodeAnalysis;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs b/CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs
similarity index 89%
rename from ICSharpCode.CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs
rename to CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs
index adf943310..f80297a11 100644
--- a/ICSharpCode.CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs
+++ b/CodeConverter/CSharp/CommentConvertingMethodBodyVisitor.cs
@@ -1,14 +1,10 @@
using System;
-using System.Linq;
using System.Threading.Tasks;
-using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.VisualBasic;
-using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using CSSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using SyntaxNodeExtensions = ICSharpCode.CodeConverter.Util.SyntaxNodeExtensions;
namespace ICSharpCode.CodeConverter.CSharp
{
diff --git a/ICSharpCode.CodeConverter/CSharp/CommentConvertingNodesVisitor.cs b/CodeConverter/CSharp/CommentConvertingNodesVisitor.cs
similarity index 81%
rename from ICSharpCode.CodeConverter/CSharp/CommentConvertingNodesVisitor.cs
rename to CodeConverter/CSharp/CommentConvertingNodesVisitor.cs
index d00d1a478..389576398 100644
--- a/ICSharpCode.CodeConverter/CSharp/CommentConvertingNodesVisitor.cs
+++ b/CodeConverter/CSharp/CommentConvertingNodesVisitor.cs
@@ -1,17 +1,10 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using ICSharpCode.CodeConverter.Shared;
+using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using VbSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
using CsSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
-using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using SyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
-using SyntaxNodeExtensions = ICSharpCode.CodeConverter.Util.SyntaxNodeExtensions;
namespace ICSharpCode.CodeConverter.CSharp
{
diff --git a/ICSharpCode.CodeConverter/CSharp/CommentConvertingVisitorWrapper.cs b/CodeConverter/CSharp/CommentConvertingVisitorWrapper.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/CommentConvertingVisitorWrapper.cs
rename to CodeConverter/CSharp/CommentConvertingVisitorWrapper.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs b/CodeConverter/CSharp/CommonConversions.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/CommonConversions.cs
rename to CodeConverter/CSharp/CommonConversions.cs
index 8a80d31c2..0f4420246 100644
--- a/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs
+++ b/CodeConverter/CSharp/CommonConversions.cs
@@ -20,7 +20,6 @@
using ArrayTypeSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.ArrayTypeSyntax;
using CSharpExtensions = Microsoft.CodeAnalysis.CSharp.CSharpExtensions;
using ExpressionSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax;
-using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using SyntaxFacts = Microsoft.CodeAnalysis.CSharp.SyntaxFacts;
using SyntaxKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
diff --git a/ICSharpCode.CodeConverter/CSharp/CsSyntaxNodeExtensions.cs b/CodeConverter/CSharp/CsSyntaxNodeExtensions.cs
similarity index 78%
rename from ICSharpCode.CodeConverter/CSharp/CsSyntaxNodeExtensions.cs
rename to CodeConverter/CSharp/CsSyntaxNodeExtensions.cs
index 901c7bb57..133a2921d 100644
--- a/ICSharpCode.CodeConverter/CSharp/CsSyntaxNodeExtensions.cs
+++ b/CodeConverter/CSharp/CsSyntaxNodeExtensions.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
diff --git a/ICSharpCode.CodeConverter/CSharp/DeclarationNodeVisitor.cs b/CodeConverter/CSharp/DeclarationNodeVisitor.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/DeclarationNodeVisitor.cs
rename to CodeConverter/CSharp/DeclarationNodeVisitor.cs
index a0939cb24..07183d120 100644
--- a/ICSharpCode.CodeConverter/CSharp/DeclarationNodeVisitor.cs
+++ b/CodeConverter/CSharp/DeclarationNodeVisitor.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
@@ -11,10 +9,8 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
-using Microsoft.VisualBasic.CompilerServices;
using StringComparer = System.StringComparer;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using SyntaxNodeExtensions = ICSharpCode.CodeConverter.Util.SyntaxNodeExtensions;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
using SyntaxToken = Microsoft.CodeAnalysis.SyntaxToken;
diff --git a/ICSharpCode.CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs b/CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs
similarity index 81%
rename from ICSharpCode.CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs
rename to CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs
index b5894d9fd..fc1724748 100644
--- a/ICSharpCode.CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs
+++ b/CodeConverter/CSharp/DefiniteAssignmentAnalyzer.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
+using System.Linq;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
diff --git a/ICSharpCode.CodeConverter/CSharp/ExpressionNodeVisitor.cs b/CodeConverter/CSharp/ExpressionNodeVisitor.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/ExpressionNodeVisitor.cs
rename to CodeConverter/CSharp/ExpressionNodeVisitor.cs
index 41c22c94d..43d1eb4ca 100644
--- a/ICSharpCode.CodeConverter/CSharp/ExpressionNodeVisitor.cs
+++ b/CodeConverter/CSharp/ExpressionNodeVisitor.cs
@@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Linq;
-using System.Linq.Expressions;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.VisualBasic.CompilerServices;
using IOperation = Microsoft.CodeAnalysis.IOperation;
-using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using SyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
diff --git a/ICSharpCode.CodeConverter/CSharp/LambdaConverter.cs b/CodeConverter/CSharp/LambdaConverter.cs
similarity index 97%
rename from ICSharpCode.CodeConverter/CSharp/LambdaConverter.cs
rename to CodeConverter/CSharp/LambdaConverter.cs
index b7de0bee3..5b4b6eaf9 100644
--- a/ICSharpCode.CodeConverter/CSharp/LambdaConverter.cs
+++ b/CodeConverter/CSharp/LambdaConverter.cs
@@ -5,10 +5,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Operations;
-using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
-using VBasic = Microsoft.CodeAnalysis.VisualBasic;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/LiteralConversions.cs b/CodeConverter/CSharp/LiteralConversions.cs
similarity index 97%
rename from ICSharpCode.CodeConverter/CSharp/LiteralConversions.cs
rename to CodeConverter/CSharp/LiteralConversions.cs
index 5648d9c86..c75f5dc97 100644
--- a/ICSharpCode.CodeConverter/CSharp/LiteralConversions.cs
+++ b/CodeConverter/CSharp/LiteralConversions.cs
@@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis.CSharp;
using ExpressionSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax;
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using SyntaxKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
-using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
-using CSSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
using CSSyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs b/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
rename to CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
index 68a9cac5e..3ac5832b3 100644
--- a/ICSharpCode.CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
+++ b/CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Linq;
-using System.Text;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
@@ -14,7 +12,6 @@
using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
-using static ICSharpCode.CodeConverter.CSharp.SyntaxKindExtensions;
using Microsoft.CodeAnalysis.Text;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/MethodInfoExtensions.cs b/CodeConverter/CSharp/MethodInfoExtensions.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/MethodInfoExtensions.cs
rename to CodeConverter/CSharp/MethodInfoExtensions.cs
index 5f344935b..885f2d03f 100644
--- a/ICSharpCode.CodeConverter/CSharp/MethodInfoExtensions.cs
+++ b/CodeConverter/CSharp/MethodInfoExtensions.cs
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Reflection;
-using System.Text;
using ICSharpCode.CodeConverter.Util;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/MethodWithHandles.cs b/CodeConverter/CSharp/MethodWithHandles.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/MethodWithHandles.cs
rename to CodeConverter/CSharp/MethodWithHandles.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/MethodsWithHandles.cs b/CodeConverter/CSharp/MethodsWithHandles.cs
similarity index 98%
rename from ICSharpCode.CodeConverter/CSharp/MethodsWithHandles.cs
rename to CodeConverter/CSharp/MethodsWithHandles.cs
index 8d911a566..b18387c9c 100644
--- a/ICSharpCode.CodeConverter/CSharp/MethodsWithHandles.cs
+++ b/CodeConverter/CSharp/MethodsWithHandles.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
diff --git a/ICSharpCode.CodeConverter/CSharp/OperationExtensions.cs b/CodeConverter/CSharp/OperationExtensions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/OperationExtensions.cs
rename to CodeConverter/CSharp/OperationExtensions.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/ProjectExtensions.cs b/CodeConverter/CSharp/ProjectExtensions.cs
similarity index 62%
rename from ICSharpCode.CodeConverter/CSharp/ProjectExtensions.cs
rename to CodeConverter/CSharp/ProjectExtensions.cs
index a831b46ca..4d383647a 100644
--- a/ICSharpCode.CodeConverter/CSharp/ProjectExtensions.cs
+++ b/CodeConverter/CSharp/ProjectExtensions.cs
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using Microsoft.CodeAnalysis;
@@ -9,6 +8,8 @@ namespace ICSharpCode.CodeConverter.CSharp
{
internal static class ProjectExtensions
{
+ private static char[] DirSeparators = new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
+
public static Project CreateReferenceOnlyProjectFromAnyOptions(this Project project, CompilationOptions baseOptions)
{
var options = baseOptions.WithMetadataImportOptionsAll();
@@ -41,33 +42,50 @@ public static Project ToProjectFromAnyOptions(this Project project, CompilationO
public static string GetDirectoryPath(this Project proj)
{
string projectFilePath = proj.FilePath;
- return projectFilePath != null ? Path.GetDirectoryName(projectFilePath) : null;
+ if (projectFilePath != null) {
+ return Path.GetDirectoryName(projectFilePath);
+ }
+
+ string solutionPath = GetDirectoryPath(proj);
+ return proj.Documents
+ .Where(d => d.FilePath != null && d.FilePath.StartsWith(solutionPath))
+ .Select(d => d.FilePath.Replace(solutionPath, "").TrimStart(DirSeparators))
+ .Where(p => p.IndexOfAny(DirSeparators) > -1)
+ .Select(p => p.Split(DirSeparators).First())
+ .OrderByDescending(p => p.Contains(proj.AssemblyName))
+ .FirstOrDefault() ?? solutionPath;
+ }
+
+ public static string GetDirectoryPath(this Solution soln)
+ {
+ // Find a directory for projects that don't have a projectfile (e.g. websites) Current dir if in memory
+ return soln.FilePath != null ? Path.GetDirectoryName(soln.FilePath) : Directory.GetCurrentDirectory();
}
- public static (Project project, List<(string Path, DocumentId DocId, string[] Errors)> firstPassDocIds)
- WithDocuments(this Project project, (string Path, SyntaxNode Node, string[] Errors)[] results)
+ public static (Project project, List> firstPassDocIds)
+ WithDocuments(this Project project, WipFileConversion[] results)
{
var firstPassDocIds = results.Select(firstPassResult =>
{
DocumentId docId = null;
- if (firstPassResult.Node != null)
+ if (firstPassResult.Wip != null)
{
- var document = project.AddDocument(firstPassResult.Path, firstPassResult.Node,
+ var document = project.AddDocument(firstPassResult.Path, firstPassResult.Wip,
filePath: firstPassResult.Path);
project = document.Project;
docId = document.Id;
}
- return (firstPassResult.Path, docId, firstPassResult.Errors);
+ return WipFileConversion.Create(firstPassResult.Path, docId, firstPassResult.Errors);
}).ToList();
//ToList ensures that the project returned has all documents added. We only return DocumentIds so it's easy to look up the final version of the doc later
return (project, firstPassDocIds);
}
- public static IEnumerable<(string Path, Document Doc, string[] Errors)> GetDocuments(this Project project, List<(string treeFilePath, DocumentId docId, string[] errors)> docIds)
+ public static IEnumerable> GetDocuments(this Project project, List> docIds)
{
- return docIds.Select(f => (f.treeFilePath, f.docId != null ? project.GetDocument(f.docId) : null, f.errors));
+ return docIds.Select(f => WipFileConversion.Create(f.Path, f.Wip != null ? project.GetDocument(f.Wip) : null, f.Errors));
}
}
}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs b/CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
similarity index 88%
rename from ICSharpCode.CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
rename to CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
index 42c8aba6a..9281e3134 100644
--- a/ICSharpCode.CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
+++ b/CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
@@ -1,16 +1,14 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Rename;
-using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
+using System.Threading;
namespace ICSharpCode.CodeConverter.CSharp
{
@@ -22,12 +20,12 @@ namespace ICSharpCode.CodeConverter.CSharp
///
internal static class ProjectMergedDeclarationExtensions
{
- public static async Task WithRenamedMergedMyNamespace(this Project vbProject)
+ public static async Task WithRenamedMergedMyNamespace(this Project vbProject, CancellationToken cancellationToken)
{
string name = "MyNamespace";
- var projectDir = Path.Combine(vbProject.GetDirectoryPath() ?? vbProject.AssemblyName, "My Project");
+ var projectDir = Path.Combine(vbProject.GetDirectoryPath(), "My Project");
- var compilation = await vbProject.GetCompilationAsync();
+ var compilation = await vbProject.GetCompilationAsync(cancellationToken);
string embeddedSourceText = (await GetAllEmbeddedSourceText(compilation));
string generatedSourceText = (await GetDynamicallyGeneratedSourceText(compilation));
@@ -114,27 +112,29 @@ private static string Renamespace(this string sourceText)
.Replace("Namespace My", $"Namespace {Constants.MergedMyNamespace}");
}
- public static async Task RenameMergedNamespaces(this Project project)
+ public static async Task RenameMergedNamespaces(this Project project, CancellationToken cancellationToken)
{
- project = await RenamePrefix(project, Constants.MergedMyNamespace, "My", SymbolFilter.Namespace);
- project = await RenamePrefix(project, Constants.MergedMsVbNamespace, "VisualBasic", SymbolFilter.Namespace);
- project = await RenamePrefix(project, Constants.MergedMyMemberPrefix, "", SymbolFilter.Member);
+ project = await RenamePrefix(project, Constants.MergedMyNamespace, "My", SymbolFilter.Namespace, cancellationToken);
+ project = await RenamePrefix(project, Constants.MergedMsVbNamespace, "VisualBasic", SymbolFilter.Namespace, cancellationToken);
+ project = await RenamePrefix(project, Constants.MergedMyMemberPrefix, "", SymbolFilter.Member, cancellationToken);
return project;
}
- private static async Task RenamePrefix(Project project, string oldNamePrefix, string newNamePrefix, SymbolFilter symbolFilter)
+ private static async Task RenamePrefix(Project project, string oldNamePrefix, string newNamePrefix, SymbolFilter symbolFilter, CancellationToken cancellationToken)
{
- for (var symbolToRename = await GetFirstSymbolStartingWith(project, oldNamePrefix, symbolFilter); symbolToRename != null; symbolToRename = await GetFirstSymbolStartingWith(project, oldNamePrefix, symbolFilter))
+ for (var symbolToRename = await GetFirstSymbolStartingWith(project, oldNamePrefix, symbolFilter, cancellationToken);
+ symbolToRename != null;
+ symbolToRename = await GetFirstSymbolStartingWith(project, oldNamePrefix, symbolFilter, cancellationToken))
{
- var renamedSolution = await Renamer.RenameSymbolAsync(project.Solution, symbolToRename, symbolToRename.Name.Replace(oldNamePrefix, newNamePrefix), default(OptionSet));
+ var renamedSolution = await Renamer.RenameSymbolAsync(project.Solution, symbolToRename, symbolToRename.Name.Replace(oldNamePrefix, newNamePrefix), default(OptionSet), cancellationToken);
project = renamedSolution.GetProject(project.Id);
}
return project;
}
- private static async Task GetFirstSymbolStartingWith(Project project, string symbolPrefix, SymbolFilter symbolFilter)
+ private static async Task GetFirstSymbolStartingWith(Project project, string symbolPrefix, SymbolFilter symbolFilter, CancellationToken cancellationToken)
{
- var compilation = await project.GetCompilationAsync();
+ var compilation = await project.GetCompilationAsync(cancellationToken);
return compilation.GetSymbolsWithName(s => s.StartsWith(symbolPrefix), symbolFilter).FirstOrDefault();
}
}
diff --git a/ICSharpCode.CodeConverter/CSharp/QueryConverter.cs b/CodeConverter/CSharp/QueryConverter.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/QueryConverter.cs
rename to CodeConverter/CSharp/QueryConverter.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/SemanticModelExtensions.cs b/CodeConverter/CSharp/SemanticModelExtensions.cs
similarity index 93%
rename from ICSharpCode.CodeConverter/CSharp/SemanticModelExtensions.cs
rename to CodeConverter/CSharp/SemanticModelExtensions.cs
index 133a83a5d..67a1c131f 100644
--- a/ICSharpCode.CodeConverter/CSharp/SemanticModelExtensions.cs
+++ b/CodeConverter/CSharp/SemanticModelExtensions.cs
@@ -1,7 +1,4 @@
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using System.Reflection;
-using ICSharpCode.CodeConverter.Util;
+using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.VisualBasic;
diff --git a/ICSharpCode.CodeConverter/CSharp/SourceTriviaMapKind.cs b/CodeConverter/CSharp/SourceTriviaMapKind.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/SourceTriviaMapKind.cs
rename to CodeConverter/CSharp/SourceTriviaMapKind.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs b/CodeConverter/CSharp/SyntaxKindExtensions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/SyntaxKindExtensions.cs
rename to CodeConverter/CSharp/SyntaxKindExtensions.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs b/CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs
similarity index 87%
rename from ICSharpCode.CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs
rename to CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs
index 08ea1ea0c..07a956794 100644
--- a/ICSharpCode.CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs
+++ b/CodeConverter/CSharp/SyntaxNodeVisitorExtensions.cs
@@ -1,11 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using ICSharpCode.CodeConverter.Shared;
+using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using CS = Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.VisualBasic;
namespace ICSharpCode.CodeConverter.CSharp
diff --git a/ICSharpCode.CodeConverter/CSharp/TypeConversionAnalyzer.cs b/CodeConverter/CSharp/TypeConversionAnalyzer.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/TypeConversionAnalyzer.cs
rename to CodeConverter/CSharp/TypeConversionAnalyzer.cs
index e35a44f79..c92115488 100644
--- a/ICSharpCode.CodeConverter/CSharp/TypeConversionAnalyzer.cs
+++ b/CodeConverter/CSharp/TypeConversionAnalyzer.cs
@@ -5,7 +5,6 @@
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using CSSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Operations;
diff --git a/ICSharpCode.CodeConverter/CSharp/UsageTypeAnalyzer.cs b/CodeConverter/CSharp/UsageTypeAnalyzer.cs
similarity index 96%
rename from ICSharpCode.CodeConverter/CSharp/UsageTypeAnalyzer.cs
rename to CodeConverter/CSharp/UsageTypeAnalyzer.cs
index 138bf615d..e898b23e0 100644
--- a/ICSharpCode.CodeConverter/CSharp/UsageTypeAnalyzer.cs
+++ b/CodeConverter/CSharp/UsageTypeAnalyzer.cs
@@ -1,7 +1,5 @@
-using System;
-using System.Linq;
+using System.Linq;
using System.Threading.Tasks;
-using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols;
diff --git a/ICSharpCode.CodeConverter/CSharp/VBToCSConversion.cs b/CodeConverter/CSharp/VBToCSConversion.cs
similarity index 93%
rename from ICSharpCode.CodeConverter/CSharp/VBToCSConversion.cs
rename to CodeConverter/CSharp/VBToCSConversion.cs
index 123012be5..c968cc7a7 100644
--- a/ICSharpCode.CodeConverter/CSharp/VBToCSConversion.cs
+++ b/CodeConverter/CSharp/VBToCSConversion.cs
@@ -3,21 +3,15 @@
using System.Linq;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
-using ICSharpCode.CodeConverter.VB;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using CSSyntax = Microsoft.CodeAnalysis.CSharp.Syntax;
using SyntaxKind = Microsoft.CodeAnalysis.VisualBasic.SyntaxKind;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.Operations;
-using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.VisualBasic;
-using Conversion = Microsoft.CodeAnalysis.CSharp.Conversion;
using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
-using LanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion;
+using System.Threading;
namespace ICSharpCode.CodeConverter.CSharp
{
@@ -29,12 +23,17 @@ public class VBToCSConversion : ILanguageConversion
private const string UnresolvedNamespaceDiagnosticId = "CS0246";
private VBToCSProjectContentsConverter _vbToCsProjectContentsConverter;
+ private IProgress _progress;
+ private CancellationToken _cancellationToken;
+
public ConversionOptions ConversionOptions { get; set; }
- public async Task CreateProjectContentsConverter(Project project)
+ public async Task CreateProjectContentsConverter(Project project, IProgress progress, CancellationToken cancellationToken)
{
- _vbToCsProjectContentsConverter = new VBToCSProjectContentsConverter(ConversionOptions);
+ _progress = progress;
+ _cancellationToken = cancellationToken;
+ _vbToCsProjectContentsConverter = new VBToCSProjectContentsConverter(ConversionOptions, progress, cancellationToken);
await _vbToCsProjectContentsConverter.InitializeSourceAsync(project);
return _vbToCsProjectContentsConverter;
}
@@ -144,7 +143,7 @@ public List FindSingleImportantChild(SyntaxNode annotatedNode)
public async Task SingleSecondPass(Document doc)
{
- return await doc.SimplifyStatements(UnresolvedNamespaceDiagnosticId);
+ return await doc.SimplifyStatements(UnresolvedNamespaceDiagnosticId, _cancellationToken);
}
public SyntaxTree CreateTree(string text)
diff --git a/ICSharpCode.CodeConverter/CSharp/VBToCSProjectContentsConverter.cs b/CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
similarity index 78%
rename from ICSharpCode.CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
rename to CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
index 15529c3fa..d49890170 100644
--- a/ICSharpCode.CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
+++ b/CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
@@ -1,13 +1,13 @@
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
-using ICSharpCode.CodeConverter.VB;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.VisualBasic;
-using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
using LanguageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion;
+using System;
namespace ICSharpCode.CodeConverter.CSharp
{
@@ -29,10 +29,14 @@ internal class VBToCSProjectContentsConverter : IProjectContentsConverter
private static readonly CSharpParseOptions DoNotAllowImplicitDefault = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7);
private Project _csharpReferenceProject;
+ private readonly IProgress _progress;
+ private readonly CancellationToken _cancellationToken;
- public VBToCSProjectContentsConverter(ConversionOptions conversionOptions)
+ public VBToCSProjectContentsConverter(ConversionOptions conversionOptions, IProgress progress, CancellationToken cancellationToken)
{
_conversionOptions = conversionOptions;
+ _progress = progress;
+ _cancellationToken = cancellationToken;
}
public string RootNamespace => _conversionOptions.RootNamespaceOverride ??
@@ -43,8 +47,8 @@ public async Task InitializeSourceAsync(Project project)
var cSharpCompilationOptions = CSharpCompiler.CreateCompilationOptions();
_convertedCsProject = project.ToProjectFromAnyOptions(cSharpCompilationOptions, DoNotAllowImplicitDefault);
_csharpReferenceProject = project.CreateReferenceOnlyProjectFromAnyOptions(cSharpCompilationOptions);
- _csharpViewOfVbSymbols = (CSharpCompilation) await _csharpReferenceProject.GetCompilationAsync();
- Project = await project.WithRenamedMergedMyNamespace();
+ _csharpViewOfVbSymbols = (CSharpCompilation) await _csharpReferenceProject.GetCompilationAsync(_cancellationToken);
+ Project = await project.WithRenamedMergedMyNamespace(_cancellationToken);
}
string IProjectContentsConverter.LanguageVersion { get { return LanguageVersion.Default.ToDisplayString(); } }
@@ -53,14 +57,14 @@ public async Task InitializeSourceAsync(Project project)
public async Task SingleFirstPass(Document document)
{
- return await VisualBasicConverter.ConvertCompilationTree(document, _csharpViewOfVbSymbols, _csharpReferenceProject);
+ return await VisualBasicConverter.ConvertCompilationTree(document, _csharpViewOfVbSymbols, _csharpReferenceProject, _cancellationToken);
}
- public async Task<(Project project, List<(string Path, DocumentId DocId, string[] Errors)> firstPassDocIds)>
- GetConvertedProject((string Path, SyntaxNode Node, string[] Errors)[] firstPassResults)
+ public async Task<(Project project, List> firstPassDocIds)>
+ GetConvertedProject(WipFileConversion[] firstPassResults)
{
var (project, docIds) = _convertedCsProject.WithDocuments(firstPassResults);
- return (await project.RenameMergedNamespaces(), docIds);
+ return (await project.RenameMergedNamespaces(_cancellationToken), docIds);
}
}
}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/CSharp/ValidSyntaxFactory.cs b/CodeConverter/CSharp/ValidSyntaxFactory.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/ValidSyntaxFactory.cs
rename to CodeConverter/CSharp/ValidSyntaxFactory.cs
index 01a4854be..fb8c26007 100644
--- a/ICSharpCode.CodeConverter/CSharp/ValidSyntaxFactory.cs
+++ b/CodeConverter/CSharp/ValidSyntaxFactory.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Linq.Expressions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
diff --git a/ICSharpCode.CodeConverter/CSharp/VbMethodSyntaxExtensions.cs b/CodeConverter/CSharp/VbMethodSyntaxExtensions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/VbMethodSyntaxExtensions.cs
rename to CodeConverter/CSharp/VbMethodSyntaxExtensions.cs
diff --git a/ICSharpCode.CodeConverter/CSharp/VbNameExpander.cs b/CodeConverter/CSharp/VbNameExpander.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/CSharp/VbNameExpander.cs
rename to CodeConverter/CSharp/VbNameExpander.cs
index 7dd2a6e99..cb2274bb6 100644
--- a/ICSharpCode.CodeConverter/CSharp/VbNameExpander.cs
+++ b/CodeConverter/CSharp/VbNameExpander.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Linq;
-using System.Threading;
+using System.Threading;
using ICSharpCode.CodeConverter.Shared;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
diff --git a/ICSharpCode.CodeConverter/CSharp/VbSyntaxNodeExtensions.cs b/CodeConverter/CSharp/VbSyntaxNodeExtensions.cs
similarity index 98%
rename from ICSharpCode.CodeConverter/CSharp/VbSyntaxNodeExtensions.cs
rename to CodeConverter/CSharp/VbSyntaxNodeExtensions.cs
index b7866fb41..6bd9543d6 100644
--- a/ICSharpCode.CodeConverter/CSharp/VbSyntaxNodeExtensions.cs
+++ b/CodeConverter/CSharp/VbSyntaxNodeExtensions.cs
@@ -1,7 +1,6 @@
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.VisualBasic;
using ArgumentSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ArgumentSyntax;
using BinaryExpressionSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.BinaryExpressionSyntax;
diff --git a/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs b/CodeConverter/CSharp/VisualBasicConverter.cs
similarity index 81%
rename from ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs
rename to CodeConverter/CSharp/VisualBasicConverter.cs
index bdd1f3775..41c25e817 100644
--- a/ICSharpCode.CodeConverter/CSharp/VisualBasicConverter.cs
+++ b/CodeConverter/CSharp/VisualBasicConverter.cs
@@ -1,29 +1,27 @@
using System;
-using System.Linq;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.Simplification;
-using VBasic = Microsoft.CodeAnalysis.VisualBasic;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
using CSS = Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.Threading;
namespace ICSharpCode.CodeConverter.CSharp
{
internal static class VisualBasicConverter
{
public static async Task ConvertCompilationTree(Document document,
- CSharpCompilation csharpViewOfVbSymbols, Project csharpReferenceProject)
+ CSharpCompilation csharpViewOfVbSymbols, Project csharpReferenceProject, CancellationToken cancellationToken)
{
- document = await document.WithExpandedRootAsync();
- var root = await document.GetSyntaxRootAsync() as VBSyntax.CompilationUnitSyntax ??
+ document = await document.WithExpandedRootAsync(cancellationToken);
+ var root = await document.GetSyntaxRootAsync(cancellationToken) as VBSyntax.CompilationUnitSyntax ??
throw new InvalidOperationException(NullRootError(document));
- var compilation = await document.Project.GetCompilationAsync();
- var tree = await document.GetSyntaxTreeAsync();
+ var compilation = await document.Project.GetCompilationAsync(cancellationToken);
+ var tree = await document.GetSyntaxTreeAsync(cancellationToken);
var csSyntaxGenerator = SyntaxGenerator.GetGenerator(csharpReferenceProject);
@@ -34,7 +32,7 @@ public static async Task ConvertCompilationTree(Document document,
try {
// This call is very expensive for large documents. Should look for a more performant version, e.g. Is NormalizeWhitespace good enough?
- converted = (CSS.CompilationUnitSyntax)Formatter.Format(converted, document.Project.Solution.Workspace);
+ converted = (CSS.CompilationUnitSyntax)Formatter.Format(converted, document.Project.Solution.Workspace, cancellationToken: cancellationToken);
return LineTriviaMapper.MapSourceTriviaToTarget(root, converted);
} catch (Exception) { //TODO log
return converted;
diff --git a/ICSharpCode.CodeConverter/CSharp/VisualBasicEqualityComparison.cs b/CodeConverter/CSharp/VisualBasicEqualityComparison.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CSharp/VisualBasicEqualityComparison.cs
rename to CodeConverter/CSharp/VisualBasicEqualityComparison.cs
diff --git a/ICSharpCode.CodeConverter/CodeConverter.cs b/CodeConverter/CodeConverter.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/CodeConverter.cs
rename to CodeConverter/CodeConverter.cs
diff --git a/ICSharpCode.CodeConverter/ICSharpCode.CodeConverter.csproj b/CodeConverter/CodeConverter.csproj
similarity index 71%
rename from ICSharpCode.CodeConverter/ICSharpCode.CodeConverter.csproj
rename to CodeConverter/CodeConverter.csproj
index c7258e055..95eb4a939 100644
--- a/ICSharpCode.CodeConverter/ICSharpCode.CodeConverter.csproj
+++ b/CodeConverter/CodeConverter.csproj
@@ -1,15 +1,13 @@
- netstandard1.3
+ netstandard2.0
ICSharpCode.CodeConverter
ICSharpCode.CodeConverter
- portable-net45+win8
ICSharpCode
Convert VB.NET to/from C#
-
- * Accurate: Full project context (through Roslyn) is used to get the most accurate conversion.
- * Actively developed: User feedback helps us continuously strive for a more accurate conversion.
- * Completely free and open source: Check out [GitHub](https://github.com/icsharpcode/CodeConverter#code-converter-).
+* Accurate: Full project context (through Roslyn) is used to get the most accurate conversion.
+* Actively developed: User feedback helps us continuously strive for a more accurate conversion.
+* Completely free and open source: Check out [GitHub](https://github.com/icsharpcode/CodeConverter#code-converter-).
Code Converter for C# to/from VB.NET
Copyright (c) 2017-2020 AlphaSierraPapa for the CodeConverter team
7.9.0.0
@@ -23,7 +21,7 @@
Convert Converter Conversion C# CSharp CS VB VB.NET Visual Basic Code Free Roslyn Tool
See https://github.com/icsharpcode/CodeConverter/blob/master/CHANGELOG.md
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- 7.3
+ 8.0
$(NoWarn);1998
@@ -33,18 +31,16 @@
-
-
-
-
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
+
+
diff --git a/ICSharpCode.CodeConverter/CodeWithOptions.cs b/CodeConverter/CodeWithOptions.cs
similarity index 95%
rename from ICSharpCode.CodeConverter/CodeWithOptions.cs
rename to CodeConverter/CodeWithOptions.cs
index 8f88a1cb2..ed42d2558 100644
--- a/ICSharpCode.CodeConverter/CodeWithOptions.cs
+++ b/CodeConverter/CodeWithOptions.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection;
-using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
namespace ICSharpCode.CodeConverter
@@ -22,7 +20,7 @@ public class CodeWithOptions
private static IEnumerable GetRefs(IReadOnlyCollection types)
{
- return types.Select(type => MetadataReference.CreateFromFile(type.GetAssemblyLocation()));
+ return types.Select(type => MetadataReference.CreateFromFile(type.Assembly.Location));
}
public string Text { get; private set; }
diff --git a/ICSharpCode.CodeConverter/ConversionResult.cs b/CodeConverter/ConversionResult.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/ConversionResult.cs
rename to CodeConverter/ConversionResult.cs
diff --git a/ICSharpCode.CodeConverter/ILanguageConversion.cs b/CodeConverter/ILanguageConversion.cs
similarity index 89%
rename from ICSharpCode.CodeConverter/ILanguageConversion.cs
rename to CodeConverter/ILanguageConversion.cs
index cb4e025cc..6ac86aaef 100644
--- a/ICSharpCode.CodeConverter/ILanguageConversion.cs
+++ b/CodeConverter/ILanguageConversion.cs
@@ -2,6 +2,8 @@
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Shared;
using Microsoft.CodeAnalysis;
+using System.Threading;
+using System;
namespace ICSharpCode.CodeConverter
{
@@ -22,7 +24,7 @@ SyntaxNode GetSurroundedNode(IEnumerable descendantNodes,
string TargetLanguage { get; }
ConversionOptions ConversionOptions { get; set; }
- Task CreateProjectContentsConverter(Project project);
+ Task CreateProjectContentsConverter(Project project, IProgress progress, CancellationToken cancellationToken);
string PostTransformProjectFile(string xml);
Document CreateProjectDocumentFromTree(Workspace workspace, SyntaxTree tree,
diff --git a/CodeConverter/Shared/ActionDisposable.cs b/CodeConverter/Shared/ActionDisposable.cs
new file mode 100644
index 000000000..d68802c57
--- /dev/null
+++ b/CodeConverter/Shared/ActionDisposable.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace ICSharpCode.CodeConverter.Shared
+{
+
+ internal sealed class ActionDisposable : IDisposable
+ {
+ private readonly Action _onDispose;
+
+ public ActionDisposable(Action onDispose)
+ {
+ _onDispose = onDispose;
+ }
+
+ public void Dispose() => _onDispose();
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Shared/AnnotationConstants.cs b/CodeConverter/Shared/AnnotationConstants.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/AnnotationConstants.cs
rename to CodeConverter/Shared/AnnotationConstants.cs
diff --git a/CodeConverter/Shared/AsyncEnumerableTaskExtensions.cs b/CodeConverter/Shared/AsyncEnumerableTaskExtensions.cs
new file mode 100644
index 000000000..afe372102
--- /dev/null
+++ b/CodeConverter/Shared/AsyncEnumerableTaskExtensions.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Threading.Tasks.Dataflow;
+
+namespace ICSharpCode.CodeConverter.Shared
+{
+ internal static class AsyncEnumerableTaskExtensions
+ {
+ public static async Task SelectManyAsync(this IEnumerable nodes,
+ Func>> selector)
+ {
+ var selectAsync = await nodes.SelectAsync(selector);
+ return selectAsync.SelectMany(x => x).ToArray();
+ }
+
+ /// High throughput parallel lazy-ish method
+ ///
+ /// Inspired by https://stackoverflow.com/a/58564740/1128762
+ ///
+ public static async IAsyncEnumerable ParallelSelectAwait(this IEnumerable source,
+ Func> selector, int maxDop, [EnumeratorCancellation] CancellationToken token = default)
+ {
+ var processor = new TransformBlock(selector, new ExecutionDataflowBlockOptions {
+ MaxDegreeOfParallelism = maxDop,
+ BoundedCapacity = (maxDop * 5) / 4,
+ CancellationToken = token
+ });
+
+ foreach (var item in source) {
+ while (!processor.Post(item)) {
+ yield return await ReceiveAsync();
+ }
+ if (processor.TryReceive(out var result)) {
+ yield return result;
+ }
+ }
+ processor.Complete();
+
+ while (await processor.OutputAvailableAsync(token)) {
+ yield return Receive();
+ }
+
+ async Task ReceiveAsync()
+ {
+ if (!await processor.OutputAvailableAsync() && !token.IsCancellationRequested) throw new InvalidOperationException("No output available after posting output and waiting");
+ return Receive();
+ }
+
+ TResult Receive()
+ {
+ token.ThrowIfCancellationRequested();
+ if (!processor.TryReceive(out var result)) throw new InvalidOperationException("Nothing received even though output available");
+ return result;
+ }
+ }
+
+ public static async Task SelectAsync(this IEnumerable nodes,
+ Func> selector)
+ {
+ var nodesWithOrders = nodes.Select((input, originalOrder) => (input, originalOrder));
+ return await nodesWithOrders.SelectAsync(nwo => selector(nwo.input, nwo.originalOrder));
+ }
+
+ public static async Task SelectAsync(this IEnumerable source,
+ Func> selector)
+ {
+ var partitionResults = new List();
+ foreach (var partitionMember in source) {
+ var result = await selector(partitionMember);
+ partitionResults.Add(result);
+ }
+
+ return partitionResults.ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Shared/CompilationOptionsExtensions.cs b/CodeConverter/Shared/CompilationOptionsExtensions.cs
similarity index 77%
rename from ICSharpCode.CodeConverter/Shared/CompilationOptionsExtensions.cs
rename to CodeConverter/Shared/CompilationOptionsExtensions.cs
index c1df29d2d..cfbd04816 100644
--- a/ICSharpCode.CodeConverter/Shared/CompilationOptionsExtensions.cs
+++ b/CodeConverter/Shared/CompilationOptionsExtensions.cs
@@ -1,9 +1,6 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
-using System.Threading.Tasks;
using ICSharpCode.CodeConverter.CSharp;
-using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
namespace ICSharpCode.CodeConverter.Shared
@@ -17,8 +14,13 @@ public static Document CreateProjectDocumentFromTree(this CompilationOptions opt
{
singleDocumentAssemblyName = singleDocumentAssemblyName ?? "ProjectToBeConverted";
ProjectId projectId = ProjectId.CreateNewId();
+
+ string projFileExtension = parseOptions.Language == LanguageNames.CSharp ? ".csproj" : ".vbproj";
+ var projectFilePath = Path.Combine(Directory.GetCurrentDirectory() + singleDocumentAssemblyName + projFileExtension);
+
var solution = workspace.CurrentSolution.AddProject(projectId, singleDocumentAssemblyName,
- singleDocumentAssemblyName, options.Language);
+ singleDocumentAssemblyName, options.Language)
+ .WithProjectFilePath(projectId, projectFilePath);
var project = solution.GetProject(projectId)
.WithCompilationOptions(options)
diff --git a/ICSharpCode.CodeConverter/Shared/Constants.cs b/CodeConverter/Shared/Constants.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/Constants.cs
rename to CodeConverter/Shared/Constants.cs
diff --git a/ICSharpCode.CodeConverter/Shared/ConversionOptions.cs b/CodeConverter/Shared/ConversionOptions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/ConversionOptions.cs
rename to CodeConverter/Shared/ConversionOptions.cs
diff --git a/ICSharpCode.CodeConverter/Shared/ConversionProgress.cs b/CodeConverter/Shared/ConversionProgress.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/ConversionProgress.cs
rename to CodeConverter/Shared/ConversionProgress.cs
diff --git a/ICSharpCode.CodeConverter/Shared/DefaultReferences.cs b/CodeConverter/Shared/DefaultReferences.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/DefaultReferences.cs
rename to CodeConverter/Shared/DefaultReferences.cs
diff --git a/ICSharpCode.CodeConverter/Shared/DocumentExtensions.cs b/CodeConverter/Shared/DocumentExtensions.cs
similarity index 87%
rename from ICSharpCode.CodeConverter/Shared/DocumentExtensions.cs
rename to CodeConverter/Shared/DocumentExtensions.cs
index a08feb725..3c725a637 100644
--- a/ICSharpCode.CodeConverter/Shared/DocumentExtensions.cs
+++ b/CodeConverter/Shared/DocumentExtensions.cs
@@ -1,23 +1,21 @@
using System;
using System.Collections.Immutable;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.CSharp;
using ICSharpCode.CodeConverter.Util;
using ICSharpCode.CodeConverter.VB;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Simplification;
-using VBasic = Microsoft.CodeAnalysis.VisualBasic;
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
namespace ICSharpCode.CodeConverter.Shared
{
internal static class DocumentExtensions
{
- public static async Task SimplifyStatements(this Document convertedDocument, string unresolvedTypeDiagnosticId)
+ public static async Task SimplifyStatements(this Document convertedDocument, string unresolvedTypeDiagnosticId, CancellationToken cancellationToken)
where TUsingDirectiveSyntax : SyntaxNode where TExpressionSyntax : SyntaxNode
{
Func wouldBeSimplifiedIncorrectly =
@@ -43,7 +41,7 @@ public static async Task SimplifyStatements WithExpandedRootAsync(this Document document)
+ public static async Task WithExpandedRootAsync(this Document document, CancellationToken cancellationToken)
{
if (document.Project.Language == LanguageNames.VisualBasic) {
- document = await ExpandAsync(document, VbNameExpander.Instance);
+ document = await ExpandAsync(document, VbNameExpander.Instance, cancellationToken);
} else {
- document = await ExpandAsync(document, CsExpander.Instance);
+ document = await ExpandAsync(document, CsExpander.Instance, cancellationToken);
}
return document;
}
- private static async Task ExpandAsync(Document document, ISyntaxExpander expander)
+ private static async Task ExpandAsync(Document document, ISyntaxExpander expander, CancellationToken cancellationToken)
{
- var semanticModel = await document.GetSemanticModelAsync();
+ var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
var workspace = document.Project.Solution.Workspace;
- var root = await document.GetSyntaxRootAsync();
+ var root = await document.GetSyntaxRootAsync(cancellationToken);
try {
var newRoot = root.ReplaceNodes(root.DescendantNodes(n => expander.ShouldExpandWithinNode(n, root, semanticModel)).Where(n => expander.ShouldExpandNode(n, root, semanticModel)),
- (node, rewrittenNode) => TryExpandNode(expander, node, root, semanticModel, workspace)
+ (node, rewrittenNode) => TryExpandNode(expander, node, root, semanticModel, workspace, cancellationToken)
);
return document.WithSyntaxRoot(newRoot);
} catch (Exception ex) {
@@ -89,8 +87,9 @@ private static async Task ExpandAsync(Document document, ISyntaxExpand
}
}
- private static SyntaxNode TryExpandNode(ISyntaxExpander expander, SyntaxNode node, SyntaxNode root, SemanticModel semanticModel, Workspace workspace)
+ private static SyntaxNode TryExpandNode(ISyntaxExpander expander, SyntaxNode node, SyntaxNode root, SemanticModel semanticModel, Workspace workspace, CancellationToken cancellationToken)
{
+ cancellationToken.ThrowIfCancellationRequested();
try {
return expander.ExpandNode(node, root, semanticModel, workspace);
} catch (Exception ex) {
@@ -99,14 +98,14 @@ private static SyntaxNode TryExpandNode(ISyntaxExpander expander, SyntaxNode nod
}
}
- private static async Task WithReducedRootAsync(this Document doc, SyntaxNode syntaxRoot = null)
+ private static async Task WithReducedRootAsync(this Document doc, SyntaxNode syntaxRoot, CancellationToken cancellationToken)
{
- var root = syntaxRoot ?? await doc.GetSyntaxRootAsync();
+ var root = syntaxRoot ?? await doc.GetSyntaxRootAsync(cancellationToken);
var withSyntaxRoot = doc.WithSyntaxRoot(root);
try {
- var options = await doc.GetOptionsAsync();
+ var options = await doc.GetOptionsAsync(cancellationToken);
var newOptions = doc.Project.Language == LanguageNames.VisualBasic ? GetVBOptions(options) : GetCSOptions(options);
- return await Simplifier.ReduceAsync(withSyntaxRoot, newOptions);
+ return await Simplifier.ReduceAsync(withSyntaxRoot, newOptions, cancellationToken: cancellationToken);
} catch (Exception ex) {
var warningText = "Conversion warning: Qualified name reduction failed for this file. " + ex;
return doc.WithSyntaxRoot(WithWarningAnnotation(root, warningText));
diff --git a/ICSharpCode.CodeConverter/Shared/Env.cs b/CodeConverter/Shared/Env.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/Env.cs
rename to CodeConverter/Shared/Env.cs
diff --git a/ICSharpCode.CodeConverter/Shared/IProjectContentsConverter.cs b/CodeConverter/Shared/IProjectContentsConverter.cs
similarity index 67%
rename from ICSharpCode.CodeConverter/Shared/IProjectContentsConverter.cs
rename to CodeConverter/Shared/IProjectContentsConverter.cs
index 3fc0889ee..2ce58643d 100644
--- a/ICSharpCode.CodeConverter/Shared/IProjectContentsConverter.cs
+++ b/CodeConverter/Shared/IProjectContentsConverter.cs
@@ -12,7 +12,7 @@ public interface IProjectContentsConverter
Project Project { get; }
Task SingleFirstPass(Document document);
- Task<(Project project, List<(string Path, DocumentId DocId, string[] Errors)> firstPassDocIds)>
- GetConvertedProject((string Path, SyntaxNode Node, string[] Errors)[] firstPassResults);
+ Task<(Project project, List> firstPassDocIds)>
+ GetConvertedProject(WipFileConversion[] firstPassResults);
}
}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Shared/ISyntaxExpander.cs b/CodeConverter/Shared/ISyntaxExpander.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/ISyntaxExpander.cs
rename to CodeConverter/Shared/ISyntaxExpander.cs
diff --git a/ICSharpCode.CodeConverter/Shared/LanguageConversionExtensions.cs b/CodeConverter/Shared/LanguageConversionExtensions.cs
similarity index 97%
rename from ICSharpCode.CodeConverter/Shared/LanguageConversionExtensions.cs
rename to CodeConverter/Shared/LanguageConversionExtensions.cs
index 98e0df825..335f77cf4 100644
--- a/ICSharpCode.CodeConverter/Shared/LanguageConversionExtensions.cs
+++ b/CodeConverter/Shared/LanguageConversionExtensions.cs
@@ -1,5 +1,4 @@
using System.Linq;
-using ICSharpCode.CodeConverter.CSharp;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
diff --git a/ICSharpCode.CodeConverter/Shared/LineTriviaMapper.cs b/CodeConverter/Shared/LineTriviaMapper.cs
similarity index 99%
rename from ICSharpCode.CodeConverter/Shared/LineTriviaMapper.cs
rename to CodeConverter/Shared/LineTriviaMapper.cs
index 333055d4e..1999a7e3c 100644
--- a/ICSharpCode.CodeConverter/Shared/LineTriviaMapper.cs
+++ b/CodeConverter/Shared/LineTriviaMapper.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
diff --git a/ICSharpCode.CodeConverter/Shared/PathConverter.cs b/CodeConverter/Shared/PathConverter.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/PathConverter.cs
rename to CodeConverter/Shared/PathConverter.cs
diff --git a/CodeConverter/Shared/ProjectConversion.cs b/CodeConverter/Shared/ProjectConversion.cs
new file mode 100644
index 000000000..9a6a0f9ff
--- /dev/null
+++ b/CodeConverter/Shared/ProjectConversion.cs
@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using ICSharpCode.CodeConverter.CSharp;
+using ICSharpCode.CodeConverter.Util;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Formatting;
+using Microsoft.CodeAnalysis.Text;
+
+namespace ICSharpCode.CodeConverter.Shared
+{
+ public class ProjectConversion
+ {
+ private readonly IReadOnlyCollection _documentsToConvert;
+ private readonly ILanguageConversion _languageConversion;
+ private readonly bool _showCompilationErrors =
+#if DEBUG && ShowCompilationErrors
+ true;
+#else
+ false;
+#endif
+ private readonly bool _returnSelectedNode;
+ private static readonly string[] BannedPaths = new[] { ".AssemblyAttributes.", "\\bin\\", "\\obj\\" };
+ private readonly IProjectContentsConverter _projectContentsConverter;
+ private readonly CancellationToken _cancellationToken;
+
+ private ProjectConversion(IProjectContentsConverter projectContentsConverter, IEnumerable documentsToConvert,
+ ILanguageConversion languageConversion, CancellationToken cancellationToken, bool returnSelectedNode = false)
+ {
+ _projectContentsConverter = projectContentsConverter;
+ _languageConversion = languageConversion;
+ _documentsToConvert = documentsToConvert.ToList();
+ _returnSelectedNode = returnSelectedNode;
+ _cancellationToken = cancellationToken;
+ }
+
+ public static async Task ConvertText(string text, TextConversionOptions conversionOptions, IProgress progress = null, CancellationToken cancellationToken = default) where TLanguageConversion : ILanguageConversion, new()
+ {
+ progress = progress ?? new Progress();
+ using var roslynEntryPoint = await RoslynEntryPoint(progress);
+
+ var languageConversion = new TLanguageConversion { ConversionOptions = conversionOptions };
+ var syntaxTree = languageConversion.MakeFullCompilationUnit(text, out var textSpan);
+ if (textSpan.HasValue) conversionOptions.SelectedTextSpan = textSpan.Value;
+ using var workspace = new AdhocWorkspace();
+ var document = languageConversion.CreateProjectDocumentFromTree(workspace, syntaxTree, conversionOptions.References);
+ return await ConvertSingle(document, conversionOptions, progress, cancellationToken);
+ }
+
+ public static async Task ConvertSingle(Document document, SingleConversionOptions conversionOptions, IProgress progress = null, CancellationToken cancellationToken = default) where TLanguageConversion : ILanguageConversion, new()
+ {
+ progress = progress ?? new Progress();
+ using var roslynEntryPoint = await RoslynEntryPoint(progress);
+
+ var languageConversion = new TLanguageConversion { ConversionOptions = conversionOptions };
+
+ bool returnSelectedNode = conversionOptions.SelectedTextSpan.Length > 0;
+ if (returnSelectedNode) {
+ document = await WithAnnotatedSelection(document, conversionOptions.SelectedTextSpan);
+ }
+
+ var projectContentsConverter = await languageConversion.CreateProjectContentsConverter(document.Project, progress, cancellationToken);
+
+ document = projectContentsConverter.Project.GetDocument(document.Id);
+
+ var conversion = new ProjectConversion(projectContentsConverter, new[] { document }, languageConversion, cancellationToken, returnSelectedNode);
+ var conversionResults = await conversion.Convert(progress).ToArrayAsync();
+ var codeResult = conversionResults.SingleOrDefault(x => !string.IsNullOrWhiteSpace(x.ConvertedCode))
+ ?? conversionResults.First();
+ codeResult.Exceptions = conversionResults.SelectMany(x => x.Exceptions).ToArray();
+ return codeResult;
+ }
+
+ public static async IAsyncEnumerable ConvertProject(Project project,
+ ILanguageConversion languageConversion, IProgress progress, [EnumeratorCancellation] CancellationToken cancellationToken,
+ params (string Find, string Replace, bool FirstOnly)[] replacements)
+ {
+ progress = progress ?? new Progress();
+ using var roslynEntryPoint = await RoslynEntryPoint(progress);
+
+ var sourceFilePathsWithoutExtension = project.Documents.Select(f => f.FilePath).ToImmutableHashSet();
+ var projectContentsConverter = await languageConversion.CreateProjectContentsConverter(project, progress, cancellationToken);
+ project = projectContentsConverter.Project;
+ var convertProjectContents = ConvertProjectContents(projectContentsConverter, languageConversion, progress, cancellationToken);
+ var results = WithProjectFile(projectContentsConverter, languageConversion, sourceFilePathsWithoutExtension, convertProjectContents, replacements);
+ await foreach (var result in results) yield return result;
+ }
+
+ /// Perf: Keep lazy so that we don't keep all files in memory at once
+ private static async IAsyncEnumerable WithProjectFile(IProjectContentsConverter projectContentsConverter, ILanguageConversion languageConversion, ImmutableHashSet originalSourcePaths, IAsyncEnumerable convertProjectContents, (string Find, string Replace, bool FirstOnly)[] replacements)
+ {
+ var project = projectContentsConverter.Project;
+ var projectDir = project.GetDirectoryPath();
+ var addedTargetFiles = new List();
+
+ await foreach (var conversionResult in convertProjectContents) {
+ yield return conversionResult;
+ if (!originalSourcePaths.Contains(conversionResult.SourcePathOrNull)) {
+ var relativePath = Path.GetFullPath(conversionResult.TargetPathOrNull).Replace(projectDir + Path.DirectorySeparatorChar, "");
+ addedTargetFiles.Add(relativePath);
+ }
+ }
+
+ var replacementSpecs = replacements.Concat(new[] {
+ AddCompiledItemsRegexFromRelativePaths(addedTargetFiles),
+ ChangeRootNamespaceRegex(projectContentsConverter.RootNamespace),
+ ChangeLanguageVersionRegex(projectContentsConverter.LanguageVersion)
+ }).ToArray();
+
+ yield return ConvertProjectFile(project, languageConversion, replacementSpecs);
+ }
+
+ public static ConversionResult ConvertProjectFile(Project project,
+ ILanguageConversion languageConversion,
+ params (string Find, string Replace, bool FirstOnly)[] textReplacements)
+ {
+ return new FileInfo(project.FilePath).ConversionResultFromReplacements(textReplacements,
+ languageConversion.PostTransformProjectFile);
+ }
+
+ private static (string Find, string Replace, bool FirstOnly) ChangeLanguageVersionRegex(string languageVersion) {
+ return (Find: new Regex(@"<\s*LangVersion>(\d|\D)*").ToString(), Replace: $"{languageVersion}", FirstOnly: true);
+ }
+
+ private static (string Find, string Replace, bool FirstOnly) ChangeRootNamespaceRegex(string rootNamespace) {
+ return (Find: new Regex(@"<\s*RootNamespace>(\d|\D)*").ToString(), Replace: $"{rootNamespace}", FirstOnly: true);
+ }
+
+ private static (string Find, string Replace, bool FirstOnly) AddCompiledItemsRegexFromRelativePaths(
+ IEnumerable relativeFilePathsToAdd)
+ {
+ var addFilesRegex = new Regex(@"(\s*<\s*Compile\s*Include\s*=\s*"".*\.(vb|cs)"")");
+ var addedFiles = string.Join("",
+ relativeFilePathsToAdd.OrderBy(x => x).Select(f => $@"{Environment.NewLine} "));
+ var addFilesRegexSpec = (Find: addFilesRegex.ToString(), Replace: addedFiles + @"$1", FirstOnly: true);
+ return addFilesRegexSpec;
+ }
+
+
+ private static async IAsyncEnumerable ConvertProjectContents(
+ IProjectContentsConverter projectContentsConverter, ILanguageConversion languageConversion,
+ IProgress progress, [EnumeratorCancellation] CancellationToken cancellationToken)
+ {
+ var documentsWithLengths = await projectContentsConverter.Project.Documents
+ .Where(d => !BannedPaths.Any(d.FilePath.Contains))
+ .SelectAsync(async d => (Doc: d, Length: (await d.GetTextAsync()).Length));
+
+ //Perf heuristic: Decrease memory pressure on the simplification phase by converting large files first https://github.com/icsharpcode/CodeConverter/issues/524#issuecomment-590301594
+ var documentsToConvert = documentsWithLengths.OrderByDescending(d => d.Length).Select(d => d.Doc);
+
+ var projectConversion = new ProjectConversion(projectContentsConverter, documentsToConvert, languageConversion, cancellationToken);
+
+ var results = projectConversion.Convert(progress);
+ await foreach (var result in results) yield return result;
+ }
+
+
+ private async IAsyncEnumerable Convert(IProgress progress)
+ {
+ var phaseProgress = StartPhase(progress, "Phase 1 of 2:");
+ var firstPassResults = _documentsToConvert.ParallelSelectAwait(d => FirstPass(d, phaseProgress), Env.MaxDop, _cancellationToken);
+ var (proj1, docs1) = await _projectContentsConverter.GetConvertedProject(await firstPassResults.ToArrayAsync());
+
+ var warnings = await GetProjectWarnings(_projectContentsConverter.Project, proj1);
+ if (warnings != null) {
+ var warningPath = Path.Combine(proj1.GetDirectoryPath(), "ConversionWarnings.txt");
+ yield return new ConversionResult() { SourcePathOrNull = warningPath, Exceptions = new[] { warnings } };
+ }
+
+ phaseProgress = StartPhase(progress, "Phase 2 of 2:");
+ var secondPassResults = proj1.GetDocuments(docs1).ParallelSelectAwait(d => SecondPass(d, phaseProgress), Env.MaxDop, _cancellationToken);
+ await foreach (var result in secondPassResults) {
+ yield return new ConversionResult(result.Wip?.ToFullString()) { SourcePathOrNull = result.Path, Exceptions = result.Errors.ToList() };
+ };
+ }
+
+ private static Progress StartPhase(IProgress progress, string phaseTitle)
+ {
+ progress.Report(new ConversionProgress(phaseTitle));
+ var strProgress = new Progress(m => progress.Report(new ConversionProgress(m, 1)));
+ return strProgress;
+ }
+
+ private async Task> SecondPass(WipFileConversion firstPassResult, IProgress progress)
+ {
+ if (firstPassResult.Wip != null) {
+ LogProgress(firstPassResult, "Simplifying", progress);
+ var (convertedNode, errors) = await SingleSecondPassHandled(firstPassResult.Wip);
+ return (firstPassResult.Path, convertedNode, firstPassResult.Errors.Concat(errors).Union(GetErrorsFromAnnotations(convertedNode)).ToArray());
+ }
+
+ return (firstPassResult.Path, null, firstPassResult.Errors);
+ }
+
+ private async Task<(SyntaxNode convertedDoc, string[] errors)> SingleSecondPassHandled(Document convertedDocument)
+ {
+ SyntaxNode selectedNode = null;
+ string[] errors = Array.Empty();
+ try {
+ Document document = await _languageConversion.SingleSecondPass(convertedDocument);
+ if (_returnSelectedNode) {
+ selectedNode = await GetSelectedNode(document);
+ var extraLeadingTrivia = selectedNode.GetFirstToken().GetPreviousToken().TrailingTrivia;
+ var extraTrailingTrivia = selectedNode.GetLastToken().GetNextToken().LeadingTrivia;
+ selectedNode = Formatter.Format(selectedNode, document.Project.Solution.Workspace);
+ if (extraLeadingTrivia.Any(t => !t.IsWhitespaceOrEndOfLine())) selectedNode = selectedNode.WithPrependedLeadingTrivia(extraLeadingTrivia);
+ if (extraTrailingTrivia.Any(t => !t.IsWhitespaceOrEndOfLine())) selectedNode = selectedNode.WithAppendedTrailingTrivia(extraTrailingTrivia);
+ } else {
+ selectedNode = await document.GetSyntaxRootAsync();
+ selectedNode = Formatter.Format(selectedNode, document.Project.Solution.Workspace);
+ var convertedDoc = document.WithSyntaxRoot(selectedNode);
+ selectedNode = await convertedDoc.GetSyntaxRootAsync();
+ }
+ } catch (Exception e) {
+ errors = new[] { e.ToString() };
+ }
+
+ var convertedNode = selectedNode ?? await convertedDocument.GetSyntaxRootAsync();
+ return (convertedNode, errors);
+ }
+
+ private async Task GetProjectWarnings(Project source, Project converted)
+ {
+ if (!_showCompilationErrors) return null;
+
+ var sourceCompilation = await source.GetCompilationAsync();
+ var convertedCompilation = await converted.GetCompilationAsync();
+ return CompilationWarnings.WarningsForCompilation(sourceCompilation, "source") + CompilationWarnings.WarningsForCompilation(convertedCompilation, "target");
+ }
+
+ private async Task> FirstPass(Document document, IProgress progress)
+ {
+ var treeFilePath = document.FilePath ?? "";
+ progress.Report(treeFilePath);
+ try {
+ var convertedNode = await _projectContentsConverter.SingleFirstPass(document);
+ string[] errors = GetErrorsFromAnnotations(convertedNode);
+
+ return (treeFilePath, convertedNode, errors);
+ } catch (Exception e) {
+ return (treeFilePath, null, new[] { e.ToString() });
+ }
+ }
+
+ private static string[] GetErrorsFromAnnotations(SyntaxNode convertedNode)
+ {
+ var errorAnnotations = convertedNode.GetAnnotations(AnnotationConstants.ConversionErrorAnnotationKind).ToList();
+ string[] errors = errorAnnotations.Select(a => a.Data).ToArray();
+ return errors;
+ }
+
+ private static async Task WithAnnotatedSelection(Document document, TextSpan selected)
+ {
+ var root = await document.GetSyntaxRootAsync();
+ var selectedNode = root.FindNode(selected);
+ var withAnnotatedSelection = await root.WithAnnotatedNode(selectedNode, AnnotationConstants.SelectedNodeAnnotationKind).GetRootAsync();
+ return document.WithSyntaxRoot(withAnnotatedSelection);
+ }
+
+ private async Task GetSelectedNode(Document document)
+ {
+ var resultNode = await document.GetSyntaxRootAsync();
+ var selectedNode = resultNode.GetAnnotatedNodes(AnnotationConstants.SelectedNodeAnnotationKind)
+ .FirstOrDefault();
+ if (selectedNode != null) {
+ var children = _languageConversion.FindSingleImportantChild(selectedNode);
+ if (selectedNode.GetAnnotations(AnnotationConstants.SelectedNodeAnnotationKind)
+ .Any(n => n.Data == AnnotationConstants.AnnotatedNodeIsParentData)
+ && children.Count == 1) {
+ selectedNode = children.Single();
+ }
+ }
+
+ return selectedNode ?? resultNode;
+ }
+
+ private void LogProgress(WipFileConversion convertedFile, string action, IProgress progress)
+ {
+ var indentedException = string.Join(Environment.NewLine, convertedFile.Errors)
+ .Replace(Environment.NewLine, Environment.NewLine + " ").TrimEnd();
+ var relativePath = PathRelativeToSolutionDir(convertedFile.Path ?? "unknown");
+
+ var containsErrors = !string.IsNullOrWhiteSpace(indentedException);
+ string output;
+ if (convertedFile.Wip == null) {
+ output = $"Failed {action.ToLower()} {relativePath}:{Environment.NewLine} {indentedException}";
+ } else if (containsErrors) {
+ output = $"Error {action.ToLower()} {relativePath}:{Environment.NewLine} {indentedException}";
+ } else {
+ output = $"{action} {relativePath}";
+ }
+
+ progress.Report(output);
+ }
+
+ private string PathRelativeToSolutionDir(string path)
+ {
+ return path.Replace(this._projectContentsConverter.Project.Solution.GetDirectoryPath() + Path.DirectorySeparatorChar, "");
+ }
+
+ private static async Task RoslynEntryPoint(IProgress progress)
+ {
+ await new SynchronizationContextRemover();
+ return RoslynCrashPreventer.Create(LogError);
+
+ void LogError(object e) => progress.Report(new ConversionProgress($"https://github.com/dotnet/roslyn threw an exception: {e}"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Shared/ProjectTypeGuids.cs b/CodeConverter/Shared/ProjectTypeGuids.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/ProjectTypeGuids.cs
rename to CodeConverter/Shared/ProjectTypeGuids.cs
diff --git a/CodeConverter/Shared/RoslynCrashPreventer.cs b/CodeConverter/Shared/RoslynCrashPreventer.cs
new file mode 100644
index 000000000..cb29edc25
--- /dev/null
+++ b/CodeConverter/Shared/RoslynCrashPreventer.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Reflection;
+using Microsoft.CodeAnalysis;
+
+namespace ICSharpCode.CodeConverter.Shared
+{
+ internal static class RoslynCrashPreventer
+ {
+ private static object _exchangeLock = new object();
+
+ ///
+ /// Use this to stop the library exiting the process without telling us.
+ /// https://github.com/dotnet/roslyn/issues/41724
+ ///
+ ///
+ /// The simplification code in particular is quite buggy, scattered with "throw ExceptionUtilities.Unreachable" with no particular reasoning for why the code wouldn't be reachable.
+ /// It then uses FatalError.ReportUnlessCanceled rather than FatalError.ReportWithoutCrashUnlessCanceled causing fatal crashes with Environment.FailFast
+ /// While this presumably allows them to get good low-level debugging info from the windows error reports caused, it just means that people come to this project complaining about VS crashes.
+ /// See https://github.com/icsharpcode/CodeConverter/issues/521 and https://github.com/icsharpcode/CodeConverter/issues/484
+ /// There are other ways to find these bugs - just run the expander/reducer on a couple of whole open source projects and the bugs will pile up.
+ ///
+ public static IDisposable Create(Action logError)
+ {
+ var FirstHandlerContainingType = (typeof(Compilation).Assembly, "Microsoft.CodeAnalysis.FatalError");
+ var SecondHandlerContainingType = (typeof(WorkspaceDiagnostic).Assembly, "Microsoft.CodeAnalysis.ErrorReporting.FatalError");
+
+ var codeAnalysisErrorHandler = ExchangeFatalErrorHandler(logError, FirstHandlerContainingType);
+ var codeAnalysisErrorReportingErrorHandler = ExchangeFatalErrorHandler(logError, SecondHandlerContainingType);
+ return new ActionDisposable(() => {
+ ExchangeFatalErrorHandler(codeAnalysisErrorHandler, FirstHandlerContainingType);
+ ExchangeFatalErrorHandler(codeAnalysisErrorReportingErrorHandler, SecondHandlerContainingType);
+ });
+ }
+
+ private static Action ExchangeFatalErrorHandler(Action errorHandler, (Assembly assembly, string containingType) container, Action errorHanderToReplace = null)
+ {
+ if (errorHandler == null) return null;
+ try {
+ var fataErrorType = container.assembly.GetType(container.containingType);
+ var fatalHandlerField = fataErrorType.GetField("s_fatalHandler", BindingFlags.NonPublic | BindingFlags.Static);
+ lock (_exchangeLock) {
+ var originalHandler = (Action)fatalHandlerField.GetValue(null);
+ if (originalHandler != null && errorHanderToReplace == null || originalHandler == errorHanderToReplace) {
+ fatalHandlerField.SetValue(null, errorHandler);
+ }
+ return originalHandler;
+ }
+ } catch (Exception) {
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Shared/SharedSemanticModelExtensions.cs b/CodeConverter/Shared/SharedSemanticModelExtensions.cs
similarity index 93%
rename from ICSharpCode.CodeConverter/Shared/SharedSemanticModelExtensions.cs
rename to CodeConverter/Shared/SharedSemanticModelExtensions.cs
index 23e154b8f..440ae8df4 100644
--- a/ICSharpCode.CodeConverter/Shared/SharedSemanticModelExtensions.cs
+++ b/CodeConverter/Shared/SharedSemanticModelExtensions.cs
@@ -1,5 +1,4 @@
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
namespace ICSharpCode.CodeConverter.Shared
{
diff --git a/ICSharpCode.CodeConverter/Shared/SingleConversionOptions.cs b/CodeConverter/Shared/SingleConversionOptions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/SingleConversionOptions.cs
rename to CodeConverter/Shared/SingleConversionOptions.cs
diff --git a/ICSharpCode.CodeConverter/Shared/SolutionConverter.cs b/CodeConverter/Shared/SolutionConverter.cs
similarity index 84%
rename from ICSharpCode.CodeConverter/Shared/SolutionConverter.cs
rename to CodeConverter/Shared/SolutionConverter.cs
index c3fa6faa7..6eef745c6 100644
--- a/ICSharpCode.CodeConverter/Shared/SolutionConverter.cs
+++ b/CodeConverter/Shared/SolutionConverter.cs
@@ -3,8 +3,8 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using ICSharpCode.CodeConverter.CSharp;
+using System.Threading;
+using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
namespace ICSharpCode.CodeConverter.Shared
@@ -17,22 +17,24 @@ public class SolutionConverter
private readonly List<(string Find, string Replace, bool FirstOnly)> _projectReferenceReplacements;
private readonly IProgress _progress;
private readonly ILanguageConversion _languageConversion;
+ private readonly CancellationToken _cancellationToken;
public static SolutionConverter CreateFor(IReadOnlyCollection projectsToConvert,
ConversionOptions conversionOptions = default,
- IProgress progress = null) where TLanguageConversion : ILanguageConversion, new()
+ IProgress progress = null,
+ CancellationToken cancellationToken = default) where TLanguageConversion : ILanguageConversion, new()
{
var conversion = new TLanguageConversion {ConversionOptions = conversionOptions ?? new ConversionOptions() };
var solutionFilePath = projectsToConvert.First().Solution.FilePath;
var sourceSolutionContents = File.ReadAllText(solutionFilePath);
var projectReferenceReplacements = GetProjectReferenceReplacements(projectsToConvert, sourceSolutionContents);
- return new SolutionConverter(solutionFilePath, sourceSolutionContents, projectsToConvert, projectReferenceReplacements, progress ?? new Progress(), conversion);
+ return new SolutionConverter(solutionFilePath, sourceSolutionContents, projectsToConvert, projectReferenceReplacements, progress ?? new Progress(), cancellationToken, conversion);
}
private SolutionConverter(string solutionFilePath,
string sourceSolutionContents, IReadOnlyCollection projectsToConvert,
List<(string Find, string Replace, bool FirstOnly)> projectReferenceReplacements, IProgress showProgressMessage,
- ILanguageConversion languageConversion)
+ CancellationToken cancellationToken, ILanguageConversion languageConversion)
{
_solutionFilePath = solutionFilePath;
_sourceSolutionContents = sourceSolutionContents;
@@ -40,29 +42,28 @@ private SolutionConverter(string solutionFilePath,
_projectReferenceReplacements = projectReferenceReplacements;
_progress = showProgressMessage;
_languageConversion = languageConversion;
+ _cancellationToken = cancellationToken;
}
- public async Task> Convert()
+ public IAsyncEnumerable Convert()
{
var projectsToUpdateReferencesOnly = _projectsToConvert.First().Solution.Projects.Except(_projectsToConvert);
- var projectContents = await ConvertProjects();
- return projectContents.SelectMany(x => x)
- .Concat(UpdateProjectReferences(projectsToUpdateReferencesOnly))
- .Concat(new[] { ConvertSolutionFile() });
+ return ConvertProjects()
+ .Concat(UpdateProjectReferences(projectsToUpdateReferencesOnly).Concat(ConvertSolutionFile().Yield()).ToAsyncEnumerable());
}
- private Task[]> ConvertProjects()
+ private IAsyncEnumerable ConvertProjects()
{
var projectFileReplacementRegexes = _languageConversion.GetProjectFileReplacementRegexes().Concat(_languageConversion.GetProjectTypeGuidMappings())
.Select(m => (m.Item1, m.Item2, false));
- return _projectsToConvert.SelectAsync(project => ConvertProject(projectFileReplacementRegexes, project));
+ return _projectsToConvert.ToAsyncEnumerable().SelectMany(project => ConvertProject(projectFileReplacementRegexes, project));
}
- private async Task> ConvertProject(IEnumerable<(string Find, string Replace, bool FirstOnly)> projectFileReplacementRegexes, Project project)
+ private IAsyncEnumerable ConvertProject(IEnumerable<(string Find, string Replace, bool FirstOnly)> projectFileReplacementRegexes, Project project)
{
var replacements = _projectReferenceReplacements.Concat(projectFileReplacementRegexes).ToArray();
_progress.Report(new ConversionProgress($"Converting {project.Name}..."));
- return await ProjectConversion.ConvertProject(project, _languageConversion, _progress, replacements);
+ return ProjectConversion.ConvertProject(project, _languageConversion, _progress, _cancellationToken, replacements);
}
private IEnumerable UpdateProjectReferences(IEnumerable projectsToUpdateReferencesOnly)
diff --git a/ICSharpCode.CodeConverter/Shared/SynchronizationContextRemover.cs b/CodeConverter/Shared/SynchronizationContextRemover.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/SynchronizationContextRemover.cs
rename to CodeConverter/Shared/SynchronizationContextRemover.cs
diff --git a/ICSharpCode.CodeConverter/Shared/TextConversionOptions.cs b/CodeConverter/Shared/TextConversionOptions.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/TextConversionOptions.cs
rename to CodeConverter/Shared/TextConversionOptions.cs
diff --git a/ICSharpCode.CodeConverter/Shared/TextLineExtensions.cs b/CodeConverter/Shared/TextLineExtensions.cs
similarity index 96%
rename from ICSharpCode.CodeConverter/Shared/TextLineExtensions.cs
rename to CodeConverter/Shared/TextLineExtensions.cs
index 98691a240..397e8baa3 100644
--- a/ICSharpCode.CodeConverter/Shared/TextLineExtensions.cs
+++ b/CodeConverter/Shared/TextLineExtensions.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.Linq;
using ICSharpCode.CodeConverter.Util;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
diff --git a/ICSharpCode.CodeConverter/Shared/TextReplacementConverter.cs b/CodeConverter/Shared/TextReplacementConverter.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/TextReplacementConverter.cs
rename to CodeConverter/Shared/TextReplacementConverter.cs
diff --git a/ICSharpCode.CodeConverter/Shared/TokenContext.cs b/CodeConverter/Shared/TokenContext.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Shared/TokenContext.cs
rename to CodeConverter/Shared/TokenContext.cs
diff --git a/ICSharpCode.CodeConverter/Shared/TriviaMapping.cs b/CodeConverter/Shared/TriviaMapping.cs
similarity index 93%
rename from ICSharpCode.CodeConverter/Shared/TriviaMapping.cs
rename to CodeConverter/Shared/TriviaMapping.cs
index 8d0901e55..06eb21dc9 100644
--- a/ICSharpCode.CodeConverter/Shared/TriviaMapping.cs
+++ b/CodeConverter/Shared/TriviaMapping.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using ICSharpCode.CodeConverter.Util;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Text;
+using Microsoft.CodeAnalysis;
namespace ICSharpCode.CodeConverter.Shared
{
diff --git a/CodeConverter/Shared/WipConversion.cs b/CodeConverter/Shared/WipConversion.cs
new file mode 100644
index 000000000..cce57fb9c
--- /dev/null
+++ b/CodeConverter/Shared/WipConversion.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+
+namespace ICSharpCode.CodeConverter.Shared
+{
+ internal struct WipFileConversion
+ {
+ public static WipFileConversion Create(string path, TWip wip, string[] errors)
+ {
+ return new WipFileConversion(path, wip, errors);
+ }
+ }
+
+ public struct WipFileConversion
+ {
+ public string Path;
+ public TWip Wip;
+ public string[] Errors;
+
+ internal WipFileConversion(string path, TWip wip, string[] errors)
+ {
+ Path = path;
+ Wip = wip;
+ Errors = errors;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is WipFileConversion other &&
+ Path == other.Path &&
+ EqualityComparer.Default.Equals(Wip, other.Wip) &&
+ EqualityComparer.Default.Equals(Errors, other.Errors);
+ }
+
+ public override int GetHashCode()
+ {
+ return Path.GetHashCode();
+ }
+
+ public void Deconstruct(out string path, out TWip node, out string[] errors)
+ {
+ path = Path;
+ node = Wip;
+ errors = Errors;
+ }
+
+ public static implicit operator (string Path, TWip Node, string[] Errors)(WipFileConversion value)
+ {
+ return (value.Path, value.Wip, value.Errors);
+ }
+
+ public static implicit operator WipFileConversion((string Path, TWip Wip, string[] Errors) value)
+ {
+ return new WipFileConversion(value.Path, value.Wip, value.Errors);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ICSharpCode.CodeConverter/Util/CSharpCompiler.cs b/CodeConverter/Util/CSharpCompiler.cs
similarity index 97%
rename from ICSharpCode.CodeConverter/Util/CSharpCompiler.cs
rename to CodeConverter/Util/CSharpCompiler.cs
index df2875744..c1c39caa1 100644
--- a/ICSharpCode.CodeConverter/Util/CSharpCompiler.cs
+++ b/CodeConverter/Util/CSharpCompiler.cs
@@ -4,7 +4,6 @@
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
namespace ICSharpCode.CodeConverter.Util
{
diff --git a/ICSharpCode.CodeConverter/Util/CSharpUtil.cs b/CodeConverter/Util/CSharpUtil.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Util/CSharpUtil.cs
rename to CodeConverter/Util/CSharpUtil.cs
diff --git a/ICSharpCode.CodeConverter/Util/CompilationWarnings.cs b/CodeConverter/Util/CompilationWarnings.cs
similarity index 100%
rename from ICSharpCode.CodeConverter/Util/CompilationWarnings.cs
rename to CodeConverter/Util/CompilationWarnings.cs
diff --git a/CodeConverter/Util/EnumerableExtensions.cs b/CodeConverter/Util/EnumerableExtensions.cs
new file mode 100644
index 000000000..52a0ec43a
--- /dev/null
+++ b/CodeConverter/Util/EnumerableExtensions.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace ICSharpCode.CodeConverter.Util
+{
+#if NR6
+ public
+#endif
+ internal static partial class EnumerableExtensions
+ {
+ public static IEnumerable Do(this IEnumerable source, Action action)
+ {
+ if (source == null) {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ if (action == null) {
+ throw new ArgumentNullException(nameof(action));
+ }
+
+ // perf optimization. try to not use enumerator if possible
+ var list = source as IList;
+ if (list != null) {
+ for (int i = 0, count = list.Count; i < count; i++) {
+ action(list[i]);
+ }
+ } else {
+ foreach (var value in source) {
+ action(value);
+ }
+ }
+
+ return source;
+ }
+
+ public static IReadOnlyCollection ToReadOnlyCollection(this IEnumerable source)
+ {
+ if (source == null) {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ return new ReadOnlyCollection(source.ToList());
+ }
+
+ public static IEnumerable Concat(this IEnumerable source, T value)
+ {
+ if (source == null) {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ return source.ConcatWorker(value);
+ }
+
+ private static IEnumerable ConcatWorker(this IEnumerable source, T value)
+ {
+ foreach (var v in source) {
+ yield return v;
+ }
+
+ yield return value;
+ }
+
+ public static bool IsEmpty(this IEnumerable source)
+ {
+ var readOnlyCollection = source as IReadOnlyCollection;
+ if (readOnlyCollection != null) {
+ return readOnlyCollection.Count == 0;
+ }
+
+ var genericCollection = source as ICollection;
+ if (genericCollection != null) {
+ return genericCollection.Count == 0;
+ }
+
+ var collection = source as ICollection;
+ if (collection != null) {
+ return collection.Count == 0;
+ }
+
+ var str = source as string;
+ if (str != null) {
+ return str.Length == 0;
+ }
+
+ foreach (var t in source) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool IsEmpty(this IReadOnlyCollection source)
+ {
+ return source.Count == 0;
+ }
+
+ private static readonly Func