* Consolidate roslyn versions

We had multiple sets of roslyn references, differing between the compiler and the tooling. This consolidates those versions and updates the compiler references to be inline with the tooling.

* Filter out compiler-generated types such as RefSafetyRulesAttribute and EmbeddedAttribute.

* Update Roslyn to 4.5.0-2.23107.1

* Add reference to `ExternalAccess.RazorCompiler`

* Emit design-time outputs from the source generator

* Emit host outputs from the source generator

* Test host outputs

* Generate both design-time and runtime outputs

* Switch to implementation output

* Remove `general-testing` feed

* Update Roslyn to 4.6.0-2.23110.2

* Update Roslyn to 4.6.0-2.23113.3

* Remove blank line

* Re-do changes of this PR onto main

* Update Roslyn to 4.7.0-2.23227.6

* Skip host outputs unless opted-in

* Update Roslyn to 4.7.0-2.23253.2

---------

Co-authored-by: Fredric Silberberg <frsilb@microsoft.com>
This commit is contained in:
Jan Jones 2023-06-08 18:43:35 +02:00 коммит произвёл GitHub
Родитель b6e673c517
Коммит a0d029c1ef
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 267 добавлений и 305 удалений

Просмотреть файл

@ -41,9 +41,6 @@
-->
<packageSourceMapping>
<clear />
<packageSource key="general-testing">
<package pattern="microsoft.commonlanguageserverProtocol.*" />
</packageSource>
<packageSource key="dotnet-core-internal-tooling">
<package pattern="microsoft.*" />
</packageSource>

Просмотреть файл

@ -23,6 +23,10 @@
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>f6725f6f04ce03574fcf89faa4b20b72ef83e4dd</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler" Version="4.7.0-2.23301.2">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>f6725f6f04ce03574fcf89faa4b20b72ef83e4dd</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CSharp" Version="4.7.0-2.23301.2">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>f6725f6f04ce03574fcf89faa4b20b72ef83e4dd</Sha>

Просмотреть файл

@ -55,6 +55,7 @@
<MicrosoftNetCompilersToolsetPackageVersion>4.7.0-2.23301.2</MicrosoftNetCompilersToolsetPackageVersion>
<MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>4.7.0-2.23301.2</MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>
<MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>4.7.0-2.23301.2</MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>
<MicrosoftCodeAnalysisExternalAccessRazorCompilerPackageVersion>4.7.0-2.23301.2</MicrosoftCodeAnalysisExternalAccessRazorCompilerPackageVersion>
<MicrosoftCodeAnalysisExternalAccessOmniSharpCSharpPackageVersion>4.7.0-2.23301.2</MicrosoftCodeAnalysisExternalAccessOmniSharpCSharpPackageVersion>
<MicrosoftCodeAnalysisCommonPackageVersion>4.7.0-2.23301.2</MicrosoftCodeAnalysisCommonPackageVersion>
<MicrosoftCodeAnalysisCSharpPackageVersion>4.7.0-2.23301.2</MicrosoftCodeAnalysisCSharpPackageVersion>

Просмотреть файл

@ -11,6 +11,7 @@
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="$(MicrosoftCodeAnalysisCommonPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler" Version="$(MicrosoftCodeAnalysisExternalAccessRazorCompilerPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="$(MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion)" />
<PackageVersion Include="Microsoft.CSharp" Version="$(MicrosoftCSharpVersion)" />
<PackageVersion Include="Microsoft.Css.Parser" Version="$(MicrosoftCssParserVersion)" />

Просмотреть файл

@ -16,6 +16,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
<PackageReference Include="Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
public LanguageVersion CSharpLanguageVersion { get; set; } = LanguageVersion.CSharp10;
/// <summary>
/// Gets a flag that determines if localized component names should be supported.</c>.
/// Gets a flag that determines if localized component names should be supported.
/// </summary>
public bool SupportLocalizedComponentNames { get; set; } = false;

Просмотреть файл

