diff --git a/CodeConverter/CodeConverter.csproj b/CodeConverter/CodeConverter.csproj index 80642c84b..415d399dc 100644 --- a/CodeConverter/CodeConverter.csproj +++ b/CodeConverter/CodeConverter.csproj @@ -38,6 +38,7 @@ + diff --git a/ResetRoslynInstance.bat b/ResetRoslynInstance.bat new file mode 100644 index 000000000..bdf4a1faa --- /dev/null +++ b/ResetRoslynInstance.bat @@ -0,0 +1 @@ +%comspec% /C "C:\Program Files\Microsoft Visual Studio\2022\Preview\VSSDK\VisualStudioIntegration\Tools\Bin\CreateExpInstance.exe" /Reset /VSInstance=17.0_56947084 /RootSuffix=Roslyn && PAUSE \ No newline at end of file diff --git a/Tests/CSharp/SelfVerifyingTests.cs b/Tests/CSharp/SelfVerifyingTests.cs index 6e182f563..edcf2458b 100644 --- a/Tests/CSharp/SelfVerifyingTests.cs +++ b/Tests/CSharp/SelfVerifyingTests.cs @@ -15,7 +15,7 @@ namespace ICSharpCode.CodeConverter.Tests.CSharp; /// public class SelfVerifyingTests { - [Theory, MemberData(nameof(GetVisualBasicToCSharpTestData))] + //[Theory, MemberData(nameof(GetVisualBasicToCSharpTestData))] public async Task VisualBasicToCSharpAsync(NamedTest verifyConvertedTestPasses) { await verifyConvertedTestPasses.Execute(); diff --git a/Tests/CSharp/SpikeTests.cs b/Tests/CSharp/SpikeTests.cs new file mode 100644 index 000000000..16ce1510f --- /dev/null +++ b/Tests/CSharp/SpikeTests.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Immutable; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis; +using Xunit; + + +namespace ICSharpCode.CodeConverter.Tests.CSharp; + +public class SpikeTests +{ + + [Fact] + public async Task ConvertRazorFileAsync() + { + var codeDocument = GetCodeDocument(""" + @Code + ViewData("Title") = "About" & CStr(1) + End Code + +
+

@ViewData("Title").

@ViewData("Title2").

+

@ViewData("Message")

+ +

Use this area to provide additional information.

+
@Code + ViewData("Title") = "About" & CStr(1) + End Code + +
+

@ViewData("Title").

@ViewData("Title2").

+

@ViewData("Message")

+ +

Use this area to provide additional information.

