diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d5e45cc903032..92ccd213d591e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -45,4 +45,5 @@ src/Features/**/PublicAPI.Unshipped.txt @dotnet/roslyn-api-owners src/EditorFeatures/**/PublicAPI.Unshipped.txt @dotnet/roslyn-api-owners src/Tools/ExternalAccess/OmniSharp*/ @333fred @dibarbet +src/Tools/ExternalAccess/RazorCompiler*/ @dotnet/roslyn-compiler src/Tools/ExternalAccess/CompilerDeveloperSDK/ @333fred diff --git a/Compilers.slnf b/Compilers.slnf index c810adbc006d7..e73b1562e7b0b 100644 --- a/Compilers.slnf +++ b/Compilers.slnf @@ -67,6 +67,8 @@ "src\\Tools\\BuildBoss\\BuildBoss.csproj", "src\\Tools\\Replay\\Replay.csproj", "src\\Tools\\BuildValidator\\BuildValidator.csproj", + "src\\Tools\\ExternalAccess\\RazorCompilerTest\\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj", + "src\\Tools\\ExternalAccess\\RazorCompiler\\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.csproj", "src\\Tools\\PrepareTests\\PrepareTests.csproj", "src\\Tools\\Source\\CompilerGeneratorTools\\Source\\BoundTreeGenerator\\CompilersBoundTreeGenerator.csproj", "src\\Tools\\Source\\CompilerGeneratorTools\\Source\\CSharpErrorFactsGenerator\\CSharpErrorFactsGenerator.csproj", diff --git a/Roslyn.sln b/Roslyn.sln index b682dc262a06b..9a79c163e46ca 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -504,6 +504,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestDiscoveryWorker", "src\Tools\TestDiscoveryWorker\TestDiscoveryWorker.csproj", "{8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler", "src\Tools\ExternalAccess\RazorCompiler\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.csproj", "{E5E0BF73-95F7-4BC3-8443-2336C4FF4297}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests", "src\Tools\ExternalAccess\RazorCompilerTest\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj", "{828FD0DB-9927-42AC-B6C2-D1514965D6C3}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj", "{2A3C94F7-5B5E-4CDC-B645-672815E61DEB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.LanguageServer.UnitTests", "src\Features\LanguageServer\Microsoft.CodeAnalysis.LanguageServer.UnitTests\Microsoft.CodeAnalysis.LanguageServer.UnitTests.csproj", "{9A90AA02-4275-40ED-B1F1-731AF17E675C}" @@ -1282,6 +1286,14 @@ Global {8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F}.Debug|Any CPU.Build.0 = Debug|Any CPU {8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F}.Release|Any CPU.ActiveCfg = Release|Any CPU {8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F}.Release|Any CPU.Build.0 = Release|Any CPU + {E5E0BF73-95F7-4BC3-8443-2336C4FF4297}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5E0BF73-95F7-4BC3-8443-2336C4FF4297}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5E0BF73-95F7-4BC3-8443-2336C4FF4297}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5E0BF73-95F7-4BC3-8443-2336C4FF4297}.Release|Any CPU.Build.0 = Release|Any CPU + {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {828FD0DB-9927-42AC-B6C2-D1514965D6C3}.Release|Any CPU.Build.0 = Release|Any CPU {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A3C94F7-5B5E-4CDC-B645-672815E61DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1600,6 +1612,8 @@ Global {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8} = {D449D505-CC6A-4E0B-AF1B-976E2D0AE67A} {8A29449D-411E-49E4-B99E-E8428076BB21} = {55A62CFA-1155-46F1-ADF3-BEEE51B58AB5} {8BC50AFF-1EBF-4E9A-AEBB-04F387AA800F} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC} + {E5E0BF73-95F7-4BC3-8443-2336C4FF4297} = {8977A560-45C2-4EC2-A849-97335B382C74} + {828FD0DB-9927-42AC-B6C2-D1514965D6C3} = {8977A560-45C2-4EC2-A849-97335B382C74} {2A3C94F7-5B5E-4CDC-B645-672815E61DEB} = {D449D505-CC6A-4E0B-AF1B-976E2D0AE67A} {9A90AA02-4275-40ED-B1F1-731AF17E675C} = {D449D505-CC6A-4E0B-AF1B-976E2D0AE67A} {521ADC3E-CC15-414B-9356-D87C5BCF3A24} = {C52D8057-43AF-40E6-A01B-6CDBB7301985} diff --git a/src/Compilers/CSharp/csc/CscCommandLine.projitems b/src/Compilers/CSharp/csc/CscCommandLine.projitems index eb07fde346dce..b25a580868321 100644 --- a/src/Compilers/CSharp/csc/CscCommandLine.projitems +++ b/src/Compilers/CSharp/csc/CscCommandLine.projitems @@ -36,6 +36,7 @@ + diff --git a/src/Compilers/Core/CodeAnalysisTest/AnalyzerAssemblyLoaderTests.cs b/src/Compilers/Core/CodeAnalysisTest/AnalyzerAssemblyLoaderTests.cs index 5c47171fb8a6f..949110ac56a74 100644 --- a/src/Compilers/Core/CodeAnalysisTest/AnalyzerAssemblyLoaderTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/AnalyzerAssemblyLoaderTests.cs @@ -519,6 +519,80 @@ public void AssemblyLoading_DependencyInDifferentDirectory(AnalyzerTestKind kind }); } +#if NET472 + /// + /// Verify that MS.CA.EA.RazorCompiler will be loaded from the compiler directory not the + /// analyzer directory. + /// + [Theory] + [CombinatorialData] + public void AssemblyLoading_RazorCompiler1(AnalyzerTestKind kind) + { + Run(kind, static (AnalyzerAssemblyLoader loader, AssemblyLoadTestFixture testFixture) => + { + using var temp = new TempRoot(); + var tempDir = temp.CreateDirectory(); + + var externalAccessRazorPath = typeof(Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.GeneratorExtensions).Assembly.Location; + var alternatePath = tempDir.CreateDirectory("a").CreateFile("Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.dll").CopyContentFrom(externalAccessRazorPath).Path; + + loader.AddDependencyLocation(alternatePath); + Assembly assembly = loader.LoadFromPath(alternatePath); + + Assert.Equal(externalAccessRazorPath, assembly.Location); + + // Even though EA.RazorCompiler is loaded from the compiler directory the shadow copy loader + // still does a defensive copy. + var copyCount = loader is ShadowCopyAnalyzerAssemblyLoader + ? 1 + : (int?)null; + + VerifyDependencyAssemblies( + loader, + copyCount: copyCount, + []); + }); + } + + /// + /// Verify that MS.CA.EA.RazorCompiler will be loaded from the compiler directory not the + /// analyzer directory. + /// + [Theory] + [CombinatorialData] + public void AssemblyLoading_RazorCompiler2(AnalyzerTestKind kind) + { + Run(kind, static (AnalyzerAssemblyLoader loader, AssemblyLoadTestFixture testFixture) => + { + using var temp = new TempRoot(); + var tempDir = temp.CreateDirectory(); + + var externalAccessRazorPath = typeof(Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.GeneratorExtensions).Assembly.Location; + var dir = tempDir.CreateDirectory("a"); + var alternatePath = dir.CreateFile("Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.dll").CopyContentFrom(externalAccessRazorPath).Path; + var deltaFile = dir.CreateFile("Delta.dll").CopyContentFrom(testFixture.Delta1).Path; + + loader.AddDependencyLocation(alternatePath); + loader.AddDependencyLocation(deltaFile); + Assembly razorAssembly = loader.LoadFromPath(alternatePath); + _ = loader.LoadFromPath(deltaFile); + + Assert.Equal(externalAccessRazorPath, razorAssembly.Location); + + // Even though EA.RazorCompiler is loaded from the compiler directory the shadow copy loader + // still does a defensive copy. + var copyCount = loader is ShadowCopyAnalyzerAssemblyLoader + ? 2 + : (int?)null; + VerifyDependencyAssemblies( + loader, + copyCount: copyCount, + deltaFile); + }); + } + +#endif + /// /// Similar to except want to validate /// a dependency in the same directory is preferred over one in a different directory. diff --git a/src/Compilers/Core/CodeAnalysisTest/Microsoft.CodeAnalysis.UnitTests.csproj b/src/Compilers/Core/CodeAnalysisTest/Microsoft.CodeAnalysis.UnitTests.csproj index e80335a1d132f..5cd86acd69fc0 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Microsoft.CodeAnalysis.UnitTests.csproj +++ b/src/Compilers/Core/CodeAnalysisTest/Microsoft.CodeAnalysis.UnitTests.csproj @@ -23,6 +23,7 @@ + diff --git a/src/Compilers/Server/VBCSCompiler/VBCSCompilerCommandLine.projitems b/src/Compilers/Server/VBCSCompiler/VBCSCompilerCommandLine.projitems index 851b618b90dba..25e47648faab4 100644 --- a/src/Compilers/Server/VBCSCompiler/VBCSCompilerCommandLine.projitems +++ b/src/Compilers/Server/VBCSCompiler/VBCSCompilerCommandLine.projitems @@ -56,6 +56,7 @@ + diff --git a/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj b/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj index bdfcfbef906ef..d9938a752fd05 100644 --- a/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj +++ b/src/Compilers/Test/Core/Microsoft.CodeAnalysis.Test.Utilities.csproj @@ -66,6 +66,7 @@ + diff --git a/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj b/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj index c332e5d4851d8..6e56556faaccf 100644 --- a/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj +++ b/src/Compilers/Test/Utilities/CSharp/Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj @@ -32,6 +32,7 @@ + diff --git a/src/Compilers/VisualBasic/vbc/VbcCommandLine.projitems b/src/Compilers/VisualBasic/vbc/VbcCommandLine.projitems index d1729cd816e1c..a85e09f46fdde 100644 --- a/src/Compilers/VisualBasic/vbc/VbcCommandLine.projitems +++ b/src/Compilers/VisualBasic/vbc/VbcCommandLine.projitems @@ -36,6 +36,7 @@ + diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj index b628f743b2ed0..cc877c4cc5a8e 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj @@ -69,6 +69,9 @@ + + + diff --git a/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj b/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj index 20ba57b5f5573..0d3924a25d6f6 100644 --- a/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj +++ b/src/Features/Lsif/Generator/Microsoft.CodeAnalysis.LanguageServerIndexFormat.Generator.csproj @@ -86,6 +86,11 @@ + + + diff --git a/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets b/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets index aa85224f576fa..7008b7b87c2f6 100644 --- a/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets +++ b/src/NuGet/Microsoft.Net.Compilers.Toolset/DesktopCompilerArtifacts.targets @@ -33,6 +33,7 @@ + diff --git a/src/NuGet/VS.Tools.Roslyn.Package/VS.Tools.Roslyn.Package.csproj b/src/NuGet/VS.Tools.Roslyn.Package/VS.Tools.Roslyn.Package.csproj index a2cd0a4560532..5a7283350c3c1 100644 --- a/src/NuGet/VS.Tools.Roslyn.Package/VS.Tools.Roslyn.Package.csproj +++ b/src/NuGet/VS.Tools.Roslyn.Package/VS.Tools.Roslyn.Package.csproj @@ -26,6 +26,7 @@ + diff --git a/src/Tools/BuildBoss/CompilerNuGetCheckerUtil.cs b/src/Tools/BuildBoss/CompilerNuGetCheckerUtil.cs index 95268daf87b17..23717503f643f 100644 --- a/src/Tools/BuildBoss/CompilerNuGetCheckerUtil.cs +++ b/src/Tools/BuildBoss/CompilerNuGetCheckerUtil.cs @@ -178,7 +178,9 @@ private bool CheckPackages(TextWriter textWriter) allGood &= VerifyPackageCore( textWriter, FindNuGetPackage(Path.Combine(ArtifactsDirectory, "packages", Configuration, "Shipping"), "Microsoft.Net.Compilers.Toolset"), - excludeFunc: relativeFileName => relativeFileName.StartsWith(@"tasks\netcore\bincore\Microsoft.DiaSymReader.Native", PathComparison), + excludeFunc: relativeFileName => + relativeFileName.StartsWith(@"tasks\netcore\bincore\Microsoft.DiaSymReader.Native", PathComparison) || + relativeFileName.StartsWith(@"tasks\netcore\bincore\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.dll", PathComparison), (@"tasks\net472", GetProjectOutputDirectory("csc", "net472")), (@"tasks\net472", GetProjectOutputDirectory("vbc", "net472")), (@"tasks\net472", GetProjectOutputDirectory("csi", "net472")), diff --git a/src/Tools/ExternalAccess/RazorCompiler/GeneratorExtensions.cs b/src/Tools/ExternalAccess/RazorCompiler/GeneratorExtensions.cs new file mode 100644 index 0000000000000..bc7d9f43af7be --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompiler/GeneratorExtensions.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Threading; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler +{ + internal static partial class GeneratorExtensions + { + public static void RegisterHostOutput(ref this IncrementalGeneratorInitializationContext @this, IncrementalValuesProvider source, Action action) + { + _ = @this; + source.Node.RegisterOutput(new HostOutputNode(source.Node, action)); + } + + public static ImmutableArray<(string Key, string Value)> GetHostOutputs(this GeneratorRunResult runResult) => runResult.HostOutputs; + } + + internal readonly struct HostProductionContext + { + internal readonly ArrayBuilder<(string, string)> Outputs; + + internal HostProductionContext(ArrayBuilder<(string, string)> outputs) + { + Outputs = outputs; + } + + public void AddOutput(string name, string value) => Outputs.Add((name, value)); + } +} diff --git a/src/Tools/ExternalAccess/RazorCompiler/HostOutputNode.cs b/src/Tools/ExternalAccess/RazorCompiler/HostOutputNode.cs new file mode 100644 index 0000000000000..3ae1b7dcd296e --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompiler/HostOutputNode.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; +using TOutput = System.Collections.Immutable.ImmutableArray<(string, string)>; + +namespace Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler +{ + internal sealed class HostOutputNode : IIncrementalGeneratorOutputNode, IIncrementalGeneratorNode + { + private readonly IIncrementalGeneratorNode _source; + + private readonly Action _action; + + public HostOutputNode(IIncrementalGeneratorNode source, Action action) + { + _source = source; + _action = action; + } + + public IncrementalGeneratorOutputKind Kind => GeneratorDriver.HostKind; + + public NodeStateTable UpdateStateTable(DriverStateTable.Builder graphState, NodeStateTable? previousTable, CancellationToken cancellationToken) + { + string stepName = "HostOutput"; + var sourceTable = graphState.GetLatestStateTableForNode(_source); + if (sourceTable.IsCached && previousTable is not null) + { + if (graphState.DriverState.TrackIncrementalSteps) + { + return previousTable.CreateCachedTableWithUpdatedSteps(sourceTable, stepName, EqualityComparer.Default); + } + return previousTable; + } + + var nodeTable = graphState.CreateTableBuilder(previousTable, stepName, EqualityComparer.Default); + foreach (var entry in sourceTable) + { + var inputs = nodeTable.TrackIncrementalSteps ? ImmutableArray.Create((entry.Step!, entry.OutputIndex)) : default; + if (entry.State == EntryState.Removed) + { + nodeTable.TryRemoveEntries(TimeSpan.Zero, inputs); + } + else if (entry.State != EntryState.Cached || !nodeTable.TryUseCachedEntries(TimeSpan.Zero, inputs)) + { + ArrayBuilder<(string, string)> output = ArrayBuilder<(string, string)>.GetInstance(); + HostProductionContext context = new HostProductionContext(output); + var stopwatch = SharedStopwatch.StartNew(); + _action(context, entry.Item, cancellationToken); + nodeTable.AddEntry(output.ToImmutableAndFree(), EntryState.Added, stopwatch.Elapsed, inputs, EntryState.Added); + } + } + + return nodeTable.ToImmutableAndFree(); + } + + public void AppendOutputs(IncrementalExecutionContext context, CancellationToken cancellationToken) + { + // get our own state table + Debug.Assert(context.TableBuilder is not null); + var table = context.TableBuilder!.GetLatestStateTableForNode(this); + + // add each non-removed entry to the context + foreach (var (list, state, _, _) in table) + { + if (state != EntryState.Removed) + { + context.HostOutputBuilder.AddRange(list); + } + } + + if (context.GeneratorRunStateBuilder.RecordingExecutedSteps) + { + context.GeneratorRunStateBuilder.RecordStepsFromOutputNodeUpdate(table); + } + } + + IIncrementalGeneratorNode IIncrementalGeneratorNode.WithComparer(IEqualityComparer comparer) => throw ExceptionUtilities.Unreachable(); + + public IIncrementalGeneratorNode WithTrackingName(string name) => throw ExceptionUtilities.Unreachable(); + + void IIncrementalGeneratorNode.RegisterOutput(IIncrementalGeneratorOutputNode output) => throw ExceptionUtilities.Unreachable(); + } +} diff --git a/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Shipped.txt b/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Shipped.txt new file mode 100644 index 0000000000000..7dc5c58110bfa --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Unshipped.txt b/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Unshipped.txt new file mode 100644 index 0000000000000..7c99629a815f4 --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompiler/InternalAPI.Unshipped.txt @@ -0,0 +1,15 @@ +#nullable enable +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.GeneratorExtensions +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode.AppendOutputs(Microsoft.CodeAnalysis.IncrementalExecutionContext context, System.Threading.CancellationToken cancellationToken) -> void +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode.HostOutputNode(Microsoft.CodeAnalysis.IIncrementalGeneratorNode! source, System.Action! action) -> void +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode.Kind.get -> Microsoft.CodeAnalysis.IncrementalGeneratorOutputKind +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode.UpdateStateTable(Microsoft.CodeAnalysis.DriverStateTable.Builder! graphState, Microsoft.CodeAnalysis.NodeStateTable>? previousTable, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.NodeStateTable>! +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostOutputNode.WithTrackingName(string! name) -> Microsoft.CodeAnalysis.IIncrementalGeneratorNode>! +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostProductionContext +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostProductionContext.AddOutput(string! name, string! value) -> void +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostProductionContext.HostProductionContext() -> void +Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostProductionContext.HostProductionContext(Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<(string!, string!)>! outputs) -> void +readonly Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.HostProductionContext.Outputs -> Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<(string!, string!)>! +static Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.GeneratorExtensions.GetHostOutputs(this Microsoft.CodeAnalysis.GeneratorRunResult runResult) -> System.Collections.Immutable.ImmutableArray<(string! Key, string! Value)> +static Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.GeneratorExtensions.RegisterHostOutput(this ref Microsoft.CodeAnalysis.IncrementalGeneratorInitializationContext this, Microsoft.CodeAnalysis.IncrementalValuesProvider source, System.Action! action) -> void diff --git a/src/Tools/ExternalAccess/RazorCompiler/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.csproj b/src/Tools/ExternalAccess/RazorCompiler/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.csproj new file mode 100644 index 0000000000000..f41f08081f772 --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompiler/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.csproj @@ -0,0 +1,46 @@ + + + + + Library + Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler + $(NetRoslynSourceBuild);netstandard2.0 + + + false + + + true + Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler + + A supporting package for Razor source generator: + https://github.com/dotnet/razor + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Tools/ExternalAccess/RazorCompiler/PublicAPI.Shipped.txt b/src/Tools/ExternalAccess/RazorCompiler/PublicAPI.Shipped.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Tools/ExternalAccess/RazorCompiler/PublicAPI.Unshipped.txt b/src/Tools/ExternalAccess/RazorCompiler/PublicAPI.Unshipped.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Tools/ExternalAccess/RazorCompilerTest/HostOutputsTests.cs b/src/Tools/ExternalAccess/RazorCompilerTest/HostOutputsTests.cs new file mode 100644 index 0000000000000..ac6da1b1b9d6a --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompilerTest/HostOutputsTests.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.CSharp.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities.TestGenerators; +using Xunit; + +namespace Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests +{ + public class HostOutputsTests : CSharpTestBase + { + [Fact] + public void Added() + { + var source = """ + class C { } + """; + var parseOptions = TestOptions.Regular; + var compilation = CreateCompilation(source, options: TestOptions.DebugDllThrowing, parseOptions: parseOptions); + compilation.VerifyDiagnostics(); + + Assert.Single(compilation.SyntaxTrees); + + var generator = new PipelineCallbackGenerator(ctx => + { + var syntaxProvider = ctx.SyntaxProvider.CreateSyntaxProvider((n, _) => n.IsKind(SyntaxKind.ClassDeclaration), (c, _) => c.Node); + + ctx.RegisterHostOutput(syntaxProvider, static (hpc, node, _) => + { + hpc.AddOutput("test", node.ToFullString()); + }); + }); + + GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator.AsSourceGenerator() }, parseOptions: parseOptions); + driver = driver.RunGenerators(compilation); + + var result = driver.GetRunResult().Results.Single(); + Assert.Empty(result.Diagnostics); + + var hostOutputs = result.GetHostOutputs(); + Assert.Equal(1, hostOutputs.Length); + Assert.Equal("test", hostOutputs[0].Key); + Assert.Equal(source, hostOutputs[0].Value); + } + } +} diff --git a/src/Tools/ExternalAccess/RazorCompilerTest/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj b/src/Tools/ExternalAccess/RazorCompilerTest/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj new file mode 100644 index 0000000000000..caa37487800e7 --- /dev/null +++ b/src/Tools/ExternalAccess/RazorCompilerTest/Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests.csproj @@ -0,0 +1,14 @@ + + + + + Library + Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.UnitTests + $(NetRoslyn);net472 + + + + + + + diff --git a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj index 5183dad27cba1..12a14f196cf15 100644 --- a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj +++ b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj @@ -92,6 +92,12 @@ true BindingRedirect + + Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler + BuiltProjectOutputGroup + true + BindingRedirect + Workspaces.Desktop BuiltProjectOutputGroup;SatelliteDllsProjectOutputGroup diff --git a/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj b/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj index 98ad23cbaab6d..9cab9ff8c290b 100644 --- a/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj +++ b/src/Workspaces/Core/MSBuild/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj @@ -41,6 +41,9 @@ true + + true + diff --git a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj index 2d85cd9ac2631..52a04fe8774d6 100644 --- a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj +++ b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj @@ -16,6 +16,7 @@ +