@ -28,6 +28,12 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
&& suppressRazorSourceGenerator == "true";
}
private static bool GetHostOutputsEnabledStatus(AnalyzerConfigOptionsProvider optionsProvider, CancellationToken _)
{
return optionsProvider.GlobalOptions.TryGetValue("build_property.EnableRazorHostOutputs", out var enableRazorHostOutputs)
&& enableRazorHostOutputs == "true";
}
private static (RazorSourceGenerationOptions?, Diagnostic?) ComputeRazorSourceGeneratorOptions((AnalyzerConfigOptionsProvider, ParseOptions) pair, CancellationToken ct)
{
Log.ComputeRazorSourceGeneratorOptions();

Просмотреть файл

@ -9,6 +9,7 @@ using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler;
namespace Microsoft.NET.Sdk.Razor.SourceGenerators
{
@ -24,11 +25,11 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
var compilation = context.CompilationProvider;
// determine if we should suppress this run and filter out all the additional files if so
var isGeneratorSuppressed = context.AnalyzerConfigOptionsProvider.Select(GetSuppressionStatus);
var isGeneratorSuppressed = analyzerConfigOptions.Select(GetSuppressionStatus);
var additionalTexts = context.AdditionalTextsProvider
.Combine(isGeneratorSuppressed)
.Where(pair => !pair.Right)
.Select((pair, _) => pair.Left);
.Combine(isGeneratorSuppressed)
.Where(pair => !pair.Right)
.Select((pair, _) => pair.Left);
var razorSourceGeneratorOptions = analyzerConfigOptions
.Combine(parseOptions)
@ -68,7 +69,6 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
.Combine(razorSourceGeneratorOptions)
.Select(static (pair, _) =>
{
var ((sourceItem, importFiles), razorSourceGeneratorOptions) = pair;
RazorSourceGeneratorEventSource.Log.GenerateDeclarationCodeStart(sourceItem.FilePath);
@ -204,26 +204,39 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
return allTagHelpers;
});
var generatedOutput = sourceItems
var withOptions = sourceItems
.Combine(importFiles.Collect())
.Combine(allTagHelpers)
.Combine(razorSourceGeneratorOptions)
.Select(static (pair, _) =>
.Combine(razorSourceGeneratorOptions);
var withOptionsDesignTime = withOptions
.Combine(analyzerConfigOptions.Select(GetHostOutputsEnabledStatus))
.Where(pair => pair.Right)
.Select((pair, _) => pair.Left);
IncrementalValuesProvider<(string, RazorCodeDocument)> processed(bool designTime) => (designTime ? withOptionsDesignTime : withOptions)
.Select((pair, _) =>
{
var (((sourceItem, imports), allTagHelpers), razorSourceGeneratorOptions) = pair;
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStart(sourceItem.FilePath);
// Add a generated suffix so tools, such as coverlet, consider the file to be generated
var hintName = GetIdentifierFromPath(sourceItem.RelativePhysicalPath) + ".g.cs";
var kind = designTime ? "DesignTime" : "Runtime";
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStart(sourceItem.FilePath, kind);
var projectEngine = GetGenerationProjectEngine(allTagHelpers, sourceItem, imports, razorSourceGeneratorOptions);
var codeDocument = projectEngine.Process(sourceItem);
var csharpDocument = codeDocument.GetCSharpDocument();
var codeDocument = designTime
? projectEngine.ProcessDesignTime(sourceItem)
: projectEngine.Process(sourceItem);
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStop(sourceItem.FilePath);
return (hintName, csharpDocument);
RazorSourceGeneratorEventSource.Log.RazorCodeGenerateStop(sourceItem.FilePath, kind);
return (filePath: sourceItem.RelativePhysicalPath, codeDocument);
});
var csharpDocuments = processed(designTime: false)
.Select(static (pair, _) =>
{
var (filePath, document) = pair;
return (filePath, csharpDocument: document.GetCSharpDocument());
})
.WithLambdaComparer(static (a, b) =>
{
@ -236,9 +249,13 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
return string.Equals(a.csharpDocument.GeneratedCode, b.csharpDocument.GeneratedCode, StringComparison.Ordinal);
}, static a => StringComparer.Ordinal.GetHashCode(a.csharpDocument));
context.RegisterSourceOutput(generatedOutput, static (context, pair) =>
context.RegisterImplementationSourceOutput(csharpDocuments, static (context, pair) =>
{
var (hintName, csharpDocument) = pair;
var (filePath, csharpDocument) = pair;
// Add a generated suffix so tools, such as coverlet, consider the file to be generated
var hintName = GetIdentifierFromPath(filePath) + ".g.cs";
RazorSourceGeneratorEventSource.Log.AddSyntaxTrees(hintName);
for (var i = 0; i < csharpDocument.Diagnostics.Count; i++)
{
@ -249,6 +266,14 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
context.AddSource(hintName, csharpDocument.GeneratedCode);
});
context.RegisterHostOutput(processed(designTime: true), static (context, pair, _) =>
{
var (filePath, document) = pair;
var hintName = GetIdentifierFromPath(filePath);
context.AddOutput(hintName + ".rsg.cs", document.GetCSharpDocument().GeneratedCode);
context.AddOutput(hintName + ".rsg.html", document.GetHtmlDocument().GeneratedCode);
});
}
}
}

Просмотреть файл

@ -42,11 +42,11 @@ namespace Microsoft.NET.Sdk.Razor.SourceGenerators
private const int RazorCodeGenerateStartId = 10;
[Event(RazorCodeGenerateStartId, Level = EventLevel.Informational)]
public void RazorCodeGenerateStart(string file) => WriteEvent(RazorCodeGenerateStartId, file);
public void RazorCodeGenerateStart(string file, string kind) => WriteEvent(RazorCodeGenerateStartId, file, kind);
private const int RazorCodeGenerateStopId = 11;
[Event(RazorCodeGenerateStopId, Level = EventLevel.Informational)]
public void RazorCodeGenerateStop(string file) => WriteEvent(RazorCodeGenerateStopId, file);
public void RazorCodeGenerateStop(string file, string kind) => WriteEvent(RazorCodeGenerateStopId, file, kind);
private const int AddSyntaxTreesId = 12;
[Event(AddSyntaxTreesId, Level = EventLevel.Informational)]

Просмотреть файл

@ -97,6 +97,99 @@ namespace MyApp.Pages
Assert.Equal(2, result.GeneratedSources.Length);
}
[Fact]
public async Task SourceGenerator_RazorFiles_DesignTime()
{
// Arrange
var project = CreateTestProject(new()
{
["Pages/Index.razor"] = "<h1>Hello world</h1>",
});
var compilation = await project.GetCompilationAsync();
var (driver, additionalTexts, optionsProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project, hostOutputs: true);
// Enable design-time.
var options = optionsProvider.Clone();
options.TestGlobalOptions["build_property.RazorDesignTime"] = "true";
options.TestGlobalOptions["build_property.EnableRazorHostOutputs"] = "true";
var driver2 = driver.WithUpdatedAnalyzerConfigOptions(options);
var result = RunGenerator(compilation!, ref driver2);
var pageOutput =
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
#line hidden
using global::System;
using global::System.Collections.Generic;
using global::System.Linq;
using global::System.Threading.Tasks;
using global::Microsoft.AspNetCore.Components;
public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
{
#pragma warning disable 1998
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
";
result.VerifyPageOutput(pageOutput);
result.VerifyHostOutput(
(@"Pages_Index_razor.rsg.cs", @"// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
#line hidden
using global::System;
using global::System.Collections.Generic;
using global::System.Linq;
using global::System.Threading.Tasks;
using global::Microsoft.AspNetCore.Components;
public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
}
#pragma warning restore 219
#pragma warning disable 0414
private static object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591
"),
(@"Pages_Index_razor.rsg.html", @"<h1>Hello world</h1>"));
Assert.Empty(result.Diagnostics);
Assert.Single(result.GeneratedSources);
// Enable design-time without host outputs.
options = optionsProvider.Clone();
options.TestGlobalOptions["build_property.RazorDesignTime"] = "true";
driver2 = driver.WithUpdatedAnalyzerConfigOptions(options);
result = RunGenerator(compilation!, ref driver2);
result.VerifyPageOutput(pageOutput);
result.VerifyHostOutput();
Assert.Empty(result.Diagnostics);
Assert.Single(result.GeneratedSources);
}
[Fact]
public async Task SourceGeneratorEvents_RazorFiles_Works()
{
@ -164,70 +257,21 @@ namespace MyApp.Pages
Assert.Collection(eventListener.Events,
e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
e =>
{
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Index.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Index.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Index_razor.g.cs", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Counter_razor.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Counter.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Counter.razor", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
);
}
[Fact]
@ -413,36 +457,12 @@ namespace MyApp.Pages
Assert.Equal(2, result.GeneratedSources.Length);
Assert.Collection(eventListener.Events,
e =>
{
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Counter_razor.g.cs", file);
});
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Counter.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Counter.razor", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
);
}
[Fact]
@ -787,38 +807,14 @@ __builder.AddContent(3, count);
Assert.Equal(2, result.GeneratedSources.Length);
Assert.Collection(eventListener.Events,
e =>
{
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Counter_razor.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Counter.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Counter.razor", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
);
}
[Fact]
@ -967,50 +963,16 @@ __builder.AddContent(3, count);
Assert.Equal(2, result.GeneratedSources.Length);
Assert.Collection(eventListener.Events,
e =>
{
Assert.Equal("GenerateDeclarationCodeStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("GenerateDeclarationCodeStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Counter_razor.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Counter.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Counter.razor", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
);
}
[Fact]
@ -1145,36 +1107,12 @@ using SurveyPromptRootNamspace;
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Counter.razor", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Index_razor.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Index.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Counter.razor", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Counter.razor", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs")
);
// Verify caching
eventListener.Events.Clear();
@ -1330,42 +1268,13 @@ namespace AspNetCoreGeneratedDocument
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Index_cshtml.g.cs", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Views_Shared__Layout_cshtml.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Index.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Index.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStart", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs"),
e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
);
}
[Fact, WorkItem("https://github.com/dotnet/razor/issues/7049")]
@ -1693,24 +1602,10 @@ namespace AspNetCoreGeneratedDocument
Assert.Equal(2, result.GeneratedSources.Length);
Assert.Collection(eventListener.Events,
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Views_Shared__Layout_cshtml.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
);
}
[Fact]
@ -2028,36 +1923,12 @@ public class HeaderTagHelper : TagHelper
Assert.Collection(eventListener.Events,
e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Pages/Index.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStart", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("RazorCodeGenerateStop", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("/Views/Shared/_Layout.cshtml", file);
},
e =>
{
Assert.Equal("AddSyntaxTrees", e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal("Pages_Index_cshtml.g.cs", file);
});
e => e.AssertPair("RazorCodeGenerateStart", "/Pages/Index.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Pages/Index.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStart", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertPair("RazorCodeGenerateStop", "/Views/Shared/_Layout.cshtml", "Runtime"),
e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs")
);
}
[Fact]