+
+ + """, "anything.vbhtml"); + + var syntaxTree = codeDocument.GetSyntaxTree(); + var getRoot = syntaxTree.GetType().GetProperty("Root", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod; + var root = getRoot.Invoke(syntaxTree, BindingFlags.Instance | BindingFlags.NonPublic, null, null, null); + var getDocument = root.GetType().GetProperty("Document", BindingFlags.Instance | BindingFlags.Public).GetMethod; + var document = getDocument.Invoke(root, BindingFlags.Instance | BindingFlags.NonPublic, null, null, null); + var getChildren = document.GetType().GetProperty("Children", BindingFlags.Instance | BindingFlags.Public).GetMethod; + var children = getChildren.Invoke(document, BindingFlags.Instance | BindingFlags.NonPublic, null, null, null); + + + } + + [UnsafeAccessor(UnsafeAccessorKind.Method)] + private static extern object get_Root(RazorSyntaxTree codeDocument); + + + private RazorCodeDocument GetCodeDocument(string source, string filePath) + { + var taghelper = TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly") + //.BoundAttributeDescriptor(attr => attr.Name("show").TypeName("System.Boolean")) + //.BoundAttributeDescriptor(attr => attr.Name("id").TypeName("System.Int32")) + //.TagMatchingRuleDescriptor(rule => rule.RequireTagName("taghelper")) + //.Metadata(TypeName("TestTagHelper")) + .Build(); + + var engine = CreateProjectEngine(_ => { + //return builder.Features.Add(new VisualStudioEnableTagHelpersFeature()); + } + ); + + var sourceDocument = TestRazorSourceDocument.Create(source, normalizeNewLines: true); + var importDocument = TestRazorSourceDocument.Create("@addTagHelper *, TestAssembly", filePath: filePath, relativePath: filePath); + + var codeDocument = engine.ProcessDesignTime(sourceDocument, FileKinds.Legacy, importSources: ImmutableArray.Create(importDocument), new[] { taghelper }); + return codeDocument; + //return RazorWrapperFactory.WrapCodeDocument(codeDocument); + } + protected RazorProjectEngine CreateProjectEngine(Action configure) + { + return RazorProjectEngine.Create(RazorConfiguration.Default, RazorProjectFileSystem.Create("c:\\tmp"), configure); + } +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable disable + + +public static class TestRazorSourceDocument +{ + + public static MemoryStream CreateStreamContent(string content = "Hello, World!", Encoding encoding = null, bool normalizeNewLines = false) + { + var stream = new MemoryStream(); + encoding ??= Encoding.UTF8; + using (var writer = new StreamWriter(stream, encoding, bufferSize: 1024, leaveOpen: true)) { + if (normalizeNewLines) { + content = NormalizeNewLines(content); + } + + writer.Write(content); + } + + stream.Seek(0L, SeekOrigin.Begin); + + return stream; + } + + public static RazorSourceDocument Create( + string content = "Hello, world!", + Encoding encoding = null, + bool normalizeNewLines = false, + string filePath = "test.cshtml", + string relativePath = "test.cshtml") + { + if (normalizeNewLines) { + content = NormalizeNewLines(content); + } + + var properties = new RazorSourceDocumentProperties(filePath, relativePath); + return RazorSourceDocument.Create(content, encoding ?? Encoding.UTF8, properties); + } + + public static RazorSourceDocument Create( + string content, + RazorSourceDocumentProperties properties, + Encoding encoding = null, + bool normalizeNewLines = false) + { + if (normalizeNewLines) { + content = NormalizeNewLines(content); + } + + return RazorSourceDocument.Create(content, encoding ?? Encoding.UTF8, properties); + } + + private static string NormalizeNewLines(string content) + { + return Regex.Replace(content, "(? GetTestFileContents() private static string GetTestSourceDirectoryPath() { - string assemblyDir = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath); + string assemblyDir = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().Location).AbsolutePath); string testSourceDirectoryPath = Path.Combine(assemblyDir, @"..\..\"); return testSourceDirectoryPath; } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 01aef701e..2628cf2ec 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,12 +1,13 @@  - net472 + net8.0 Library ICSharpCode.CodeConverter.Tests ICSharpCode.CodeConverter.Tests true true true + latest diff --git a/Tests/VB/SelfVerifyingTests.cs b/Tests/VB/SelfVerifyingTests.cs index a8dd93ad9..e9bed486e 100644 --- a/Tests/VB/SelfVerifyingTests.cs +++ b/Tests/VB/SelfVerifyingTests.cs @@ -15,7 +15,7 @@ namespace ICSharpCode.CodeConverter.Tests.VB; /// public class SelfVerifyingTests { - [Theory, MemberData(nameof(GetCSharpToVisualBasicTestData))] + //[Theory, MemberData(nameof(GetCSharpToVisualBasicTestData))] public async Task VisualBasicToCSharpAsync(NamedTest verifyConvertedTestPasses) { await verifyConvertedTestPasses.Execute(); diff --git a/Tests/VB/StandaloneStatementTests.cs b/Tests/VB/StandaloneStatementTests.cs index 9baf185c6..76064a776 100644 --- a/Tests/VB/StandaloneStatementTests.cs +++ b/Tests/VB/StandaloneStatementTests.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using System.Windows.Forms; using ICSharpCode.CodeConverter.Tests.TestRunners; using Xunit; diff --git a/Vsix/CodeConversion.cs b/Vsix/CodeConversion.cs index b7ac11d7d..80af66860 100644 --- a/Vsix/CodeConversion.cs +++ b/Vsix/CodeConversion.cs @@ -308,7 +308,8 @@ private async IAsyncEnumerable ConvertProjectUnhandledAsync p.FilePath, p => p); #pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread - ToList ensures this happens within the same thread just switched to above - var projects = selectedProjects.Select(p => projectsByPath[p.FullName].First()).ToList(); + var projects = selectedProjects.SelectMany(p => projectsByPath[p.FullName]).ToList(); + #pragma warning restore VSTHRD010 // Invoke single-threaded types on Main thread await TaskScheduler.Default;