Просмотреть файл

@ -30,6 +30,7 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
@ -56,10 +57,11 @@ public abstract class RazorSourceGeneratorTestsBase
return (result.Item1, result.Item2);
}
protected static async ValueTask<(GeneratorDriver, ImmutableArray<AdditionalText>, TestAnalyzerConfigOptionsProvider)> GetDriverWithAdditionalTextAndProviderAsync(Project project, Action<TestAnalyzerConfigOptionsProvider>? configureGlobalOptions = null)
protected static async ValueTask<(GeneratorDriver, ImmutableArray<AdditionalText>, TestAnalyzerConfigOptionsProvider)> GetDriverWithAdditionalTextAndProviderAsync(Project project, Action<TestAnalyzerConfigOptionsProvider>? configureGlobalOptions = null, bool hostOutputs = false)
{
var razorSourceGenerator = new RazorSourceGenerator().AsSourceGenerator();
var driver = (GeneratorDriver)CSharpGeneratorDriver.Create(new[] { razorSourceGenerator }, parseOptions: (CSharpParseOptions)project.ParseOptions!, driverOptions: new GeneratorDriverOptions(IncrementalGeneratorOutputKind.None, true));
var disabledOutputs = hostOutputs ? IncrementalGeneratorOutputKind.None : (IncrementalGeneratorOutputKind)0b100000;
var driver = (GeneratorDriver)CSharpGeneratorDriver.Create(new[] { razorSourceGenerator }, parseOptions: (CSharpParseOptions)project.ParseOptions!, driverOptions: new GeneratorDriverOptions(disabledOutputs, true));
var optionsProvider = new TestAnalyzerConfigOptionsProvider();
optionsProvider.TestGlobalOptions["build_property.RazorConfiguration"] = "Default";
@ -409,7 +411,7 @@ internal static class Extensions
{
if (expectedOutput.Length == 1 && string.IsNullOrWhiteSpace(expectedOutput[0]))
{
Assert.True(false, GenerateExpectedOutput(result));
Assert.True(false, GenerateExpectedPageOutput(result));
}
else
{
@ -424,6 +426,29 @@ internal static class Extensions
return result;
}
public static GeneratorRunResult VerifyHostOutput(this GeneratorRunResult result, params (string hintName, string text)[] expectedOutputs)
{
if (expectedOutputs.Length == 1 && string.IsNullOrWhiteSpace(expectedOutputs[0].text))
{
Assert.True(false, GenerateExpectedHostOutput(result));
}
else
{
var hostOutputs = result.GetHostOutputs();
Assert.Equal(expectedOutputs.Length, hostOutputs.Length);
for (int i = 0; i < hostOutputs.Length; i++)
{
var expectedOutput = expectedOutputs[i];
var actualOutput = hostOutputs[i];
Assert.Equal(expectedOutput.hintName, actualOutput.Key);
Assert.Equal(expectedOutput.text, actualOutput.Value, ignoreWhiteSpaceDifferences: true);
}
}
return result;
}
private static string CreateBaselineDirectory(string testPath, string testName)
{
var baselineDirectory = Path.Join(
@ -490,9 +515,9 @@ internal static class Extensions
}
}
private static string GenerateExpectedOutput(GeneratorRunResult result)
private static string GenerateExpectedPageOutput(GeneratorRunResult result)
{
StringBuilder sb = new StringBuilder("Generated Output:").AppendLine().AppendLine();
StringBuilder sb = new StringBuilder("Generated Page Output:").AppendLine().AppendLine();
for (int i = 0; i < result.GeneratedSources.Length; i++)
{
if (i > 0)
@ -504,6 +529,22 @@ internal static class Extensions
return sb.ToString();
}
private static string GenerateExpectedHostOutput(GeneratorRunResult result)
{
StringBuilder sb = new StringBuilder("Generated Host Output:").AppendLine().AppendLine();
var hostOutputs = result.GetHostOutputs();
for (int i = 0; i < hostOutputs.Length; i++)
{
if (i > 0)
{
sb.AppendLine(",");
}
sb.Append("(@\"").Append(hostOutputs[i].Key.Replace("\"", "\"\"")).Append("\", ");
sb.Append("@\"").Append(hostOutputs[i].Value.Replace("\"", "\"\"")).Append("\")");
}
return sb.ToString();
}
public static GeneratorRunResult VerifyOutputsMatch(this GeneratorRunResult actual, GeneratorRunResult expected, params (int index, string replacement)[] diffs)
{
Assert.Equal(actual.GeneratedSources.Length, expected.GeneratedSources.Length);
@ -532,4 +573,19 @@ internal static class Extensions
Assert.StartsWith("#pragma", trimmed);
return trimmed.Substring(trimmed.IndexOf('\n') + 1);
}
public static void AssertSingleItem(this RazorEventListener.RazorEvent e, string expectedEventName, string expectedFileName)
{
Assert.Equal(expectedEventName, e.EventName);
var file = Assert.Single(e.Payload);
Assert.Equal(expectedFileName, file);
}
public static void AssertPair(this RazorEventListener.RazorEvent e, string expectedEventName, string payload1, string payload2)
{
Assert.Equal(expectedEventName, e.EventName);
Assert.Equal(2, e.Payload.Length);
Assert.Equal(payload1, e.Payload[0]);
Assert.Equal(payload2, e.Payload[1]);
}
}